Merge pull request #506 from squidbus/macos-translocation

Untranslocate app bundle path if needed on macOS.
This commit is contained in:
georgemoralis 2024-08-21 18:13:08 +03:00 committed by GitHub
commit 132ca9c5a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 40 additions and 10 deletions

View File

@ -8,6 +8,7 @@
#ifdef __APPLE__ #ifdef __APPLE__
#include <CoreFoundation/CFBundle.h> #include <CoreFoundation/CFBundle.h>
#include <dlfcn.h>
#include <sys/param.h> #include <sys/param.h>
#endif #endif
@ -26,26 +27,55 @@ namespace Common::FS {
namespace fs = std::filesystem; namespace fs = std::filesystem;
#ifdef __APPLE__ #ifdef __APPLE__
using IsTranslocatedURLFunc = Boolean (*)(CFURLRef path, bool* isTranslocated,
CFErrorRef* __nullable error);
using CreateOriginalPathForURLFunc = CFURLRef __nullable (*)(CFURLRef translocatedPath,
CFErrorRef* __nullable error);
static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) {
if (void* security_handle =
dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY)) {
SCOPE_EXIT {
dlclose(security_handle);
};
const auto IsTranslocatedURL = reinterpret_cast<IsTranslocatedURLFunc>(
dlsym(security_handle, "SecTranslocateIsTranslocatedURL"));
const auto CreateOriginalPathForURL = reinterpret_cast<CreateOriginalPathForURLFunc>(
dlsym(security_handle, "SecTranslocateCreateOriginalPathForURL"));
bool is_translocated = false;
if (IsTranslocatedURL && CreateOriginalPathForURL &&
IsTranslocatedURL(bundle_path, &is_translocated, nullptr) && is_translocated) {
return CreateOriginalPathForURL(bundle_path, nullptr);
}
}
return nullptr;
}
static std::filesystem::path GetBundleParentDirectory() { static std::filesystem::path GetBundleParentDirectory() {
if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) { if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) {
if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) { if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) {
SCOPE_EXIT { SCOPE_EXIT {
CFRelease(bundle_url_ref); CFRelease(bundle_url_ref);
}; };
if (CFStringRef bundle_path_ref =
CFURLCopyFileSystemPath(bundle_url_ref, kCFURLPOSIXPathStyle)) { CFURLRef untranslocated_url_ref = UntranslocateBundlePath(bundle_url_ref);
SCOPE_EXIT { SCOPE_EXIT {
CFRelease(bundle_path_ref); if (untranslocated_url_ref) {
CFRelease(untranslocated_url_ref);
}
}; };
char app_bundle_path[MAXPATHLEN]; char app_bundle_path[MAXPATHLEN];
if (CFStringGetFileSystemRepresentation(bundle_path_ref, app_bundle_path, if (CFURLGetFileSystemRepresentation(
sizeof(app_bundle_path))) { untranslocated_url_ref ? untranslocated_url_ref : bundle_url_ref, true,
reinterpret_cast<u8*>(app_bundle_path), sizeof(app_bundle_path))) {
std::filesystem::path bundle_path{app_bundle_path}; std::filesystem::path bundle_path{app_bundle_path};
return bundle_path.parent_path(); return bundle_path.parent_path();
} }
} }
} }
}
return std::filesystem::current_path(); return std::filesystem::current_path();
} }
#endif #endif