X-Git-Url: https://git.saurik.com/apple/dyld.git/blobdiff_plain/842490583351ae7f965714913a51f32fbde2867b..6cae9b637796eb548e85897ce8a2a058bb5799cf:/dyld3/shared-cache/dyld_shared_cache_builder.mm?ds=sidebyside diff --git a/dyld3/shared-cache/dyld_shared_cache_builder.mm b/dyld3/shared-cache/dyld_shared_cache_builder.mm index cbedce2..b3a1262 100644 --- a/dyld3/shared-cache/dyld_shared_cache_builder.mm +++ b/dyld3/shared-cache/dyld_shared_cache_builder.mm @@ -63,8 +63,9 @@ #include "DyldSharedCache.h" #include "BuilderUtils.h" #include "FileUtils.h" +#include "JSONWriter.h" #include "StringUtils.h" -#include "MachOParser.h" +#include "mrm_shared_cache_builder.h" #if !__has_feature(objc_arc) #error The use of libdispatch in this files requires it to be compiled with ARC in order to avoid leaks @@ -74,9 +75,6 @@ extern char** environ; static dispatch_queue_t build_queue; -static const char* tempRootDirTemplate = "/tmp/dyld_shared_cache_builder.XXXXXX"; -static char* tempRootDir = nullptr; - int runCommandAndWait(Diagnostics& diags, const char* args[]) { pid_t pid; @@ -99,7 +97,7 @@ int runCommandAndWait(Diagnostics& diags, const char* args[]) return res; } -void processRoots(Diagnostics& diags, std::set& roots) +void processRoots(Diagnostics& diags, std::set& roots, const char *tempRootsDir) { std::set processedRoots; struct stat sb; @@ -110,9 +108,16 @@ void processRoots(Diagnostics& diags, std::set& roots) res = stat(root.c_str(), &sb); if (res == 0 && S_ISDIR(sb.st_mode)) { - roots.insert(root); - return; - } else if (endsWith(root, ".cpio") || endsWith(root, ".cpio.gz") || endsWith(root, ".cpgz") || endsWith(root, ".cpio.bz2") || endsWith(root, ".cpbz2") || endsWith(root, ".pax") || endsWith(root, ".pax.gz") || endsWith(root, ".pgz") || endsWith(root, ".pax.bz2") || endsWith(root, ".pbz2")) { + processedRoots.insert(root); + continue; + } + + char tempRootDir[MAXPATHLEN]; + strlcpy(tempRootDir, tempRootsDir, MAXPATHLEN); + strlcat(tempRootDir, "/XXXXXXXX", MAXPATHLEN); + mkdtemp(tempRootDir); + + if (endsWith(root, ".cpio") || endsWith(root, ".cpio.gz") || endsWith(root, ".cpgz") || endsWith(root, ".cpio.bz2") || endsWith(root, ".cpbz2") || endsWith(root, ".pax") || endsWith(root, ".pax.gz") || endsWith(root, ".pgz") || endsWith(root, ".pax.bz2") || endsWith(root, ".pbz2")) { args[0] = (char*)"/usr/bin/ditto"; args[1] = (char*)"-x"; args[2] = (char*)root.c_str(); @@ -176,6 +181,7 @@ void processRoots(Diagnostics& diags, std::set& roots) bool writeRootList(const std::string& dstRoot, const std::set& roots) { + mkpath_np(dstRoot.c_str(), 0755); if (roots.size() == 0) return false; @@ -192,35 +198,109 @@ bool writeRootList(const std::string& dstRoot, const std::set& root return true; } -std::set cachePaths; - -BOMCopierCopyOperation filteredCopy(BOMCopier copier, const char* path, BOMFSObjType type, off_t size) +BOMCopierCopyOperation filteredCopyExcludingPaths(BOMCopier copier, const char* path, BOMFSObjType type, off_t size) { std::string absolutePath = &path[1]; - if (cachePaths.count(absolutePath)) { + void *userData = BOMCopierUserData(copier); + std::set *cachePaths = (std::set*)userData; + if (cachePaths->count(absolutePath)) { return BOMCopierSkipFile; } return BOMCopierContinue; } +BOMCopierCopyOperation filteredCopyIncludingPaths(BOMCopier copier, const char* path, BOMFSObjType type, off_t size) +{ + std::string absolutePath = &path[1]; + void *userData = BOMCopierUserData(copier); + std::set *cachePaths = (std::set*)userData; + for (const std::string& cachePath : *cachePaths) { + if (startsWith(cachePath, absolutePath)) + return BOMCopierContinue; + } + if (cachePaths->count(absolutePath)) { + return BOMCopierContinue; + } + return BOMCopierSkipFile; +} + +static std::string dispositionToString(Disposition disposition) { + switch (disposition) { + case Unknown: + return "Unknown"; + case InternalDevelopment: + return "InternalDevelopment"; + case Customer: + return "Customer"; + case InternalMinDevelopment: + return "InternalMinDevelopment"; + } +} + +static std::string platformToString(Platform platform) { + switch (platform) { + case unknown: + return "unknown"; + case macOS: + return "macOS"; + case iOS: + return "iOS"; + case tvOS: + return "tvOS"; + case watchOS: + return "watchOS"; + case bridgeOS: + return "bridgeOS"; + case iOSMac: + return "iOSMac"; + case iOS_simulator: + return "iOS_simulator"; + case tvOS_simulator: + return "tvOS_simulator"; + case watchOS_simulator: + return "watchOS_simulator"; + } +} + +static dyld3::json::Node getBuildOptionsNode(BuildOptions_v1 buildOptions) { + dyld3::json::Node buildOptionsNode; + buildOptionsNode.map["version"].value = dyld3::json::decimal(buildOptions.version); + buildOptionsNode.map["updateName"].value = buildOptions.updateName; + buildOptionsNode.map["deviceName"].value = buildOptions.deviceName; + buildOptionsNode.map["disposition"].value = dispositionToString(buildOptions.disposition); + buildOptionsNode.map["platform"].value = platformToString(buildOptions.platform); + for (unsigned i = 0; i != buildOptions.numArchs; ++i) { + dyld3::json::Node archNode; + archNode.value = buildOptions.archs[i]; + buildOptionsNode.map["archs"].array.push_back(archNode); + } + buildOptionsNode.map["verboseDiagnostics"].value = buildOptions.verboseDiagnostics ? "true" : "false"; + return buildOptionsNode; +} + int main(int argc, const char* argv[]) { @autoreleasepool { __block Diagnostics diags; std::set roots; std::string dylibCacheDir; + std::string artifactDir; std::string release; bool emitDevCaches = true; bool emitElidedDylibs = true; bool listConfigs = false; bool copyRoots = false; bool debug = false; + bool useMRM = false; std::string dstRoot; + std::string emitJSONPath; std::string configuration; std::string resultPath; + std::string baselineDifferenceResultPath; + bool baselineCopyRoots = false; + char* tempRootsDir = strdup("/tmp/dyld_shared_cache_builder.XXXXXX"); - tempRootDir = strdup(tempRootDirTemplate); - mkdtemp(tempRootDir); + mkdtemp(tempRootsDir); for (int i = 1; i < argc; ++i) { const char* arg = argv[i]; @@ -236,6 +316,8 @@ int main(int argc, const char* argv[]) copyRoots = true; } else if (strcmp(arg, "-dylib_cache") == 0) { dylibCacheDir = realPath(argv[++i]); + } else if (strcmp(arg, "-artifact") == 0) { + artifactDir = realPath(argv[++i]); } else if (strcmp(arg, "-no_development_cache") == 0) { emitDevCaches = false; } else if (strcmp(arg, "-no_overflow_dylibs") == 0) { @@ -244,19 +326,29 @@ int main(int argc, const char* argv[]) emitDevCaches = true; } else if (strcmp(arg, "-overflow_dylibs") == 0) { emitElidedDylibs = true; + } else if (strcmp(arg, "-mrm") == 0) { + useMRM = true; + } else if (strcmp(arg, "-emit_json") == 0) { + emitJSONPath = realPath(argv[++i]); } else if (strcmp(arg, "-dst_root") == 0) { dstRoot = realPath(argv[++i]); } else if (strcmp(arg, "-release") == 0) { release = argv[++i]; } else if (strcmp(arg, "-results") == 0) { resultPath = realPath(argv[++i]); + } else if (strcmp(arg, "-baseline_diff_results") == 0) { + baselineDifferenceResultPath = realPath(argv[++i]); + } else if (strcmp(arg, "-baseline_copy_roots") == 0) { + baselineCopyRoots = true; } else { //usage(); - diags.error("unknown option: %s\n", arg); + fprintf(stderr, "unknown option: %s\n", arg); + exit(-1); } } else { if (!configuration.empty()) { - diags.error("You may only specify one configuration"); + fprintf(stderr, "You may only specify one configuration\n"); + exit(-1); } configuration = argv[i]; } @@ -264,16 +356,20 @@ int main(int argc, const char* argv[]) time_t mytime = time(0); fprintf(stderr, "Started: %s", asctime(localtime(&mytime))); - processRoots(diags, roots); + writeRootList(dstRoot, roots); + processRoots(diags, roots, tempRootsDir); struct rlimit rl = { OPEN_MAX, OPEN_MAX }; (void)setrlimit(RLIMIT_NOFILE, &rl); - if (dylibCacheDir.empty() && release.empty()) { - fprintf(stderr, "you must specify either -dylib_cache or -release"); + if (dylibCacheDir.empty() && artifactDir.empty() && release.empty()) { + fprintf(stderr, "you must specify either -dylib_cache, -artifact or -release\n"); exit(-1); } else if (!dylibCacheDir.empty() && !release.empty()) { - fprintf(stderr, "you may not use -dylib_cache and -release at the same time"); + fprintf(stderr, "you may not use -dylib_cache and -release at the same time\n"); + exit(-1); + } else if (!dylibCacheDir.empty() && !artifactDir.empty()) { + fprintf(stderr, "you may not use -dylib_cache and -artifact at the same time\n"); exit(-1); } @@ -282,6 +378,49 @@ int main(int argc, const char* argv[]) exit(-1); } + if (!baselineDifferenceResultPath.empty() && (roots.size() > 1)) { + fprintf(stderr, "Cannot use -baseline_diff_results with more that one -root\n"); + exit(-1); + } + + if (!artifactDir.empty()) { + // Find the dylib cache dir from inside the artifact dir + struct stat stat_buf; + if (stat(artifactDir.c_str(), &stat_buf) != 0) { + fprintf(stderr, "Could not find artifact path '%s'\n", artifactDir.c_str()); + exit(-1); + } + std::string dir = artifactDir + "/AppleInternal/Developer/DylibCaches"; + if (stat(dir.c_str(), &stat_buf) != 0) { + fprintf(stderr, "Could not find artifact path '%s'\n", dir.c_str()); + exit(-1); + } + + if (!release.empty()) { + // Use the given release + dylibCacheDir = dir + "/" + release + ".dlc"; + } else { + // Find a release directory + __block std::vector subDirectories; + iterateDirectoryTree("", dir, ^(const std::string& dirPath) { + subDirectories.push_back(dirPath); + return false; + }, nullptr, false, false); + + if (subDirectories.empty()) { + fprintf(stderr, "Could not find dlc subdirectories inside '%s'\n", dir.c_str()); + exit(-1); + } + + if (subDirectories.size() > 1) { + fprintf(stderr, "Found too many subdirectories inside artifact path '%s'. Use -release to select one\n", dir.c_str()); + exit(-1); + } + + dylibCacheDir = subDirectories.front(); + } + } + if (dylibCacheDir.empty()) { dylibCacheDir = std::string("/AppleInternal/Developer/DylibCaches/") + release + ".dlc"; } @@ -290,7 +429,10 @@ int main(int argc, const char* argv[]) chdir(dylibCacheDir.c_str()); dispatch_async(dispatch_get_main_queue(), ^{ - auto manifest = dyld3::Manifest(diags, dylibCacheDir + "/Manifest.plist", roots); + // If we only want a list of configuations, then tell the manifest to only parse the data and not + // actually get all the macho's. + bool onlyParseManifest = listConfigs && configuration.empty(); + auto manifest = dyld3::Manifest(diags, dylibCacheDir + "/Manifest.plist", roots, onlyParseManifest); if (manifest.build().empty()) { fprintf(stderr, "No manifest found at '%s/Manifest.plist'\n", dylibCacheDir.c_str()); @@ -302,6 +444,9 @@ int main(int argc, const char* argv[]) manifest.forEachConfiguration([](const std::string& configName) { printf("%s\n", configName.c_str()); }); + // If we weren't passed a configuration then exit + if (configuration.empty()) + exit(0); } if (!manifest.filterForConfig(configuration)) { @@ -309,51 +454,327 @@ int main(int argc, const char* argv[]) configuration.c_str(), manifest.build().c_str()); exit(-1); } - manifest.calculateClosure(); - std::vector buildQueue; + (void)mkpath_np((dstRoot + "/System/Library/Caches/com.apple.dyld/").c_str(), 0755); + bool cacheBuildSuccess = false; + if (useMRM) { + + FILE* jsonFile = nullptr; + if (!emitJSONPath.empty()) { + jsonFile = fopen(emitJSONPath.c_str(), "w"); + if (!jsonFile) { + diags.verbose("can't open file '%s', errno=%d\n", emitJSONPath.c_str(), errno); + return; + } + } + dyld3::json::Node buildInvocationNode; + + // Find the archs for the configuration we want. + __block std::set validArchs; + manifest.configuration(configuration).forEachArchitecture(^(const std::string& path) { + validArchs.insert(path); + }); + + if (validArchs.size() != 1) { + fprintf(stderr, "MRM doesn't support more than one arch per configuration: %s\n", + configuration.c_str()); + exit(-1); + } + + const char* archs[validArchs.size()]; + uint64_t archIndex = 0; + for (const std::string& arch : validArchs) { + archs[archIndex++] = arch.c_str(); + } + + BuildOptions_v1 buildOptions; + buildOptions.version = 1; + buildOptions.updateName = manifest.build().c_str(); + buildOptions.deviceName = configuration.c_str(); + buildOptions.disposition = Disposition::Unknown; + buildOptions.platform = (Platform)manifest.platform(); + buildOptions.archs = archs; + buildOptions.numArchs = validArchs.size(); + buildOptions.verboseDiagnostics = debug; + buildOptions.isLocallyBuiltCache = true; + + __block struct SharedCacheBuilder* sharedCacheBuilder = createSharedCacheBuilder(&buildOptions); + buildInvocationNode.map["build-options"] = getBuildOptionsNode(buildOptions); + + std::set requiredBinaries = { + "/usr/lib/libSystem.B.dylib" + }; + + // Get the file data for every MachO in the BOM. + __block dyld3::json::Node filesNode; + __block std::vector> mappedFiles; + manifest.forEachMachO(configuration, ^(const std::string &buildPath, const std::string &runtimePath, const std::string &arch, bool shouldBeExcludedIfLeaf) { + + // Filter based on arch as the Manifest adds the file once for each UUID. + if (!validArchs.count(arch)) + return; + + struct stat stat_buf; + int fd = ::open(buildPath.c_str(), O_RDONLY, 0); + if (fd == -1) { + diags.verbose("can't open file '%s', errno=%d\n", buildPath.c_str(), errno); + return; + } + + if (fstat(fd, &stat_buf) == -1) { + diags.verbose("can't stat open file '%s', errno=%d\n", buildPath.c_str(), errno); + ::close(fd); + return; + } + + const void* buffer = mmap(NULL, (size_t)stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (buffer == MAP_FAILED) { + diags.verbose("mmap() for file at %s failed, errno=%d\n", buildPath.c_str(), errno); + ::close(fd); + } + ::close(fd); + + mappedFiles.emplace_back(buffer, (size_t)stat_buf.st_size); + FileFlags fileFlags = FileFlags::NoFlags; + if (requiredBinaries.count(runtimePath)) + fileFlags = FileFlags::RequiredClosure; + addFile(sharedCacheBuilder, runtimePath.c_str(), (uint8_t*)buffer, (size_t)stat_buf.st_size, fileFlags); + + dyld3::json::Node fileNode; + fileNode.map["path"].value = runtimePath; + fileNode.map["flags"].value = "NoFlags"; + filesNode.array.push_back(fileNode); + }); + + __block dyld3::json::Node symlinksNode; + manifest.forEachSymlink(configuration, ^(const std::string &fromPath, const std::string &toPath) { + addSymlink(sharedCacheBuilder, fromPath.c_str(), toPath.c_str()); + + dyld3::json::Node symlinkNode; + symlinkNode.map["from-path"].value = fromPath; + symlinkNode.map["to-path"].value = toPath; + symlinksNode.array.push_back(symlinkNode); + }); + + buildInvocationNode.map["symlinks"] = symlinksNode; + + std::string orderFileData; + if (!manifest.dylibOrderFile().empty()) { + orderFileData = loadOrderFile(manifest.dylibOrderFile()); + if (!orderFileData.empty()) { + addFile(sharedCacheBuilder, "*order file data*", (uint8_t*)orderFileData.data(), orderFileData.size(), FileFlags::DylibOrderFile); + dyld3::json::Node fileNode; + fileNode.map["path"].value = manifest.dylibOrderFile(); + fileNode.map["flags"].value = "DylibOrderFile"; + filesNode.array.push_back(fileNode); + } + } + + std::string dirtyDataOrderFileData; + if (!manifest.dirtyDataOrderFile().empty()) { + dirtyDataOrderFileData = loadOrderFile(manifest.dirtyDataOrderFile()); + if (!dirtyDataOrderFileData.empty()) { + addFile(sharedCacheBuilder, "*dirty data order file data*", (uint8_t*)dirtyDataOrderFileData.data(), dirtyDataOrderFileData.size(), FileFlags::DirtyDataOrderFile); + dyld3::json::Node fileNode; + fileNode.map["path"].value = manifest.dirtyDataOrderFile(); + fileNode.map["flags"].value = "DirtyDataOrderFile"; + filesNode.array.push_back(fileNode); + } + } + + buildInvocationNode.map["files"] = filesNode; + + if (jsonFile) { + dyld3::json::printJSON(buildInvocationNode, 0, jsonFile); + fclose(jsonFile); + jsonFile = nullptr; + } + + cacheBuildSuccess = runSharedCacheBuilder(sharedCacheBuilder); + + if (!cacheBuildSuccess) { + for (uint64 i = 0, e = getErrorCount(sharedCacheBuilder); i != e; ++i) { + const char* errorMessage = getError(sharedCacheBuilder, i); + fprintf(stderr, "ERROR: %s\n", errorMessage); + } + } + + // Now emit each cache we generated, or the errors for them. + for (uint64 i = 0, e = getCacheResultCount(sharedCacheBuilder); i != e; ++i) { + BuildResult result; + getCacheResult(sharedCacheBuilder, i, &result); + if (result.numErrors) { + for (uint64_t errorIndex = 0; errorIndex != result.numErrors; ++errorIndex) { + fprintf(stderr, "[%s] ERROR: %s\n", result.loggingPrefix, result.errors[errorIndex]); + } + cacheBuildSuccess = false; + continue; + } + if (result.numWarnings) { + for (uint64_t warningIndex = 0; warningIndex != result.numWarnings; ++warningIndex) { + fprintf(stderr, "[%s] WARNING: %s\n", result.loggingPrefix, result.warnings[warningIndex]); + } + } + } + + // If we built caches, then write everything out. + // TODO: Decide if we should we write any good caches anyway? + if (cacheBuildSuccess) { + for (uint64 i = 0, e = getFileResultCount(sharedCacheBuilder); i != e; ++i) { + FileResult result; + getFileResult(sharedCacheBuilder, i, &result); + + if (!result.data) + continue; + + const std::string path = dstRoot + result.path; + std::string pathTemplate = path + "-XXXXXX"; + size_t templateLen = strlen(pathTemplate.c_str())+2; + char pathTemplateSpace[templateLen]; + strlcpy(pathTemplateSpace, pathTemplate.c_str(), templateLen); + int fd = mkstemp(pathTemplateSpace); + if ( fd != -1 ) { + ::ftruncate(fd, result.size); + uint64_t writtenSize = pwrite(fd, result.data, result.size, 0); + if ( writtenSize == result.size ) { + ::fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); // mkstemp() makes file "rw-------", switch it to "rw-r--r--" + if ( ::rename(pathTemplateSpace, path.c_str()) == 0) { + ::close(fd); + continue; // success + } + } + else { + fprintf(stderr, "ERROR: could not write file %s\n", pathTemplateSpace); + cacheBuildSuccess = false; + } + ::close(fd); + ::unlink(pathTemplateSpace); + } + else { + fprintf(stderr, "ERROR: could not open file %s\n", pathTemplateSpace); + cacheBuildSuccess = false; + } + } + } + + destroySharedCacheBuilder(sharedCacheBuilder); - bool cacheBuildSuccess = build(diags, manifest, dstRoot, false, debug, false, false); + for (auto mappedFile : mappedFiles) + ::munmap((void*)mappedFile.first, mappedFile.second); + } else { + manifest.calculateClosure(); + + cacheBuildSuccess = build(diags, manifest, dstRoot, false, debug, false, false, emitDevCaches, true); + } if (!cacheBuildSuccess) { exit(-1); } - writeRootList(dstRoot, roots); + // Compare this cache to the baseline cache and see if we have any roots to copy over + if (!baselineDifferenceResultPath.empty() || baselineCopyRoots) { + std::set baselineDylibs = manifest.resultsForConfiguration(configuration); + + std::set newDylibs; + manifest.forEachConfiguration([&manifest, &newDylibs](const std::string& configName) { + for (auto& arch : manifest.configuration(configName).architectures) { + for (auto& dylib : arch.second.results.dylibs) { + if (dylib.second.included) { + newDylibs.insert(manifest.installNameForUUID(dylib.first)); + } + } + } + }); + + if (baselineCopyRoots) { + // Work out the set of dylibs in the old cache but not the new one + std::set dylibsMissingFromNewCache; + for (const std::string& baselineDylib : baselineDylibs) { + if (!newDylibs.count(baselineDylib)) + dylibsMissingFromNewCache.insert(baselineDylib); + } + + if (!dylibsMissingFromNewCache.empty()) { + BOMCopier copier = BOMCopierNewWithSys(BomSys_default()); + BOMCopierSetUserData(copier, (void*)&dylibsMissingFromNewCache); + BOMCopierSetCopyFileStartedHandler(copier, filteredCopyIncludingPaths); + std::string dylibCacheRootDir = realFilePath(dylibCacheDir + "/Root"); + if (dylibCacheRootDir == "") { + fprintf(stderr, "Could not find dylib Root directory to copy baseline roots from\n"); + exit(1); + } + BOMCopierCopy(copier, dylibCacheRootDir.c_str(), dstRoot.c_str()); + BOMCopierFree(copier); + + for (const std::string& dylibMissingFromNewCache : dylibsMissingFromNewCache) { + diags.verbose("Dylib missing from new cache: '%s'\n", dylibMissingFromNewCache.c_str()); + } + } + } + + if (!baselineDifferenceResultPath.empty()) { + auto cppToObjStr = [](const std::string& str) { + return [NSString stringWithUTF8String:str.c_str()]; + }; + + // Work out the set of dylibs in the cache and taken from the -root + NSMutableArray* dylibsFromRoots = [NSMutableArray array]; + for (auto& root : roots) { + for (const std::string& dylibInstallName : newDylibs) { + struct stat sb; + std::string filePath = root + "/" + dylibInstallName; + if (!stat(filePath.c_str(), &sb)) { + [dylibsFromRoots addObject:cppToObjStr(dylibInstallName)]; + } + } + } + + // Work out the set of dylibs in the new cache but not in the baseline cache. + NSMutableArray* dylibsMissingFromBaselineCache = [NSMutableArray array]; + for (const std::string& newDylib : newDylibs) { + if (!baselineDylibs.count(newDylib)) + [dylibsMissingFromBaselineCache addObject:cppToObjStr(newDylib)]; + } + + NSMutableDictionary* cacheDict = [[NSMutableDictionary alloc] init]; + cacheDict[@"root-paths-in-cache"] = dylibsFromRoots; + cacheDict[@"device-paths-to-delete"] = dylibsMissingFromBaselineCache; + + NSError* error = nil; + NSData* outData = [NSPropertyListSerialization dataWithPropertyList:cacheDict + format:NSPropertyListBinaryFormat_v1_0 + options:0 + error:&error]; + (void)[outData writeToFile:cppToObjStr(baselineDifferenceResultPath) atomically:YES]; + } + } if (copyRoots) { - manifest.forEachConfiguration([&manifest](const std::string& configName) { + std::set cachePaths; + manifest.forEachConfiguration([&manifest, &cachePaths](const std::string& configName) { for (auto& arch : manifest.configuration(configName).architectures) { for (auto& dylib : arch.second.results.dylibs) { if (dylib.second.included) { - dyld3::MachOParser parser = manifest.parserForUUID(dylib.first); - cachePaths.insert(parser.installName()); + cachePaths.insert(manifest.installNameForUUID(dylib.first)); } } } }); BOMCopier copier = BOMCopierNewWithSys(BomSys_default()); - BOMCopierSetCopyFileStartedHandler(copier, filteredCopy); + BOMCopierSetUserData(copier, (void*)&cachePaths); + BOMCopierSetCopyFileStartedHandler(copier, filteredCopyExcludingPaths); for (auto& root : roots) { BOMCopierCopy(copier, root.c_str(), dstRoot.c_str()); } BOMCopierFree(copier); } - - - int err = sync_volume_np(dstRoot.c_str(), SYNC_VOLUME_FULLSYNC | SYNC_VOLUME_WAIT); if (err) { fprintf(stderr, "Volume sync failed errnor=%d (%s)\n", err, strerror(err)); } - // Create an empty FIPS data in the root - (void)mkpath_np((dstRoot + "/private/var/db/FIPS/").c_str(), 0755); - int fd = open((dstRoot + "/private/var/db/FIPS/fips_data").c_str(), O_CREAT | O_TRUNC, 0644); - close(fd); - // Now that all the build commands have been issued lets put a barrier in after then which can tear down the app after // everything is written. @@ -364,7 +785,7 @@ int main(int argc, const char* argv[]) const char* args[8]; args[0] = (char*)"/bin/rm"; args[1] = (char*)"-rf"; - args[2] = (char*)tempRootDir; + args[2] = (char*)tempRootsDir; args[3] = nullptr; (void)runCommandAndWait(diags, args);