15
15
#include <dlfcn.h>
16
16
#endif
17
17
18
+ #if CFBUNDLE_ALLOW_FHS_BUNDLES
19
+ #if __LP64__
20
+ #define _CFBundleFHSArchDirectorySuffix "64"
21
+ #else // !__LP64__
22
+ #define _CFBundleFHSArchDirectorySuffix "32"
23
+ #endif // __LP64__
24
+
25
+ CONST_STRING_DECL (_CFBundleFHSDirectory_bin , "bin" );
26
+ CONST_STRING_DECL (_CFBundleFHSDirectory_sbin , "sbin" );
27
+ CONST_STRING_DECL (_CFBundleFHSDirectory_libWithArchSuffix , "lib" _CFBundleFHSArchDirectorySuffix );
28
+ CONST_STRING_DECL (_CFBundleFHSDirectory_lib , "lib" );
29
+
30
+ #define _CFBundleFHSExecutablesDirectorySuffix CFSTR(".executables")
31
+
32
+ #define _CFBundleFHSDirectoryCLiteral_libexec "libexec"
33
+
34
+ #define _CFBundleFHSDirectoriesInExecutableSearchOrder \
35
+ _CFBundleFHSDirectory_bin, \
36
+ _CFBundleFHSDirectory_sbin, \
37
+ _CFBundleFHSDirectory_libWithArchSuffix, \
38
+ _CFBundleFHSDirectory_lib
39
+
40
+ #endif // CFBUNDLE_ALLOW_FHS_BUNDLES
41
+
18
42
// This is here because on iPhoneOS with the dyld shared cache, we remove binaries from their
19
43
// original locations on disk, so checking whether a binary's path exists is no longer sufficient.
20
44
// For performance reasons, we only call dlopen_preflight() after we've verified that the binary
@@ -38,7 +62,22 @@ static CFURLRef _CFBundleCopyExecutableURLRaw(CFURLRef urlPath, CFStringRef exeN
38
62
CFURLRef executableURL = NULL ;
39
63
if (!urlPath || !exeName ) return NULL ;
40
64
41
- #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
65
+ #if CFBUNDLE_ALLOW_FHS_BUNDLES
66
+ if (!executableURL ) {
67
+ executableURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorSystemDefault , exeName , kCFURLPOSIXPathStyle , false, urlPath );
68
+ if (!_binaryLoadable (executableURL )) {
69
+ CFRelease (executableURL );
70
+
71
+ CFStringRef sharedLibraryName = CFStringCreateWithFormat (kCFAllocatorSystemDefault , NULL , CFSTR ("%@%@%@" ), _CFBundleFHSSharedLibraryFilenamePrefix , exeName , _CFBundleFHSSharedLibraryFilenameSuffix );
72
+
73
+ executableURL = CFURLCreateWithFileSystemPathRelativeToBase (kCFAllocatorSystemDefault , sharedLibraryName , kCFURLPOSIXPathStyle , false, urlPath );
74
+ if (!_binaryLoadable (executableURL )) {
75
+ CFRelease (executableURL );
76
+ executableURL = NULL ;
77
+ }
78
+ }
79
+ }
80
+ #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
42
81
const uint8_t * image_suffix = (uint8_t * )__CFgetenvIfNotRestricted ("DYLD_IMAGE_SUFFIX" );
43
82
44
83
if (image_suffix ) {
@@ -152,19 +191,60 @@ static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURL
152
191
#else
153
192
Boolean doExecSearch = true;
154
193
#endif
194
+
195
+ #if CFBUNDLE_ALLOW_FHS_BUNDLES
196
+ if (lookupMainExe && bundle && bundle -> _isFHSInstalledBundle ) {
197
+ // For a FHS installed bundle, the URL points to share/Bundle.resources, and the binary is in:
198
+
199
+ CFURLRef prefix = CFURLCreateCopyDeletingLastPathComponent (kCFAllocatorSystemDefault , url );
200
+
201
+ CFStringRef directories [] = { _CFBundleFHSDirectoriesInExecutableSearchOrder };
202
+ size_t directoriesCount = sizeof (directories ) / sizeof (directories [0 ]);
203
+
204
+ for (size_t i = 0 ; i < directoriesCount ; i ++ ) {
205
+ CFURLRef where = CFURLCreateCopyAppendingPathComponent (kCFAllocatorSystemDefault , prefix , directories [i ], true);
206
+ executableURL = _CFBundleCopyExecutableURLRaw (where , executableName );
207
+ CFRelease (where );
208
+
209
+ if (executableURL ) {
210
+ foundIt = true;
211
+ break ;
212
+ }
213
+ }
214
+
215
+ CFRelease (prefix );
216
+ }
217
+ #endif // CFBUNDLE_ALLOW_FHS_BUNDLES
218
+
155
219
// Now, look for the executable inside the bundle.
156
- if (doExecSearch && 0 != version ) {
220
+ if (! foundIt && doExecSearch && 0 != version ) {
157
221
CFURLRef exeDirURL = NULL ;
158
222
223
+ #if CFBUNDLE_ALLOW_FHS_BUNDLES
224
+ if (bundle && bundle -> _isFHSInstalledBundle ) {
225
+ CFURLRef withoutExtension = CFURLCreateCopyDeletingPathExtension (kCFAllocatorSystemDefault , url );
226
+ CFStringRef lastPathComponent = CFURLCopyLastPathComponent (withoutExtension );
227
+
228
+ CFURLRef libexec = CFURLCreateWithString (kCFAllocatorSystemDefault , CFSTR ("../../" _CFBundleFHSDirectoryCLiteral_libexec ), url );
229
+
230
+ CFStringRef exeDirName = CFStringCreateWithFormat (kCFAllocatorSystemDefault , NULL , CFSTR ("%@%@" ), lastPathComponent , _CFBundleFHSExecutablesDirectorySuffix );
231
+ exeDirURL = CFURLCreateCopyAppendingPathComponent (kCFAllocatorSystemDefault , libexec , exeDirName , true);
232
+
233
+ CFRelease (withoutExtension );
234
+ CFRelease (lastPathComponent );
235
+ CFRelease (libexec );
236
+ CFRelease (exeDirName );
237
+ } else
238
+ #endif // CFBUNDLE_ALLOW_FHS_BUNDLES
159
239
if (1 == version ) {
160
240
exeDirURL = CFURLCreateWithString (kCFAllocatorSystemDefault , _CFBundleExecutablesURLFromBase1 , url );
161
241
} else if (2 == version ) {
162
242
exeDirURL = CFURLCreateWithString (kCFAllocatorSystemDefault , _CFBundleExecutablesURLFromBase2 , url );
163
243
} else {
164
- #if DEPLOYMENT_TARGET_WINDOWS
165
- // On Windows, if the bundle URL is foo.resources, then the executable is at the same level as the .resources directory
244
+ #if DEPLOYMENT_TARGET_WINDOWS || CFBUNDLE_ALLOW_FHS_BUNDLES
245
+ // On Windows, Linyx if the bundle URL is foo.resources, then the executable is at the same level as the .resources directory
166
246
CFStringRef extension = CFURLCopyPathExtension (url );
167
- if (extension && CFEqual (extension , _CFBundleWindowsResourceDirectoryExtension )) {
247
+ if (extension && CFEqual (extension , _CFBundleSiblingResourceDirectoryExtension )) {
168
248
exeDirURL = CFURLCreateCopyDeletingLastPathComponent (kCFAllocatorSystemDefault , url );
169
249
} else {
170
250
exeDirURL = (CFURLRef )CFRetain (url );
@@ -232,15 +312,15 @@ static CFURLRef _CFBundleCopyBundleURLForExecutablePath(CFStringRef str) {
232
312
#if DEPLOYMENT_TARGET_WINDOWS
233
313
// Is this a .dll or .exe?
234
314
if (buffLen >= 5 && (_wcsnicmp ((wchar_t * )& (buff [buffLen - 4 ]), L".dll" , 4 ) == 0 || _wcsnicmp ((wchar_t * )& (buff [buffLen - 4 ]), L".exe" , 4 ) == 0 )) {
235
- CFIndex extensionLength = CFStringGetLength (_CFBundleWindowsResourceDirectoryExtension );
315
+ CFIndex extensionLength = CFStringGetLength (_CFBundleSiblingResourceDirectoryExtension );
236
316
buffLen -= 4 ;
237
317
// If this is an _debug, we should strip that before looking for the bundle
238
318
if (buffLen >= 7 && (_wcsnicmp ((wchar_t * )& buff [buffLen - 6 ], L"_debug" , 6 ) == 0 )) buffLen -= 6 ;
239
319
240
320
if (buffLen + 1 + extensionLength < CFMaxPathSize ) {
241
321
buff [buffLen ] = '.' ;
242
322
buffLen ++ ;
243
- CFStringGetCharacters (_CFBundleWindowsResourceDirectoryExtension , CFRangeMake (0 , extensionLength ), buff + buffLen );
323
+ CFStringGetCharacters (_CFBundleSiblingResourceDirectoryExtension , CFRangeMake (0 , extensionLength ), buff + buffLen );
244
324
buffLen += extensionLength ;
245
325
outstr = CFStringCreateWithCharactersNoCopy (kCFAllocatorSystemDefault , buff , buffLen , kCFAllocatorNull );
246
326
url = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , outstr , PLATFORM_PATH_STYLE , true);
0 commit comments