macOS >= 10.12 includes a security feature that 'translocates' applications (with a list of exclusions that don't always apply to OpenRA) at runtime to run from a read-only disk image. This breaks our ModMetadata launch paths, giving transient paths that are not repeatable.
LaunchPath: /private/var/folders/wm/1cb20jp50y9_ycdlqlqxhky00000gn/T/AppTranslocation/E917BB1D-A577-4BD3-89B7-A8BA65E6CEAB/d/OpenRA.app/Contents/MacOS/OpenRA
Running from the translocated location isn't a problem so long as we know the original launch path so that we can reliably relaunch the game.
#include <dlfcn.h> // dlopen, dlclose
bool IsTranslocatedURL(CFURLRef currentURL, CFURLRef *originalURL)
{
if (currentURL == NULL)
{
return false;
}
// #define NSAppKitVersionNumber10_11 1404
if (floor(NSAppKitVersionNumber) <= 1404)
{
return false;
}
void *handle = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY);
if (handle == NULL)
{
return false;
}
bool isTranslocated = false;
Boolean (*mySecTranslocateIsTranslocatedURL)(CFURLRef path, bool *isTranslocated, CFErrorRef * __nullable error);
mySecTranslocateIsTranslocatedURL = dlsym(handle, "SecTranslocateIsTranslocatedURL");
if (mySecTranslocateIsTranslocatedURL != NULL)
{
if (mySecTranslocateIsTranslocatedURL(currentURL, &isTranslocated, NULL))
{
if (isTranslocated)
{
if (originalURL != NULL)
{
CFURLRef __nullable (*mySecTranslocateCreateOriginalPathForURL)(CFURLRef translocatedPath, CFErrorRef * __nullable error);
mySecTranslocateCreateOriginalPathForURL = dlsym(handle, "SecTranslocateCreateOriginalPathForURL");
if (mySecTranslocateCreateOriginalPathForURL != NULL)
{
*originalURL = mySecTranslocateCreateOriginalPathForURL((CFURLRef)currentURL, NULL);
}
else
{
*originalURL = NULL;
}
}
}
}
}
dlclose(handle);
return isTranslocated;
}