Vuo  2.3.2
VuoFileUtilitiesCocoa.mm
Go to the documentation of this file.
1 
10 #include "VuoFileUtilities.hh"
11 #include "VuoFileUtilitiesCocoa.hh"
12 #include "VuoException.hh"
13 #include "VuoStringUtilities.hh"
14 
15 #include <AppKit/AppKit.h>
16 #include <sys/utsname.h>
17 
24 {
25  NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:filePath.c_str()]];
26  if (!url)
27  throw VuoException("Couldn't move file '" + filePath + "' to the trash: Couldn't create NSURL.");
28 
29  NSError *error = nil;
30  bool success = [[NSFileManager defaultManager] trashItemAtURL:url resultingItemURL:nil error:&error];
31  if (!success)
32  throw VuoException(string("Couldn't move file '" + filePath + "' to the trash: ") + [[error localizedDescription] UTF8String]);
33 }
34 
46 {
47  NSString *pathNS = [NSString stringWithUTF8String:path.c_str()];
48  if (!pathNS)
49  throw VuoException("Path \"" + path + "\" isn't a valid UTF-8 string.");
50 
51  NSURL *baseURL = [NSURL fileURLWithPath:pathNS isDirectory:YES];
52  if (!baseURL)
53  throw VuoException("Path \"" + path + "\" isn't a valid directory.");
54 
55  NSURL *temporaryDirectoryURL = nil;
56  while (true)
57  {
58  NSError *error = nil;
59  temporaryDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSItemReplacementDirectory
60  inDomain:NSUserDomainMask
61  appropriateForURL:baseURL
62  create:YES
63  error:&error];
64  if (error)
65  {
66  NSError *underlyingError = [[error userInfo] objectForKey:NSUnderlyingErrorKey];
67  if ([[underlyingError domain] isEqualToString:NSPOSIXErrorDomain]
68  && [underlyingError code] == ENOENT)
69  {
70  // File not found; go up a directory and try again.
71  baseURL = [baseURL URLByDeletingLastPathComponent];
72  }
73  else
74  throw VuoException((string("Couldn't get a temp folder: ") + [[error localizedDescription] UTF8String]).c_str());
75  }
76  else if (!temporaryDirectoryURL)
77  throw VuoException("Couldn't get a temp folder for path \"" + path + "\".");
78  else
79  break;
80  }
81 
82  return [[temporaryDirectoryURL path] UTF8String];
83 }
84 
93 {
94  NSString *pathNS = [NSString stringWithUTF8String:path.c_str()];
95  if (!pathNS)
96  throw VuoException("Path \"" + path + "\" isn't a valid UTF-8 string.");
97 
98  NSDictionary *fileAttributes;
99  while (true)
100  {
101  NSError *error = nil;
102  fileAttributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:pathNS error:&error];
103  if (error)
104  {
105  NSError *underlyingError = [[error userInfo] objectForKey:NSUnderlyingErrorKey];
106  if ([[underlyingError domain] isEqualToString:NSPOSIXErrorDomain]
107  && [underlyingError code] == ENOENT)
108  {
109  // File not found; go up a directory and try again.
110  pathNS = [pathNS stringByDeletingLastPathComponent];
111  }
112  else
113  throw VuoException((string("Couldn't get information about path: ") + [[error localizedDescription] UTF8String]).c_str());
114  }
115  else if (!fileAttributes)
116  throw VuoException("Couldn't get information about path \"" + path + "\".");
117  else
118  break;
119  }
120 
121  unsigned long long freeSpace = [fileAttributes[NSFileSystemFreeSize] longLongValue];
122  return freeSpace;
123 }
124 
130 void VuoFileUtilitiesCocoa_focusProcess(pid_t pid, bool force)
131 {
132  NSRunningApplication *compositionApp = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
133  [compositionApp activateWithOptions: NSApplicationActivateAllWindows
134  | (force ? NSApplicationActivateIgnoringOtherApps : 0)];
135 }
136 
141 {
142  return NSProcessInfo.processInfo.operatingSystemVersion.majorVersion;
143 }
144 
149 {
150  return NSProcessInfo.processInfo.operatingSystemVersion.minorVersion;
151 }
152 
157 {
158  struct utsname un;
159  if (uname(&un) < 0)
160  throw VuoException("Couldn't look up the system's architecture: %s", strerror(errno));
161 
162  return un.machine;
163 }
164 
169 void VuoFileUtilitiesCocoa_setBundle(string filePath)
170 {
171  CFStringRef path = CFStringCreateWithCString(NULL, filePath.c_str(), kCFStringEncodingUTF8);
172  CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, true);
173  CFErrorRef error;
174  if (!CFURLSetResourcePropertyForKey(url, kCFURLIsPackageKey, kCFBooleanTrue, &error))
175  {
176  CFStringRef errorString = CFErrorCopyDescription(error);
177  VUserLog("Warning: Couldn't set kCFURLIsPackageKey on this bundle: %s", VuoStringUtilities::makeFromCFString(errorString).c_str());
178  CFRelease(errorString);
179  }
180  CFRelease(url);
181  CFRelease(path);
182 }
183 
187 static CFURLRef VuoFileUtilitiesCocoa_getCFURL(const string &path)
188 {
189  if (path.empty())
190  return nullptr;
191 
192  CFStringRef cfpath = CFStringCreateWithCString(nullptr, path.c_str(), kCFStringEncodingUTF8);
193  if (!cfpath)
194  throw VuoException("Path \"" + path + "\" isn't a valid UTF-8 string.");
195  VuoDefer(^{ CFRelease(cfpath); });
196 
197  CFURLRef url = CFURLCreateWithFileSystemPath(nullptr, cfpath, kCFURLPOSIXPathStyle, true);
198  if (!url)
199  throw VuoException("Path \"" + path + "\" isn't a valid POSIX path.");
200 
201  return url;
202 }
203 
207 static CFDataRef VuoFileUtilitiesCocoa_getMacAliasData(const string &path)
208 {
209  CFURLRef url = VuoFileUtilitiesCocoa_getCFURL(path);
210  if (!url)
211  return nullptr;
212  VuoDefer(^{ CFRelease(url); });
213 
214  return CFURLCreateBookmarkDataFromFile(nullptr, url, nullptr);
215 }
216 
222 bool VuoFileUtilitiesCocoa_isMacAlias(const string &path)
223 {
224  CFDataRef aliasData = VuoFileUtilitiesCocoa_getMacAliasData(path);
225  if (!aliasData)
226  return false;
227 
228  CFRelease(aliasData);
229  return true;
230 }
231 
237 string VuoFileUtilitiesCocoa_resolveMacAlias(const string &path)
238 {
239  CFDataRef aliasData = VuoFileUtilitiesCocoa_getMacAliasData(path);
240  if (!aliasData)
241  throw VuoException("Path \"" + path + "\" isn't a macOS Alias.");
242  VuoDefer(^{ CFRelease(aliasData); });
243 
244  CFURLRef url = VuoFileUtilitiesCocoa_getCFURL(path);
245  VuoDefer(^{ CFRelease(url); });
246 
247  Boolean isStale = false;
248  CFErrorRef error = nullptr;
249  CFURLRef resolvedURL = CFURLCreateByResolvingBookmarkData(nullptr, aliasData, kCFBookmarkResolutionWithoutUIMask, url, nullptr, &isStale, &error);
250  if (!resolvedURL)
251  {
252  CFStringRef desc = CFErrorCopyDescription(error);
253  VuoDefer(^{ CFRelease(desc); });
254  throw VuoException("Path \"" + path + "\" is a macOS Alias, but it couldn't be resolved: \"" + VuoStringUtilities::makeFromCFString(desc) + "\" (isStale=" + std::to_string(isStale) + ")");
255  }
256  VuoDefer(^{ CFRelease(resolvedURL); });
257 
258  CFStringRef resolvedPath = CFURLCopyFileSystemPath(resolvedURL, kCFURLPOSIXPathStyle);
259  if (!resolvedPath)
260  throw VuoException("Path \"" + path + "\" is a macOS Alias, but it resolved to something that isn't a POSIX path (\"" + VuoStringUtilities::makeFromCFString(((NSURL *)resolvedURL).description) + "\").");
261  VuoDefer(^{ CFRelease(resolvedPath); });
262 
263  return VuoStringUtilities::makeFromCFString(resolvedPath);
264 }