46 const char FILE_SEPARATOR =
'/';
48 size_t separatorIndex = path.rfind(FILE_SEPARATOR);
49 string fileAndExtension;
50 if (separatorIndex != string::npos)
52 dir = path.substr(0, separatorIndex + 1);
53 if (separatorIndex < path.length())
54 fileAndExtension = path.substr(separatorIndex + 1, path.length());
58 fileAndExtension = path;
61 size_t dotIndex = fileAndExtension.rfind(
".");
62 if (dotIndex != string::npos)
64 file = fileAndExtension.substr(0, dotIndex);
65 extension = fileAndExtension.substr(dotIndex + 1, fileAndExtension.length());
69 file = fileAndExtension;
142 if (directory.empty())
144 if (directory.at(directory.length()-1) !=
'/')
146 string suffix = (extension.empty() ?
"" : (
"." + extension));
147 string pathTemplate = directory + file +
"-XXXXXX" + suffix;
148 char *path = (
char *)calloc(pathTemplate.length() + 1,
sizeof(char));
149 strncpy(path, pathTemplate.c_str(), pathTemplate.length());
150 int fd = mkstemps(path, suffix.length());
152 string pathStr(path);
239 throw VuoException(
"Couldn't create directory with empty path");
244 const char FILE_SEPARATOR =
'/';
245 size_t lastNonSeparator = path.find_last_not_of(FILE_SEPARATOR);
246 if (lastNonSeparator != string::npos)
247 path.resize(lastNonSeparator + 1);
249 string parentDir, file, ext;
255 int ret = mkdir(path.c_str(), 0777);
256 int mkdirErrno = errno;
258 throw VuoException((
string(
"Couldn't create directory \"" + path +
"\": ") + strerror(mkdirErrno)).c_str());
266void VuoFileUtilities::dylibLoaded(
const struct mach_header *mh32, intptr_t vmaddr_slide)
362 string compositionDir, compositionFile, ext;
366 string parentDir, compositionDirName;
367 splitPath(compositionDir, parentDir, compositionDirName, ext);
370 string compositionBaseDir = (compositionDirName ==
"Modules" ? parentDir : compositionDir);
372 string compositionModulesDir = compositionBaseDir +
"/Modules";
375 return compositionModulesDir;
742 int i = open(fromPath.c_str(), O_RDONLY);
744 throw VuoException(
string(
"Couldn't open copy source: ") + strerror(errno) +
" — " + fromPath);
748 int o = open(toPath.c_str(), O_WRONLY | O_CREAT, s.st_mode & 0777);
752 throw VuoException(
string(
"Couldn't open copy destination: ") + strerror(errno) +
" — " + toPath);
755 int ret = fcopyfile(i, o, NULL, COPYFILE_DATA | (preserveMetadata ? COPYFILE_STAT : 0));
756 char *e = strerror(errno);
761 throw VuoException(
string(
"Couldn't copy ") + fromPath +
" to " + toPath +
": " + e);
763 VDebugLog(
"%s -> %s", fromPath.c_str(), toPath.c_str());
780 char linkDestination[PATH_MAX + 1];
781 ssize_t len = readlink(fromPath.c_str(), linkDestination, PATH_MAX);
782 linkDestination[len] = 0;
783 if (symlink(linkDestination, toPath.c_str()) == -1)
784 throw VuoException(
string(
"Couldn't copy symlink \"") + fromPath +
"\" to \"" + toPath +
"\": " + strerror(errno));
786 VDebugLog(
"%s -> %s (symlink)", fromPath.c_str(), toPath.c_str());
797 for (
auto file : files)
799 string sourceFile = fromPath +
"/" + file->getRelativePath();
800 string targetFile = toPath +
"/" + file->getRelativePath();
813 int fd = open(path.c_str(), O_RDONLY);
815 throw VuoException(
"Error: Couldn't open \"" + path +
"\": " + strerror(errno));
819 if (fstat(fd, &stat) != 0)
820 throw VuoException(
"Error: Couldn't fstat \"" + path +
"\": " + strerror(errno));
824 void *data = mmap(
nullptr, stat.st_size, PROT_READ, MAP_PRIVATE | MAP_NOCACHE, fd, 0);
825 if (data == MAP_FAILED)
826 throw VuoException(
"Error: Couldn't mmap \"" + path +
"\": " + strerror(errno));
827 VuoDefer(^{ munmap(data, stat.st_size); });
829 unsigned char hash[CC_SHA256_DIGEST_LENGTH];
830 if (!CC_SHA256(data, stat.st_size, hash))
831 throw VuoException(
"Error: CC_SHA256 failed on file \"" + path +
"\"");
834 oss << setfill(
'0') << hex;
835 for (
int i = 0; i < CC_SHA256_DIGEST_LENGTH; ++i)
836 oss << setw(2) << (int)hash[i];
889 bool shouldSearchRecursively)
897 DIR *d = opendir(dirPath.c_str());
900 if (access(dirPath.c_str(), F_OK) != -1)
901 throw VuoException(
string(
"Couldn't read directory: ") + strerror(errno) +
" — " + dirPath);
906 while( (de=readdir(d)) )
908 string fileName = de->d_name;
909 string relativeFilePath = dirPath +
"/" + fileName;
911 if (fileName ==
"." || fileName ==
"..")
914 bool isArchive =
false;
915 for (set<string>::iterator archiveExtension = archiveExtensions.begin(); archiveExtension != archiveExtensions.end(); ++archiveExtension)
925 files.insert(fs.begin(), fs.end());
930 bool shouldSearchDir = shouldSearchRecursively
936 for (set<File *>::iterator i = filesInDir.begin(); i != filesInDir.end(); ++i)
939 f->dirPath = dirPath;
940 f->filePath = fileName +
"/" + f->filePath;
942 files.insert(filesInDir.begin(), filesInDir.end());
946 File *f =
new File(dirPath, fileName);
969 set<File *> matchingFiles;
971 for (set<File *>::iterator i = allFiles.begin(); i != allFiles.end(); ++i)
973 bool endsWithExtension =
false;
974 for (set<string>::iterator extension = extensions.begin(); extension != extensions.end(); ++extension)
976 endsWithExtension =
true;
979 matchingFiles.insert(*i);
984 return matchingFiles;
1004 mz_uint numFiles = mz_zip_reader_get_num_files(archive->
zipArchive);
1005 for (mz_uint i = 0; i < numFiles; ++i)
1007 mz_zip_archive_file_stat file_stat;
1008 bool success = mz_zip_reader_file_stat(archive->
zipArchive, i, &file_stat);
1011 VUserLog(
"Error: Couldn't read file '%u' in zip archive '%s'.", i, archive->
path.c_str());
1015 File *f =
new File(archive, file_stat.m_filename);
1037 set<File *> matchingFiles;
1039 for (set<File *>::iterator i = allFiles.begin(); i != allFiles.end(); ++i)
1043 string dir, file, ext;
1047 bool endsWithExtension =
false;
1048 for (set<string>::iterator extension = extensions.begin(); extension != extensions.end(); ++extension)
1050 endsWithExtension =
true;
1052 if (beginsWithDir && endsWithExtension)
1053 matchingFiles.insert(f);
1058 return matchingFiles;
1103 vector<string> processAndArgs{
1110 if (!entitlementsPath.empty())
1112 processAndArgs.push_back(
"--entitlements");
1113 processAndArgs.push_back(entitlementsPath);
1307 string fullPath = (dirPath.empty() ?
"" : (dirPath +
"/")) + filePath;
1309 FILE *pFile = fopen ( fullPath.c_str() ,
"rb" );
1311 throw VuoException(
string(
"Couldn't open file: ") + strerror(errno) +
" — " + fullPath);
1314 fseek (pFile , 0 , SEEK_END);
1315 size_t lSize = ftell (pFile);
1319 buffer = (
char*) malloc (
sizeof(
char)*lSize);
1322 numBytes = fread (buffer,1,lSize,pFile);
1324 if (numBytes != lSize)
1327 throw VuoException(
string(
"Couldn't read file: ") + strerror(errno) +
" — " + fullPath);
1332 buffer = (
char *)mz_zip_reader_extract_file_to_heap(archive->zipArchive, filePath.c_str(), &numBytes, 0);
1417 string binaryDir, binaryFile, binaryExt;
1418 splitPath(processAndArgs[0], binaryDir, binaryFile, binaryExt);
1420 string errorPrefix =
"Couldn't execute " + binaryFile +
": ";
1424 int ret = pipe(outputPipe);
1426 throw VuoException(errorPrefix +
"couldn't open pipe: " + strerror(ret));
1427 int pipeRead = outputPipe[0];
1428 int pipeWrite = outputPipe[1];
1430 posix_spawn_file_actions_t fileActions;
1431 posix_spawn_file_actions_init(&fileActions);
1432 posix_spawn_file_actions_adddup2(&fileActions, pipeWrite, STDOUT_FILENO);
1433 posix_spawn_file_actions_adddup2(&fileActions, pipeWrite, STDERR_FILENO);
1434 posix_spawn_file_actions_addclose(&fileActions, pipeRead);
1438 char **processAndArgsZ = (
char **)malloc(
sizeof(
char *) * (processAndArgs.size() + 1));
1441 for (
auto arg : processAndArgs)
1443 processAndArgsZ[argCount++] = strdup(arg.c_str());
1446 commandLine +=
'"' + arg +
'"';
1448 processAndArgsZ[argCount] =
nullptr;
1453 char **environmentZ = (
char **)malloc(
sizeof(
char *) * (environment.size() + 1));
1454 int environmentVarCount = 0;
1455 for (
auto environmentVar : environment)
1457 environmentZ[environmentVarCount++] = strdup(environmentVar.c_str());
1458 commandLine = environmentVar +
" " + commandLine;
1460 environmentZ[environmentVarCount] =
nullptr;
1466 ret = posix_spawn(&pid, processAndArgs[0].c_str(), &fileActions, NULL, (
char *
const *)processAndArgsZ, (
char *
const *)environmentZ);
1468 posix_spawn_file_actions_destroy(&fileActions);
1469 for (
int i = 0; i < argCount; ++i)
1470 free(processAndArgsZ[i]);
1480 ret = waitpid(pid, &status, 0);
1481 if (ret == -1 && errno == EINTR)
1486 throw VuoException(errorPrefix +
"waitpid failed: " + strerror(errno));
1487 else if (status != 0)
1492 while (read(pipeRead, &buf, 255) > 0)