2 * Copyright (c) 2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright (c) 1999-2007 Apple Inc. All rights reserved.
25 Responsibility: Doug Davidson
28 #include "CFBundle_Internal.h"
29 #include <CoreFoundation/CFPropertyList.h>
30 #include <CoreFoundation/CFNumber.h>
31 #include <CoreFoundation/CFSet.h>
32 #include <CoreFoundation/CFURLAccess.h>
33 #include <CoreFoundation/CFError.h>
36 #include "CFInternal.h"
37 #include <CoreFoundation/CFByteOrder.h>
38 #include "CFBundle_BinaryTypes.h"
43 #if defined(BINARY_SUPPORT_DYLD)
44 // Import the mach-o headers that define the macho magic numbers
45 #include <mach-o/loader.h>
46 #include <mach-o/fat.h>
47 #include <mach-o/arch.h>
48 #include <mach-o/dyld.h>
49 #include <mach-o/getsect.h>
53 #endif /* BINARY_SUPPORT_DYLD */
55 #if defined(BINARY_SUPPORT_DLFCN)
57 #endif /* BINARY_SUPPORT_DLFCN */
59 #if DEPLOYMENT_TARGET_MACOSX
64 #define LOG_BUNDLE_LOAD 0
66 // Public CFBundle Info plist keys
67 CONST_STRING_DECL(kCFBundleInfoDictionaryVersionKey
, "CFBundleInfoDictionaryVersion")
68 CONST_STRING_DECL(kCFBundleExecutableKey
, "CFBundleExecutable")
69 CONST_STRING_DECL(kCFBundleIdentifierKey
, "CFBundleIdentifier")
70 CONST_STRING_DECL(kCFBundleVersionKey
, "CFBundleVersion")
71 CONST_STRING_DECL(kCFBundleDevelopmentRegionKey
, "CFBundleDevelopmentRegion")
72 CONST_STRING_DECL(kCFBundleLocalizationsKey
, "CFBundleLocalizations")
75 CONST_STRING_DECL(_kCFBundlePackageTypeKey
, "CFBundlePackageType")
76 CONST_STRING_DECL(_kCFBundleSignatureKey
, "CFBundleSignature")
77 CONST_STRING_DECL(_kCFBundleIconFileKey
, "CFBundleIconFile")
78 CONST_STRING_DECL(_kCFBundleDocumentTypesKey
, "CFBundleDocumentTypes")
79 CONST_STRING_DECL(_kCFBundleURLTypesKey
, "CFBundleURLTypes")
81 // Keys that are usually localized in InfoPlist.strings
82 CONST_STRING_DECL(kCFBundleNameKey
, "CFBundleName")
83 CONST_STRING_DECL(_kCFBundleDisplayNameKey
, "CFBundleDisplayName")
84 CONST_STRING_DECL(_kCFBundleShortVersionStringKey
, "CFBundleShortVersionString")
85 CONST_STRING_DECL(_kCFBundleGetInfoStringKey
, "CFBundleGetInfoString")
86 CONST_STRING_DECL(_kCFBundleGetInfoHTMLKey
, "CFBundleGetInfoHTML")
88 // Sub-keys for CFBundleDocumentTypes dictionaries
89 CONST_STRING_DECL(_kCFBundleTypeNameKey
, "CFBundleTypeName")
90 CONST_STRING_DECL(_kCFBundleTypeRoleKey
, "CFBundleTypeRole")
91 CONST_STRING_DECL(_kCFBundleTypeIconFileKey
, "CFBundleTypeIconFile")
92 CONST_STRING_DECL(_kCFBundleTypeOSTypesKey
, "CFBundleTypeOSTypes")
93 CONST_STRING_DECL(_kCFBundleTypeExtensionsKey
, "CFBundleTypeExtensions")
94 CONST_STRING_DECL(_kCFBundleTypeMIMETypesKey
, "CFBundleTypeMIMETypes")
96 // Sub-keys for CFBundleURLTypes dictionaries
97 CONST_STRING_DECL(_kCFBundleURLNameKey
, "CFBundleURLName")
98 CONST_STRING_DECL(_kCFBundleURLIconFileKey
, "CFBundleURLIconFile")
99 CONST_STRING_DECL(_kCFBundleURLSchemesKey
, "CFBundleURLSchemes")
101 // Compatibility key names
102 CONST_STRING_DECL(_kCFBundleOldExecutableKey
, "NSExecutable")
103 CONST_STRING_DECL(_kCFBundleOldInfoDictionaryVersionKey
, "NSInfoPlistVersion")
104 CONST_STRING_DECL(_kCFBundleOldNameKey
, "NSHumanReadableName")
105 CONST_STRING_DECL(_kCFBundleOldIconFileKey
, "NSIcon")
106 CONST_STRING_DECL(_kCFBundleOldDocumentTypesKey
, "NSTypes")
107 CONST_STRING_DECL(_kCFBundleOldShortVersionStringKey
, "NSAppVersion")
109 // Compatibility CFBundleDocumentTypes key names
110 CONST_STRING_DECL(_kCFBundleOldTypeNameKey
, "NSName")
111 CONST_STRING_DECL(_kCFBundleOldTypeRoleKey
, "NSRole")
112 CONST_STRING_DECL(_kCFBundleOldTypeIconFileKey
, "NSIcon")
113 CONST_STRING_DECL(_kCFBundleOldTypeExtensions1Key
, "NSUnixExtensions")
114 CONST_STRING_DECL(_kCFBundleOldTypeExtensions2Key
, "NSDOSExtensions")
115 CONST_STRING_DECL(_kCFBundleOldTypeOSTypesKey
, "NSMacOSType")
117 // Internally used keys for loaded Info plists.
118 CONST_STRING_DECL(_kCFBundleInfoPlistURLKey
, "CFBundleInfoPlistURL")
119 CONST_STRING_DECL(_kCFBundleRawInfoPlistURLKey
, "CFBundleRawInfoPlistURL")
120 CONST_STRING_DECL(_kCFBundleNumericVersionKey
, "CFBundleNumericVersion")
121 CONST_STRING_DECL(_kCFBundleExecutablePathKey
, "CFBundleExecutablePath")
122 CONST_STRING_DECL(_kCFBundleResourcesFileMappedKey
, "CSResourcesFileMapped")
123 CONST_STRING_DECL(_kCFBundleCFMLoadAsBundleKey
, "CFBundleCFMLoadAsBundle")
124 CONST_STRING_DECL(_kCFBundleAllowMixedLocalizationsKey
, "CFBundleAllowMixedLocalizations")
126 // Keys used by NSBundle for loaded Info plists.
127 CONST_STRING_DECL(_kCFBundleInitialPathKey
, "NSBundleInitialPath")
128 CONST_STRING_DECL(_kCFBundleResolvedPathKey
, "NSBundleResolvedPath")
129 CONST_STRING_DECL(_kCFBundlePrincipalClassKey
, "NSPrincipalClass")
131 static CFTypeID __kCFBundleTypeID
= _kCFRuntimeNotATypeID
;
139 CFDictionaryRef _infoDict
;
140 CFDictionaryRef _localInfoDict
;
141 CFArrayRef _searchLanguages
;
143 __CFPBinaryType _binaryType
;
146 Boolean _sharesStringsFiles
;
150 void *_connectionCookie
;
153 const void *_imageCookie
;
154 const void *_moduleCookie
;
159 /* CFM<->DYLD glue */
160 CFMutableDictionaryRef _glueDict
;
162 /* Resource fork goop */
163 _CFResourceData _resourceData
;
165 _CFPlugInData _plugInData
;
167 #if defined(BINARY_SUPPORT_DLL)
169 #endif /* BINARY_SUPPORT_DLL */
173 static CFSpinLock_t CFBundleGlobalDataLock
= CFSpinLockInit
;
175 static CFMutableDictionaryRef _bundlesByURL
= NULL
;
176 static CFMutableDictionaryRef _bundlesByIdentifier
= NULL
;
178 // For scheduled lazy unloading. Used by CFPlugIn.
179 static CFMutableSetRef _bundlesToUnload
= NULL
;
180 static Boolean _scheduledBundlesAreUnloading
= false;
182 // Various lists of all bundles.
183 static CFMutableArrayRef _allBundles
= NULL
;
185 static Boolean _initedMainBundle
= false;
186 static CFBundleRef _mainBundle
= NULL
;
187 static CFStringRef _defaultLocalization
= NULL
;
189 static Boolean _useDlfcn
= false;
191 // Forward declares functions.
192 static CFBundleRef
_CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
, Boolean alreadyLocked
, Boolean doFinalProcessing
);
193 static CFStringRef
_CFBundleCopyExecutableName(CFAllocatorRef alloc
, CFBundleRef bundle
, CFURLRef url
, CFDictionaryRef infoDict
);
194 static CFURLRef
_CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle
);
195 static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint
);
196 static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void);
197 static void _CFBundleCheckWorkarounds(CFBundleRef bundle
);
198 static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath
);
199 static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths
);
200 #if defined(BINARY_SUPPORT_DYLD)
201 static CFDictionaryRef
_CFBundleGrokInfoDictFromMainExecutable(void);
202 static Boolean
_CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion
, uint32_t *objcFlags
);
203 static CFStringRef
_CFBundleDYLDCopyLoadedImagePathForPointer(void *p
);
204 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
);
205 #endif /* BINARY_SUPPORT_DYLD */
206 #if defined(BINARY_SUPPORT_DLFCN)
207 static CFStringRef
_CFBundleDlfcnCopyLoadedImagePathForPointer(void *p
);
208 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
);
209 #endif /* BINARY_SUPPORT_DLFCN */
210 #if defined(BINARY_SUPPORT_DYLD) && defined(BINARY_SUPPORT_CFM)
211 static void *_CFBundleFunctionPointerForTVector(CFAllocatorRef allocator
, void *tvp
);
212 static void *_CFBundleTVectorForFunctionPointer(CFAllocatorRef allocator
, void *fp
);
213 #endif /* BINARY_SUPPORT_DYLD && BINARY_SUPPORT_CFM */
215 static void _CFBundleAddToTables(CFBundleRef bundle
, Boolean alreadyLocked
) {
216 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
218 if (!alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
220 // Add to the _allBundles list
222 // Create this from the default allocator
223 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
224 nonRetainingArrayCallbacks
.retain
= NULL
;
225 nonRetainingArrayCallbacks
.release
= NULL
;
226 _allBundles
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
228 CFArrayAppendValue(_allBundles
, bundle
);
230 // Add to the table that maps urls to bundles
231 if (!_bundlesByURL
) {
232 // Create this from the default allocator
233 CFDictionaryValueCallBacks nonRetainingDictionaryValueCallbacks
= kCFTypeDictionaryValueCallBacks
;
234 nonRetainingDictionaryValueCallbacks
.retain
= NULL
;
235 nonRetainingDictionaryValueCallbacks
.release
= NULL
;
236 _bundlesByURL
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &nonRetainingDictionaryValueCallbacks
);
238 CFDictionarySetValue(_bundlesByURL
, bundle
->_url
, bundle
);
240 // Add to the table that maps identifiers to bundles
242 CFMutableArrayRef bundlesWithThisID
= NULL
;
243 CFBundleRef existingBundle
= NULL
;
244 if (!_bundlesByIdentifier
) {
245 // Create this from the default allocator
246 _bundlesByIdentifier
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
248 bundlesWithThisID
= (CFMutableArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
249 if (bundlesWithThisID
) {
250 CFIndex i
, count
= CFArrayGetCount(bundlesWithThisID
);
251 UInt32 existingVersion
, newVersion
= CFBundleGetVersionNumber(bundle
);
252 for (i
= 0; i
< count
; i
++) {
253 existingBundle
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, i
);
254 existingVersion
= CFBundleGetVersionNumber(existingBundle
);
255 // If you load two bundles with the same identifier and the same version, the last one wins.
256 if (newVersion
>= existingVersion
) break;
258 CFArrayInsertValueAtIndex(bundlesWithThisID
, i
, bundle
);
260 // Create this from the default allocator
261 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
262 nonRetainingArrayCallbacks
.retain
= NULL
;
263 nonRetainingArrayCallbacks
.release
= NULL
;
264 bundlesWithThisID
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
265 CFArrayAppendValue(bundlesWithThisID
, bundle
);
266 CFDictionarySetValue(_bundlesByIdentifier
, bundleID
, bundlesWithThisID
);
267 CFRelease(bundlesWithThisID
);
270 if (!alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
273 static void _CFBundleRemoveFromTables(CFBundleRef bundle
) {
274 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
276 __CFSpinLock(&CFBundleGlobalDataLock
);
278 // Remove from the various lists
280 CFIndex i
= CFArrayGetFirstIndexOfValue(_allBundles
, CFRangeMake(0, CFArrayGetCount(_allBundles
)), bundle
);
281 if (i
>= 0) CFArrayRemoveValueAtIndex(_allBundles
, i
);
284 // Remove from the table that maps urls to bundles
285 if (_bundlesByURL
) CFDictionaryRemoveValue(_bundlesByURL
, bundle
->_url
);
287 // Remove from the table that maps identifiers to bundles
288 if (bundleID
&& _bundlesByIdentifier
) {
289 CFMutableArrayRef bundlesWithThisID
= (CFMutableArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
290 if (bundlesWithThisID
) {
291 CFIndex count
= CFArrayGetCount(bundlesWithThisID
);
292 while (count
-- > 0) if (bundle
== (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, count
)) CFArrayRemoveValueAtIndex(bundlesWithThisID
, count
);
293 if (0 == CFArrayGetCount(bundlesWithThisID
)) CFDictionaryRemoveValue(_bundlesByIdentifier
, bundleID
);
297 __CFSpinUnlock(&CFBundleGlobalDataLock
);
300 __private_extern__ CFBundleRef
_CFBundleFindByURL(CFURLRef url
, Boolean alreadyLocked
) {
301 CFBundleRef result
= NULL
;
302 if (!alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
303 if (_bundlesByURL
) result
= (CFBundleRef
)CFDictionaryGetValue(_bundlesByURL
, url
);
304 if (!alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
308 static CFURLRef
_CFBundleCopyBundleURLForExecutablePath(CFStringRef str
) {
309 //!!! need to handle frameworks, NT; need to integrate with NSBundle - drd
310 UniChar buff
[CFMaxPathSize
];
315 buffLen
= CFStringGetLength(str
);
316 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
317 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
320 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
); // Remove exe name
322 #if DEPLOYMENT_TARGET_MACOSX
324 // See if this is a new bundle. If it is, we have to remove more path components.
325 CFIndex startOfLastDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
326 if ((startOfLastDir
> 0) && (startOfLastDir
< buffLen
)) {
327 CFStringRef lastDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfLastDir
]), buffLen
- startOfLastDir
);
329 if (CFEqual(lastDirName
, _CFBundleGetPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetAlternatePlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName())) {
330 // This is a new bundle. Back off a few more levels
332 // Remove platform folder
333 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
336 // Remove executables folder (if present)
337 CFIndex startOfNextDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
338 if ((startOfNextDir
> 0) && (startOfNextDir
< buffLen
)) {
339 CFStringRef nextDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfNextDir
]), buffLen
- startOfNextDir
);
340 if (CFEqual(nextDirName
, _CFBundleExecutablesDirectoryName
)) buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
341 CFRelease(nextDirName
);
345 // Remove support files folder
346 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
350 #if DEPLOYMENT_TARGET_MACOSX
351 CFRelease(lastDirName
);
357 outstr
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, buff
, buffLen
, kCFAllocatorNull
);
358 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, outstr
, PLATFORM_PATH_STYLE
, true);
365 static CFURLRef
_CFBundleCopyResolvedURLForExecutableURL(CFURLRef url
) {
366 // this is necessary so that we match any sanitization CFURL may perform on the result of _CFBundleCopyBundleURLForExecutableURL()
367 CFURLRef absoluteURL
, url1
, url2
, outURL
= NULL
;
368 CFStringRef str
, str1
, str2
;
369 absoluteURL
= CFURLCopyAbsoluteURL(url
);
370 str
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
);
372 UniChar buff
[CFMaxPathSize
];
373 CFIndex buffLen
= CFStringGetLength(str
), len1
;
374 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
375 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
376 len1
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
377 if (len1
> 0 && len1
+ 1 < buffLen
) {
378 str1
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, buff
, len1
);
379 str2
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, buff
+ len1
+ 1, buffLen
- len1
- 1);
381 url1
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str1
, PLATFORM_PATH_STYLE
, true);
383 url2
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, str2
, PLATFORM_PATH_STYLE
, false, url1
);
385 outURL
= CFURLCopyAbsoluteURL(url2
);
391 if (str1
) CFRelease(str1
);
392 if (str2
) CFRelease(str2
);
397 outURL
= absoluteURL
;
399 CFRelease(absoluteURL
);
404 CFURLRef
_CFBundleCopyBundleURLForExecutableURL(CFURLRef url
) {
405 CFURLRef resolvedURL
, outurl
= NULL
;
407 resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
408 str
= CFURLCopyFileSystemPath(resolvedURL
, PLATFORM_PATH_STYLE
);
410 outurl
= _CFBundleCopyBundleURLForExecutablePath(str
);
413 CFRelease(resolvedURL
);
417 CFBundleRef
_CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
418 CFBundleRef bundle
= CFBundleCreate(allocator
, url
);
420 // exclude type 0 bundles with no binary (or CFM binary) and no Info.plist, since they give too many false positives
421 if (bundle
&& 0 == bundle
->_version
) {
422 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
423 if (!infoDict
|| 0 == CFDictionaryGetCount(infoDict
)) {
424 #if defined(BINARY_SUPPORT_CFM) && defined(BINARY_SUPPORT_DYLD)
425 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
427 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
428 if (bundle
->_binaryType
== __CFBundleCFMBinary
|| bundle
->_binaryType
== __CFBundleUnreadableBinary
) {
429 bundle
->_version
= 4;
431 bundle
->_resourceData
._executableLacksResourceFork
= true;
433 CFRelease(executableURL
);
435 bundle
->_version
= 4;
437 #elif defined(BINARY_SUPPORT_CFM)
438 bundle
->_version
= 4;
440 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
442 CFRelease(executableURL
);
444 bundle
->_version
= 4;
446 #endif /* BINARY_SUPPORT_CFM && BINARY_SUPPORT_DYLD */
449 if (bundle
&& (3 == bundle
->_version
|| 4 == bundle
->_version
)) {
456 CFBundleRef
_CFBundleGetMainBundleIfLooksLikeBundle(void) {
457 CFBundleRef mainBundle
= CFBundleGetMainBundle();
458 if (mainBundle
&& (3 == mainBundle
->_version
|| 4 == mainBundle
->_version
)) mainBundle
= NULL
;
462 Boolean
_CFBundleMainBundleInfoDictionaryComesFromResourceFork(void) {
463 CFBundleRef mainBundle
= CFBundleGetMainBundle();
464 return (mainBundle
&& mainBundle
->_resourceData
._infoDictionaryFromResourceFork
);
467 CFBundleRef
_CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
468 CFBundleRef bundle
= NULL
;
469 CFURLRef bundleURL
= _CFBundleCopyBundleURLForExecutableURL(url
), resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
470 if (bundleURL
&& resolvedURL
) {
471 bundle
= _CFBundleCreateIfLooksLikeBundle(allocator
, bundleURL
);
473 CFURLRef executableURL
= _CFBundleCopyExecutableURLIgnoringCache(bundle
);
474 char buff1
[CFMaxPathSize
], buff2
[CFMaxPathSize
];
475 if (!executableURL
|| !CFURLGetFileSystemRepresentation(resolvedURL
, true, (uint8_t *)buff1
, CFMaxPathSize
) || !CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff2
, CFMaxPathSize
) || 0 != strcmp(buff1
, buff2
)) {
479 if (executableURL
) CFRelease(executableURL
);
482 if (bundleURL
) CFRelease(bundleURL
);
483 if (resolvedURL
) CFRelease(resolvedURL
);
487 CFURLRef
_CFBundleCopyMainBundleExecutableURL(Boolean
*looksLikeBundle
) {
488 // This function is for internal use only; _mainBundle is deliberately accessed outside of the lock to get around a reentrancy issue
489 const char *processPath
;
490 CFStringRef str
= NULL
;
491 CFURLRef executableURL
= NULL
;
492 processPath
= _CFProcessPath();
494 str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, processPath
);
496 executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str
, PLATFORM_PATH_STYLE
, false);
500 if (looksLikeBundle
) {
501 CFBundleRef mainBundle
= _mainBundle
;
502 if (mainBundle
&& (3 == mainBundle
->_version
|| 4 == mainBundle
->_version
)) mainBundle
= NULL
;
503 *looksLikeBundle
= (mainBundle
? true : false);
505 return executableURL
;
508 static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef executablePath
) {
509 #if defined(BINARY_SUPPORT_CFM)
510 Boolean versRegionOverrides
= false;
511 #endif /* BINARY_SUPPORT_CFM */
512 CFBundleGetInfoDictionary(_mainBundle
);
513 if (!_mainBundle
->_infoDict
|| CFDictionaryGetCount(_mainBundle
->_infoDict
) == 0) {
514 // if type 3 bundle and no Info.plist, treat as unbundled, since this gives too many false positives
515 if (_mainBundle
->_version
== 3) _mainBundle
->_version
= 4;
516 if (_mainBundle
->_version
== 0) {
517 // if type 0 bundle and no Info.plist and not main executable for bundle, treat as unbundled, since this gives too many false positives
518 CFStringRef executableName
= _CFBundleCopyExecutableName(kCFAllocatorSystemDefault
, _mainBundle
, NULL
, NULL
);
519 if (!executableName
|| !executablePath
|| !CFStringHasSuffix(executablePath
, executableName
)) _mainBundle
->_version
= 4;
520 if (executableName
) CFRelease(executableName
);
522 #if defined(BINARY_SUPPORT_DYLD)
523 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
) {
524 if (_mainBundle
->_infoDict
) CFRelease(_mainBundle
->_infoDict
);
525 _mainBundle
->_infoDict
= _CFBundleGrokInfoDictFromMainExecutable();
527 #endif /* BINARY_SUPPORT_DYLD */
528 #if defined(BINARY_SUPPORT_CFM)
529 if (_mainBundle
->_binaryType
== __CFBundleCFMBinary
|| _mainBundle
->_binaryType
== __CFBundleUnreadableBinary
) {
530 // if type 0 bundle and CFM binary and no Info.plist, treat as unbundled, since this also gives too many false positives
531 if (_mainBundle
->_version
== 0) _mainBundle
->_version
= 4;
532 if (_mainBundle
->_version
!= 4) {
533 // if CFM binary and no Info.plist and not main executable for bundle, treat as unbundled, since this also gives too many false positives
534 // except for Macromedia Director MX, which is unbundled but wants to be treated as bundled
535 CFStringRef executableName
= _CFBundleCopyExecutableName(kCFAllocatorSystemDefault
, _mainBundle
, NULL
, NULL
);
536 Boolean treatAsBundled
= false;
537 if (executablePath
) {
538 CFIndex strLength
= CFStringGetLength(executablePath
);
539 if (strLength
> 10) treatAsBundled
= CFStringFindWithOptions(executablePath
, CFSTR(" MX"), CFRangeMake(strLength
- 10, 10), 0, NULL
);
541 if (!treatAsBundled
&& (!executableName
|| !executablePath
|| !CFStringHasSuffix(executablePath
, executableName
))) _mainBundle
->_version
= 4;
542 if (executableName
) CFRelease(executableName
);
544 if (_mainBundle
->_infoDict
) CFRelease(_mainBundle
->_infoDict
);
545 if (executablePath
) {
546 CFURLRef executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, executablePath
, PLATFORM_PATH_STYLE
, false);
548 _mainBundle
->_infoDict
= _CFBundleCopyInfoDictionaryInResourceForkWithAllocator(CFGetAllocator(_mainBundle
), executableURL
);
549 if (_mainBundle
->_infoDict
) _mainBundle
->_resourceData
._infoDictionaryFromResourceFork
= true;
550 CFRelease(executableURL
);
553 if (_mainBundle
->_binaryType
== __CFBundleUnreadableBinary
&& _mainBundle
->_infoDict
&& CFDictionaryGetValue(_mainBundle
->_infoDict
, kCFBundleDevelopmentRegionKey
)) versRegionOverrides
= true;
555 #endif /* BINARY_SUPPORT_CFM */
557 if (!_mainBundle
->_infoDict
) _mainBundle
->_infoDict
= CFDictionaryCreateMutable(CFGetAllocator(_mainBundle
), 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
558 if (!CFDictionaryGetValue(_mainBundle
->_infoDict
, _kCFBundleExecutablePathKey
)) CFDictionarySetValue((CFMutableDictionaryRef
)(_mainBundle
->_infoDict
), _kCFBundleExecutablePathKey
, executablePath
);
559 #if defined(BINARY_SUPPORT_CFM)
560 if (versRegionOverrides
) {
561 // This is a hack to preserve backward compatibility for certain broken applications (2761067)
562 CFStringRef devLang
= _CFBundleCopyBundleDevelopmentRegionFromVersResource(_mainBundle
);
564 CFDictionarySetValue((CFMutableDictionaryRef
)(_mainBundle
->_infoDict
), kCFBundleDevelopmentRegionKey
, devLang
);
568 #endif /* BINARY_SUPPORT_CFM */
571 CF_EXPORT
void _CFBundleFlushBundleCaches(CFBundleRef bundle
) {
572 CFDictionaryRef oldInfoDict
= bundle
->_infoDict
;
575 _CFBundleFlushCachesForURL(bundle
->_url
);
576 bundle
->_infoDict
= NULL
;
577 if (bundle
->_localInfoDict
) {
578 CFRelease(bundle
->_localInfoDict
);
579 bundle
->_localInfoDict
= NULL
;
581 if (bundle
->_searchLanguages
) {
582 CFRelease(bundle
->_searchLanguages
);
583 bundle
->_searchLanguages
= NULL
;
585 if (bundle
->_resourceData
._stringTableCache
) {
586 CFRelease(bundle
->_resourceData
._stringTableCache
);
587 bundle
->_resourceData
._stringTableCache
= NULL
;
589 if (bundle
== _mainBundle
) {
590 CFStringRef executablePath
= oldInfoDict
? (CFStringRef
)CFDictionaryGetValue(oldInfoDict
, _kCFBundleExecutablePathKey
) : NULL
;
591 __CFSpinLock(&CFBundleGlobalDataLock
);
592 _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(executablePath
);
593 __CFSpinUnlock(&CFBundleGlobalDataLock
);
595 CFBundleGetInfoDictionary(bundle
);
598 if (!bundle
->_infoDict
) bundle
->_infoDict
= CFDictionaryCreateMutable(CFGetAllocator(bundle
), 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
599 val
= CFDictionaryGetValue(oldInfoDict
, _kCFBundleInitialPathKey
);
600 if (val
) CFDictionarySetValue((CFMutableDictionaryRef
)bundle
->_infoDict
, _kCFBundleInitialPathKey
, val
);
601 val
= CFDictionaryGetValue(oldInfoDict
, _kCFBundleResolvedPathKey
);
602 if (val
) CFDictionarySetValue((CFMutableDictionaryRef
)bundle
->_infoDict
, _kCFBundleResolvedPathKey
, val
);
603 val
= CFDictionaryGetValue(oldInfoDict
, _kCFBundlePrincipalClassKey
);
604 if (val
) CFDictionarySetValue((CFMutableDictionaryRef
)bundle
->_infoDict
, _kCFBundlePrincipalClassKey
, val
);
605 CFRelease(oldInfoDict
);
609 static CFBundleRef
_CFBundleGetMainBundleAlreadyLocked(void) {
610 if (!_initedMainBundle
) {
611 const char *processPath
;
612 CFStringRef str
= NULL
;
613 CFURLRef executableURL
= NULL
, bundleURL
= NULL
;
614 _initedMainBundle
= true;
615 processPath
= _CFProcessPath();
617 str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, processPath
);
618 if (!executableURL
) executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str
, PLATFORM_PATH_STYLE
, false);
620 if (executableURL
) bundleURL
= _CFBundleCopyBundleURLForExecutableURL(executableURL
);
622 // make sure that main bundle has executable path
623 //??? what if we are not the main executable in the bundle?
624 // NB doFinalProcessing must be false here, see below
625 _mainBundle
= _CFBundleCreate(kCFAllocatorSystemDefault
, bundleURL
, true, false);
627 // make sure that the main bundle is listed as loaded, and mark it as executable
628 _mainBundle
->_isLoaded
= true;
629 #if defined(BINARY_SUPPORT_DYLD)
630 if (_mainBundle
->_binaryType
== __CFBundleUnknownBinary
) {
631 if (!executableURL
) {
632 _mainBundle
->_binaryType
= __CFBundleNoBinary
;
634 _mainBundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
635 #if defined(BINARY_SUPPORT_CFM)
636 if (_mainBundle
->_binaryType
!= __CFBundleCFMBinary
&& _mainBundle
->_binaryType
!= __CFBundleUnreadableBinary
) _mainBundle
->_resourceData
._executableLacksResourceFork
= true;
637 #endif /* BINARY_SUPPORT_CFM */
640 #endif /* BINARY_SUPPORT_DYLD */
641 #if defined(BINARY_SUPPORT_DYLD)
642 // get cookie for already-loaded main bundle
643 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
&& !_mainBundle
->_imageCookie
) {
644 // ??? need better way to specify main executable image
645 _mainBundle
->_imageCookie
= (void *)_dyld_get_image_header(0);
647 printf("main bundle %p getting image %p\n", _mainBundle
, _mainBundle
->_imageCookie
);
648 #endif /* LOG_BUNDLE_LOAD */
650 #endif /* BINARY_SUPPORT_DYLD */
651 _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(str
);
652 // Perform delayed final processing steps.
653 // This must be done after _isLoaded has been set, for security reasons (3624341).
654 _CFBundleCheckWorkarounds(_mainBundle
);
655 if (_CFBundleNeedsInitPlugIn(_mainBundle
)) {
656 __CFSpinUnlock(&CFBundleGlobalDataLock
);
657 _CFBundleInitPlugIn(_mainBundle
);
658 __CFSpinLock(&CFBundleGlobalDataLock
);
662 if (bundleURL
) CFRelease(bundleURL
);
663 if (str
) CFRelease(str
);
664 if (executableURL
) CFRelease(executableURL
);
669 CFBundleRef
CFBundleGetMainBundle(void) {
670 CFBundleRef mainBundle
;
671 __CFSpinLock(&CFBundleGlobalDataLock
);
672 mainBundle
= _CFBundleGetMainBundleAlreadyLocked();
673 __CFSpinUnlock(&CFBundleGlobalDataLock
);
677 CFBundleRef
CFBundleGetBundleWithIdentifier(CFStringRef bundleID
) {
678 CFBundleRef result
= NULL
;
679 CFArrayRef bundlesWithThisID
;
681 __CFSpinLock(&CFBundleGlobalDataLock
);
682 (void)_CFBundleGetMainBundleAlreadyLocked();
683 if (_bundlesByIdentifier
) {
684 bundlesWithThisID
= (CFArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
685 if (bundlesWithThisID
&& CFArrayGetCount(bundlesWithThisID
) > 0) result
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, 0);
687 #if DEPLOYMENT_TARGET_MACOSX
689 // Try to create the bundle for the caller and try again
690 void *p
= __builtin_return_address(0);
692 CFStringRef imagePath
= NULL
;
693 #if defined(BINARY_SUPPORT_DLFCN)
694 if (!imagePath
&& _useDlfcn
) imagePath
= _CFBundleDlfcnCopyLoadedImagePathForPointer(p
);
695 #endif /* BINARY_SUPPORT_DLFCN */
696 #if defined(BINARY_SUPPORT_DYLD)
697 if (!imagePath
) imagePath
= _CFBundleDYLDCopyLoadedImagePathForPointer(p
);
698 #endif /* BINARY_SUPPORT_DYLD */
700 _CFBundleEnsureBundleExistsForImagePath(imagePath
);
701 CFRelease(imagePath
);
703 if (_bundlesByIdentifier
) {
704 bundlesWithThisID
= (CFArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
705 if (bundlesWithThisID
&& CFArrayGetCount(bundlesWithThisID
) > 0) result
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, 0);
711 // Try to guess the bundle from the identifier and try again
712 _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(bundleID
);
713 if (_bundlesByIdentifier
) {
714 bundlesWithThisID
= (CFArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
715 if (bundlesWithThisID
&& CFArrayGetCount(bundlesWithThisID
) > 0) result
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, 0);
719 // Make sure all bundles have been created and try again.
720 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
721 if (_bundlesByIdentifier
) {
722 bundlesWithThisID
= (CFArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
723 if (bundlesWithThisID
&& CFArrayGetCount(bundlesWithThisID
) > 0) result
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, 0);
726 __CFSpinUnlock(&CFBundleGlobalDataLock
);
731 static CFStringRef
__CFBundleCopyDescription(CFTypeRef cf
) {
732 char buff
[CFMaxPathSize
];
733 CFStringRef path
= NULL
, binaryType
= NULL
, retval
= NULL
;
734 if (((CFBundleRef
)cf
)->_url
&& CFURLGetFileSystemRepresentation(((CFBundleRef
)cf
)->_url
, true, (uint8_t *)buff
, CFMaxPathSize
)) path
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, buff
);
735 switch (((CFBundleRef
)cf
)->_binaryType
) {
736 case __CFBundleCFMBinary
:
737 binaryType
= CFSTR("");
739 case __CFBundleDYLDExecutableBinary
:
740 binaryType
= CFSTR("executable, ");
742 case __CFBundleDYLDBundleBinary
:
743 binaryType
= CFSTR("bundle, ");
745 case __CFBundleDYLDFrameworkBinary
:
746 binaryType
= CFSTR("framework, ");
748 case __CFBundleDLLBinary
:
749 binaryType
= CFSTR("DLL, ");
751 case __CFBundleUnreadableBinary
:
752 binaryType
= CFSTR("");
755 binaryType
= CFSTR("");
758 if (((CFBundleRef
)cf
)->_plugInData
._isPlugIn
) {
759 retval
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("CFBundle/CFPlugIn %p <%@> (%@%sloaded)"), cf
, path
, binaryType
, ((CFBundleRef
)cf
)->_isLoaded
? "" : "not ");
761 retval
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("CFBundle %p <%@> (%@%sloaded)"), cf
, path
, binaryType
, ((CFBundleRef
)cf
)->_isLoaded
? "" : "not ");
763 if (path
) CFRelease(path
);
767 static void _CFBundleDeallocateGlue(const void *key
, const void *value
, void *context
) {
768 CFAllocatorRef allocator
= (CFAllocatorRef
)context
;
769 if (value
) CFAllocatorDeallocate(allocator
, (void *)value
);
772 static void __CFBundleDeallocate(CFTypeRef cf
) {
773 CFBundleRef bundle
= (CFBundleRef
)cf
;
774 CFAllocatorRef allocator
;
776 __CFGenericValidateType(cf
, __kCFBundleTypeID
);
778 allocator
= CFGetAllocator(bundle
);
781 CFBundleUnloadExecutable(bundle
);
783 // Clean up plugIn stuff
784 _CFBundleDeallocatePlugIn(bundle
);
786 _CFBundleRemoveFromTables(bundle
);
789 _CFBundleFlushCachesForURL(bundle
->_url
);
790 CFRelease(bundle
->_url
);
792 if (bundle
->_infoDict
) CFRelease(bundle
->_infoDict
);
793 if (bundle
->_modDate
) CFRelease(bundle
->_modDate
);
794 if (bundle
->_localInfoDict
) CFRelease(bundle
->_localInfoDict
);
795 if (bundle
->_searchLanguages
) CFRelease(bundle
->_searchLanguages
);
796 if (bundle
->_glueDict
) {
797 CFDictionaryApplyFunction(bundle
->_glueDict
, _CFBundleDeallocateGlue
, (void *)allocator
);
798 CFRelease(bundle
->_glueDict
);
800 if (bundle
->_resourceData
._stringTableCache
) CFRelease(bundle
->_resourceData
._stringTableCache
);
803 static const CFRuntimeClass __CFBundleClass
= {
808 __CFBundleDeallocate
,
812 __CFBundleCopyDescription
815 __private_extern__
void __CFBundleInitialize(void) {
816 __kCFBundleTypeID
= _CFRuntimeRegisterClass(&__CFBundleClass
);
817 #if defined(BINARY_SUPPORT_DLFCN)
819 #if defined(BINARY_SUPPORT_DYLD)
820 if (getenv("CFBundleUseDYLD")) _useDlfcn
= false;
821 #endif /* BINARY_SUPPORT_DYLD */
822 #endif /* BINARY_SUPPORT_DLFCN */
825 Boolean
_CFBundleUseDlfcn(void) {
829 CFTypeID
CFBundleGetTypeID(void) {
830 return __kCFBundleTypeID
;
833 CFBundleRef
_CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL
) {
834 CFBundleRef bundle
= NULL
;
835 char buff
[CFMaxPathSize
];
836 CFURLRef newURL
= NULL
;
838 if (!CFURLGetFileSystemRepresentation(bundleURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) return NULL
;
840 newURL
= CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault
, (uint8_t *)buff
, strlen(buff
), true);
841 if (!newURL
) newURL
= (CFURLRef
)CFRetain(bundleURL
);
842 bundle
= _CFBundleFindByURL(newURL
, false);
847 static CFBundleRef
_CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
, Boolean alreadyLocked
, Boolean doFinalProcessing
) {
848 CFBundleRef bundle
= NULL
;
849 char buff
[CFMaxPathSize
];
850 CFDateRef modDate
= NULL
;
851 Boolean exists
= false;
853 CFURLRef newURL
= NULL
;
854 uint8_t localVersion
= 0;
856 if (!CFURLGetFileSystemRepresentation(bundleURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) return NULL
;
858 newURL
= CFURLCreateFromFileSystemRepresentation(allocator
, (uint8_t *)buff
, strlen(buff
), true);
859 if (!newURL
) newURL
= (CFURLRef
)CFRetain(bundleURL
);
860 bundle
= _CFBundleFindByURL(newURL
, alreadyLocked
);
867 if (!_CFBundleURLLooksLikeBundleVersion(newURL
, &localVersion
)) {
869 if (_CFGetFileProperties(allocator
, newURL
, &exists
, &mode
, NULL
, &modDate
, NULL
, NULL
) == 0) {
870 if (!exists
|| ((mode
& S_IFMT
) != S_IFDIR
)) {
871 if (modDate
) CFRelease(modDate
);
881 bundle
= (CFBundleRef
)_CFRuntimeCreateInstance(allocator
, __kCFBundleTypeID
, sizeof(struct __CFBundle
) - sizeof(CFRuntimeBase
), NULL
);
887 bundle
->_url
= newURL
;
889 bundle
->_modDate
= modDate
;
890 bundle
->_version
= localVersion
;
891 bundle
->_infoDict
= NULL
;
892 bundle
->_localInfoDict
= NULL
;
893 bundle
->_searchLanguages
= NULL
;
895 #if defined(BINARY_SUPPORT_DYLD)
896 /* We'll have to figure it out later */
897 bundle
->_binaryType
= __CFBundleUnknownBinary
;
898 #elif defined(BINARY_SUPPORT_CFM)
899 /* We support CFM only */
900 bundle
->_binaryType
= __CFBundleCFMBinary
;
901 #elif defined(BINARY_SUPPORT_DLL)
902 /* We support DLL only */
903 bundle
->_binaryType
= __CFBundleDLLBinary
;
904 bundle
->_hModule
= NULL
;
906 /* We'll have to figure it out later */
907 bundle
->_binaryType
= __CFBundleUnknownBinary
;
908 #endif /* BINARY_SUPPORT_DYLD */
910 bundle
->_isLoaded
= false;
911 bundle
->_sharesStringsFiles
= false;
913 if (!getenv("CFBundleDisableStringsSharing") &&
914 #if DEPLOYMENT_TARGET_MACOSX
915 (strncmp(buff
, "/System/Library/Frameworks", 26) == 0) &&
917 (strncmp(buff
+ strlen(buff
) - 10, ".framework", 10) == 0)) bundle
->_sharesStringsFiles
= true;
919 bundle
->_connectionCookie
= NULL
;
920 bundle
->_handleCookie
= NULL
;
921 bundle
->_imageCookie
= NULL
;
922 bundle
->_moduleCookie
= NULL
;
924 bundle
->_glueDict
= NULL
;
926 #if defined(BINARY_SUPPORT_CFM)
927 bundle
->_resourceData
._executableLacksResourceFork
= false;
928 #else /* BINARY_SUPPORT_CFM */
929 bundle
->_resourceData
._executableLacksResourceFork
= true;
930 #endif /* BINARY_SUPPORT_CFM */
931 bundle
->_resourceData
._infoDictionaryFromResourceFork
= false;
932 bundle
->_resourceData
._stringTableCache
= NULL
;
934 bundle
->_plugInData
._isPlugIn
= false;
935 bundle
->_plugInData
._loadOnDemand
= false;
936 bundle
->_plugInData
._isDoingDynamicRegistration
= false;
937 bundle
->_plugInData
._instanceCount
= 0;
938 bundle
->_plugInData
._factories
= NULL
;
940 CFBundleGetInfoDictionary(bundle
);
942 _CFBundleAddToTables(bundle
, alreadyLocked
);
944 if (doFinalProcessing
) {
945 _CFBundleCheckWorkarounds(bundle
);
946 if (_CFBundleNeedsInitPlugIn(bundle
)) {
947 if (alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
948 _CFBundleInitPlugIn(bundle
);
949 if (alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
956 CFBundleRef
CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
) {return _CFBundleCreate(allocator
, bundleURL
, false, true);}
958 CFArrayRef
CFBundleCreateBundlesFromDirectory(CFAllocatorRef alloc
, CFURLRef directoryURL
, CFStringRef bundleType
) {
959 CFMutableArrayRef bundles
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
);
960 CFArrayRef URLs
= _CFContentsOfDirectory(alloc
, NULL
, NULL
, directoryURL
, bundleType
);
962 CFIndex i
, c
= CFArrayGetCount(URLs
);
964 CFBundleRef curBundle
;
966 for (i
= 0; i
< c
; i
++) {
967 curURL
= (CFURLRef
)CFArrayGetValueAtIndex(URLs
, i
);
968 curBundle
= CFBundleCreate(alloc
, curURL
);
969 if (curBundle
) CFArrayAppendValue(bundles
, curBundle
);
977 CFURLRef
CFBundleCopyBundleURL(CFBundleRef bundle
) {
979 CFRetain(bundle
->_url
);
984 void _CFBundleSetDefaultLocalization(CFStringRef localizationName
) {
985 CFStringRef newLocalization
= localizationName
? (CFStringRef
)CFStringCreateCopy(kCFAllocatorSystemDefault
, localizationName
) : NULL
;
986 if (_defaultLocalization
) CFRelease(_defaultLocalization
);
987 _defaultLocalization
= newLocalization
;
990 CFArrayRef
_CFBundleGetLanguageSearchList(CFBundleRef bundle
) {
991 if (!bundle
->_searchLanguages
) {
992 CFMutableArrayRef langs
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
993 CFStringRef devLang
= CFBundleGetDevelopmentRegion(bundle
);
995 _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
, bundle
->_infoDict
, langs
, devLang
);
997 if (CFArrayGetCount(langs
) == 0) {
998 // If the user does not prefer any of our languages, and devLang is not present, try English
999 _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
, bundle
->_infoDict
, langs
, CFSTR("en_US"));
1001 if (CFArrayGetCount(langs
) == 0) {
1002 // if none of the preferred localizations are present, fall back on a random localization that is present
1003 CFArrayRef localizations
= CFBundleCopyBundleLocalizations(bundle
);
1004 if (localizations
) {
1005 if (CFArrayGetCount(localizations
) > 0) {
1006 _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
, bundle
->_infoDict
, langs
, (CFStringRef
)CFArrayGetValueAtIndex(localizations
, 0));
1008 CFRelease(localizations
);
1012 if (devLang
&& !CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), devLang
)) {
1013 // Make sure that devLang is on the list as a fallback for individual resources that are not present
1014 CFArrayAppendValue(langs
, devLang
);
1015 } else if (!devLang
) {
1016 // Or if there is no devLang, try some variation of English that is present
1017 CFArrayRef localizations
= CFBundleCopyBundleLocalizations(bundle
);
1018 if (localizations
) {
1019 CFStringRef en_US
= CFSTR("en_US"), en
= CFSTR("en"), English
= CFSTR("English");
1020 CFRange range
= CFRangeMake(0, CFArrayGetCount(localizations
));
1021 if (CFArrayContainsValue(localizations
, range
, en
)) {
1022 if (!CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), en
)) CFArrayAppendValue(langs
, en
);
1023 } else if (CFArrayContainsValue(localizations
, range
, English
)) {
1024 if (!CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), English
)) CFArrayAppendValue(langs
, English
);
1025 } else if (CFArrayContainsValue(localizations
, range
, en_US
)) {
1026 if (!CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), en_US
)) CFArrayAppendValue(langs
, en_US
);
1028 CFRelease(localizations
);
1031 if (CFArrayGetCount(langs
) == 0) {
1032 // Total backstop behavior to avoid having an empty array.
1033 if (_defaultLocalization
) {
1034 CFArrayAppendValue(langs
, _defaultLocalization
);
1036 CFArrayAppendValue(langs
, CFSTR("en"));
1039 bundle
->_searchLanguages
= langs
;
1041 return bundle
->_searchLanguages
;
1044 CFDictionaryRef
CFBundleCopyInfoDictionaryInDirectory(CFURLRef url
) {return _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault
, url
, NULL
);}
1046 CFDictionaryRef
CFBundleGetInfoDictionary(CFBundleRef bundle
) {
1047 if (!bundle
->_infoDict
) bundle
->_infoDict
= _CFBundleCopyInfoDictionaryInDirectoryWithVersion(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
);
1048 return bundle
->_infoDict
;
1051 CFDictionaryRef
_CFBundleGetLocalInfoDictionary(CFBundleRef bundle
) {return CFBundleGetLocalInfoDictionary(bundle
);}
1053 CFDictionaryRef
CFBundleGetLocalInfoDictionary(CFBundleRef bundle
) {
1054 if (!bundle
->_localInfoDict
) {
1055 CFURLRef url
= CFBundleCopyResourceURL(bundle
, _CFBundleLocalInfoName
, _CFBundleStringTableType
, NULL
);
1059 CFStringRef errStr
= NULL
;
1061 if (CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(bundle
), url
, &data
, NULL
, NULL
, &errCode
)) {
1062 bundle
->_localInfoDict
= (CFDictionaryRef
)CFPropertyListCreateFromXMLData(CFGetAllocator(bundle
), data
, kCFPropertyListImmutable
, &errStr
);
1063 if (errStr
) CFRelease(errStr
);
1064 if (bundle
->_localInfoDict
&& CFDictionaryGetTypeID() != CFGetTypeID(bundle
->_localInfoDict
)) {
1065 CFRelease(bundle
->_localInfoDict
);
1066 bundle
->_localInfoDict
= NULL
;
1073 return bundle
->_localInfoDict
;
1076 CFPropertyListRef
_CFBundleGetValueForInfoKey(CFBundleRef bundle
, CFStringRef key
) {return (CFPropertyListRef
)CFBundleGetValueForInfoDictionaryKey(bundle
, key
);}
1078 CFTypeRef
CFBundleGetValueForInfoDictionaryKey(CFBundleRef bundle
, CFStringRef key
) {
1079 // Look in InfoPlist.strings first. Then look in Info.plist
1080 CFTypeRef result
= NULL
;
1081 if (bundle
&& key
) {
1082 CFDictionaryRef dict
= CFBundleGetLocalInfoDictionary(bundle
);
1083 if (dict
) result
= CFDictionaryGetValue(dict
, key
);
1085 dict
= CFBundleGetInfoDictionary(bundle
);
1086 if (dict
) result
= CFDictionaryGetValue(dict
, key
);
1092 CFStringRef
CFBundleGetIdentifier(CFBundleRef bundle
) {
1093 CFStringRef bundleID
= NULL
;
1094 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1095 if (infoDict
) bundleID
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleIdentifierKey
);
1099 #define DEVELOPMENT_STAGE 0x20
1100 #define ALPHA_STAGE 0x40
1101 #define BETA_STAGE 0x60
1102 #define RELEASE_STAGE 0x80
1104 #define MAX_VERS_LEN 10
1106 CF_INLINE Boolean
_isDigit(UniChar aChar
) {return (((aChar
>= (UniChar
)'0') && (aChar
<= (UniChar
)'9')) ? true : false);}
1108 __private_extern__ CFStringRef
_CFCreateStringFromVersionNumber(CFAllocatorRef alloc
, UInt32 vers
) {
1109 CFStringRef result
= NULL
;
1110 uint8_t major1
, major2
, minor1
, minor2
, stage
, build
;
1112 major1
= (vers
& 0xF0000000) >> 28;
1113 major2
= (vers
& 0x0F000000) >> 24;
1114 minor1
= (vers
& 0x00F00000) >> 20;
1115 minor2
= (vers
& 0x000F0000) >> 16;
1116 stage
= (vers
& 0x0000FF00) >> 8;
1117 build
= (vers
& 0x000000FF);
1119 if (stage
== RELEASE_STAGE
) {
1121 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d%d.%d.%d"), major1
, major2
, minor1
, minor2
);
1123 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d.%d.%d"), major2
, minor1
, minor2
);
1127 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d%d.%d.%d%s%d"), major1
, major2
, minor1
, minor2
, ((stage
== DEVELOPMENT_STAGE
) ? "d" : ((stage
== ALPHA_STAGE
) ? "a" : "b")), build
);
1129 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d.%d.%d%s%d"), major2
, minor1
, minor2
, ((stage
== DEVELOPMENT_STAGE
) ? "d" : ((stage
== ALPHA_STAGE
) ? "a" : "b")), build
);
1135 __private_extern__ UInt32
_CFVersionNumberFromString(CFStringRef versStr
) {
1136 // Parse version number from string.
1137 // String can begin with "." for major version number 0. String can end at any point, but elements within the string cannot be skipped.
1138 UInt32 major1
= 0, major2
= 0, minor1
= 0, minor2
= 0, stage
= RELEASE_STAGE
, build
= 0;
1139 UniChar versChars
[MAX_VERS_LEN
];
1140 UniChar
*chars
= NULL
;
1143 Boolean digitsDone
= false;
1145 if (!versStr
) return 0;
1147 len
= CFStringGetLength(versStr
);
1149 if ((len
== 0) || (len
> MAX_VERS_LEN
)) return 0;
1151 CFStringGetCharacters(versStr
, CFRangeMake(0, len
), versChars
);
1154 // Get major version number.
1155 major1
= major2
= 0;
1156 if (_isDigit(*chars
)) {
1157 major2
= *chars
- (UniChar
)'0';
1161 if (_isDigit(*chars
)) {
1163 major2
= *chars
- (UniChar
)'0';
1167 if (*chars
== (UniChar
)'.') {
1174 } else if (*chars
== (UniChar
)'.') {
1181 } else if (*chars
== (UniChar
)'.') {
1188 // Now major1 and major2 contain first and second digit of the major version number as ints.
1189 // Now either len is 0 or chars points at the first char beyond the first decimal point.
1191 // Get the first minor version number.
1192 if (len
> 0 && !digitsDone
) {
1193 if (_isDigit(*chars
)) {
1194 minor1
= *chars
- (UniChar
)'0';
1198 if (*chars
== (UniChar
)'.') {
1210 // Now minor1 contains the first minor version number as an int.
1211 // Now either len is 0 or chars points at the first char beyond the second decimal point.
1213 // Get the second minor version number.
1214 if (len
> 0 && !digitsDone
) {
1215 if (_isDigit(*chars
)) {
1216 minor2
= *chars
- (UniChar
)'0';
1224 // Now minor2 contains the second minor version number as an int.
1225 // Now either len is 0 or chars points at the build stage letter.
1227 // Get the build stage letter. We must find 'd', 'a', 'b', or 'f' next, if there is anything next.
1229 if (*chars
== (UniChar
)'d') {
1230 stage
= DEVELOPMENT_STAGE
;
1231 } else if (*chars
== (UniChar
)'a') {
1232 stage
= ALPHA_STAGE
;
1233 } else if (*chars
== (UniChar
)'b') {
1235 } else if (*chars
== (UniChar
)'f') {
1236 stage
= RELEASE_STAGE
;
1244 // Now stage contains the release stage.
1245 // Now either len is 0 or chars points at the build number.
1247 // Get the first digit of the build number.
1249 if (_isDigit(*chars
)) {
1250 build
= *chars
- (UniChar
)'0';
1257 // Get the second digit of the build number.
1259 if (_isDigit(*chars
)) {
1261 build
+= *chars
- (UniChar
)'0';
1268 // Get the third digit of the build number.
1270 if (_isDigit(*chars
)) {
1272 build
+= *chars
- (UniChar
)'0';
1280 // Range check the build number and make sure we exhausted the string.
1281 if ((build
> 0xFF) || (len
> 0)) return 0;
1284 theVers
= major1
<< 28;
1285 theVers
+= major2
<< 24;
1286 theVers
+= minor1
<< 20;
1287 theVers
+= minor2
<< 16;
1288 theVers
+= stage
<< 8;
1294 UInt32
CFBundleGetVersionNumber(CFBundleRef bundle
) {
1295 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1296 CFTypeRef unknownVersionValue
= CFDictionaryGetValue(infoDict
, _kCFBundleNumericVersionKey
);
1297 CFNumberRef versNum
;
1300 if (!unknownVersionValue
) unknownVersionValue
= CFDictionaryGetValue(infoDict
, kCFBundleVersionKey
);
1301 if (unknownVersionValue
) {
1302 if (CFGetTypeID(unknownVersionValue
) == CFStringGetTypeID()) {
1303 // Convert a string version number into a numeric one.
1304 vers
= _CFVersionNumberFromString((CFStringRef
)unknownVersionValue
);
1306 versNum
= CFNumberCreate(CFGetAllocator(bundle
), kCFNumberSInt32Type
, &vers
);
1307 CFDictionarySetValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleNumericVersionKey
, versNum
);
1309 } else if (CFGetTypeID(unknownVersionValue
) == CFNumberGetTypeID()) {
1310 CFNumberGetValue((CFNumberRef
)unknownVersionValue
, kCFNumberSInt32Type
, &vers
);
1312 CFDictionaryRemoveValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleNumericVersionKey
);
1318 CFStringRef
CFBundleGetDevelopmentRegion(CFBundleRef bundle
) {
1319 CFStringRef devLang
= NULL
;
1320 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1322 devLang
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleDevelopmentRegionKey
);
1323 if (devLang
&& (CFGetTypeID(devLang
) != CFStringGetTypeID() || CFStringGetLength(devLang
) == 0)) {
1325 CFDictionaryRemoveValue((CFMutableDictionaryRef
)infoDict
, kCFBundleDevelopmentRegionKey
);
1332 Boolean
_CFBundleGetHasChanged(CFBundleRef bundle
) {
1334 Boolean result
= false;
1335 Boolean exists
= false;
1338 if (_CFGetFileProperties(CFGetAllocator(bundle
), bundle
->_url
, &exists
, &mode
, NULL
, &modDate
, NULL
, NULL
) == 0) {
1339 // If the bundle no longer exists or is not a folder, it must have "changed"
1340 if (!exists
|| ((mode
& S_IFMT
) != S_IFDIR
)) result
= true;
1342 // Something is wrong. The stat failed.
1345 if (bundle
->_modDate
&& !CFEqual(bundle
->_modDate
, modDate
)) {
1346 // mod date is different from when we created.
1353 void _CFBundleSetStringsFilesShared(CFBundleRef bundle
, Boolean flag
) {
1354 bundle
->_sharesStringsFiles
= flag
;
1357 Boolean
_CFBundleGetStringsFilesShared(CFBundleRef bundle
) {
1358 return bundle
->_sharesStringsFiles
;
1361 static Boolean
_urlExists(CFAllocatorRef alloc
, CFURLRef url
) {
1363 return url
&& (0 == _CFGetFileProperties(alloc
, url
, &exists
, NULL
, NULL
, NULL
, NULL
, NULL
)) && exists
;
1366 __private_extern__ CFURLRef
_CFBundleCopySupportFilesDirectoryURLInDirectory(CFAllocatorRef alloc
, CFURLRef bundleURL
, uint8_t version
) {
1367 CFURLRef result
= NULL
;
1370 result
= CFURLCreateWithString(alloc
, _CFBundleSupportFilesURLFromBase1
, bundleURL
);
1371 } else if (2 == version
) {
1372 result
= CFURLCreateWithString(alloc
, _CFBundleSupportFilesURLFromBase2
, bundleURL
);
1374 result
= (CFURLRef
)CFRetain(bundleURL
);
1380 CF_EXPORT CFURLRef
CFBundleCopySupportFilesDirectoryURL(CFBundleRef bundle
) {return _CFBundleCopySupportFilesDirectoryURLInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
);}
1382 __private_extern__ CFURLRef
_CFBundleCopyResourcesDirectoryURLInDirectory(CFAllocatorRef alloc
, CFURLRef bundleURL
, uint8_t version
) {
1383 CFURLRef result
= NULL
;
1386 result
= CFURLCreateWithString(alloc
, _CFBundleResourcesURLFromBase0
, bundleURL
);
1387 } else if (1 == version
) {
1388 result
= CFURLCreateWithString(alloc
, _CFBundleResourcesURLFromBase1
, bundleURL
);
1389 } else if (2 == version
) {
1390 result
= CFURLCreateWithString(alloc
, _CFBundleResourcesURLFromBase2
, bundleURL
);
1392 result
= (CFURLRef
)CFRetain(bundleURL
);
1398 CFURLRef
CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle
) {return _CFBundleCopyResourcesDirectoryURLInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
);}
1400 static CFURLRef
_CFBundleCopyExecutableURLRaw(CFAllocatorRef alloc
, CFURLRef urlPath
, CFStringRef exeName
) {
1401 // Given an url to a folder and a name, this returns the url to the executable in that folder with that name, if it exists, and NULL otherwise. This function deals with appending the ".exe" or ".dll" on Windows.
1402 CFURLRef executableURL
= NULL
;
1403 if (!urlPath
|| !exeName
) return NULL
;
1405 #if DEPLOYMENT_TARGET_MACOSX
1406 const uint8_t *image_suffix
= (uint8_t *)getenv("DYLD_IMAGE_SUFFIX");
1408 CFStringRef newExeName
, imageSuffix
;
1409 imageSuffix
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, (char *)image_suffix
, kCFStringEncodingUTF8
);
1410 if (CFStringHasSuffix(exeName
, CFSTR(".dylib"))) {
1411 CFStringRef bareExeName
= CFStringCreateWithSubstring(alloc
, exeName
, CFRangeMake(0, CFStringGetLength(exeName
)-6));
1412 newExeName
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%@%@.dylib"), exeName
, imageSuffix
);
1413 CFRelease(bareExeName
);
1415 newExeName
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%@%@"), exeName
, imageSuffix
);
1417 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(alloc
, newExeName
, kCFURLPOSIXPathStyle
, false, urlPath
);
1418 if (executableURL
&& !_urlExists(alloc
, executableURL
)) {
1419 CFRelease(executableURL
);
1420 executableURL
= NULL
;
1422 CFRelease(newExeName
);
1423 CFRelease(imageSuffix
);
1426 if (!executableURL
) {
1427 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(alloc
, exeName
, kCFURLPOSIXPathStyle
, false, urlPath
);
1428 if (executableURL
&& !_urlExists(alloc
, executableURL
)) {
1429 CFRelease(executableURL
);
1430 executableURL
= NULL
;
1433 return executableURL
;
1436 static CFStringRef
_CFBundleCopyExecutableName(CFAllocatorRef alloc
, CFBundleRef bundle
, CFURLRef url
, CFDictionaryRef infoDict
) {
1437 CFStringRef executableName
= NULL
;
1439 if (!alloc
&& bundle
) alloc
= CFGetAllocator(bundle
);
1440 if (!infoDict
&& bundle
) infoDict
= CFBundleGetInfoDictionary(bundle
);
1441 if (!url
&& bundle
) url
= bundle
->_url
;
1444 // Figure out the name of the executable.
1445 // First try for the new key in the plist.
1446 executableName
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleExecutableKey
);
1447 // Second try for the old key in the plist.
1448 if (!executableName
) executableName
= (CFStringRef
)CFDictionaryGetValue(infoDict
, _kCFBundleOldExecutableKey
);
1449 if (executableName
&& CFGetTypeID(executableName
) == CFStringGetTypeID() && CFStringGetLength(executableName
) > 0) {
1450 CFRetain(executableName
);
1452 executableName
= NULL
;
1455 if (!executableName
&& url
) {
1456 // Third, take the name of the bundle itself (with path extension stripped)
1457 CFURLRef absoluteURL
= CFURLCopyAbsoluteURL(url
);
1458 CFStringRef bundlePath
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
);
1459 UniChar buff
[CFMaxPathSize
];
1460 CFIndex len
= CFStringGetLength(bundlePath
);
1461 CFIndex startOfBundleName
, endOfBundleName
;
1463 CFRelease(absoluteURL
);
1464 if (len
> CFMaxPathSize
) len
= CFMaxPathSize
;
1465 CFStringGetCharacters(bundlePath
, CFRangeMake(0, len
), buff
);
1466 startOfBundleName
= _CFStartOfLastPathComponent(buff
, len
);
1467 endOfBundleName
= _CFLengthAfterDeletingPathExtension(buff
, len
);
1469 if ((startOfBundleName
<= len
) && (endOfBundleName
<= len
) && (startOfBundleName
< endOfBundleName
)) {
1470 executableName
= CFStringCreateWithCharacters(alloc
, &(buff
[startOfBundleName
]), (endOfBundleName
- startOfBundleName
));
1472 CFRelease(bundlePath
);
1475 return executableName
;
1478 __private_extern__ CFURLRef
_CFBundleCopyResourceForkURLMayBeLocal(CFBundleRef bundle
, Boolean mayBeLocal
) {
1479 CFStringRef executableName
= _CFBundleCopyExecutableName(kCFAllocatorSystemDefault
, bundle
, NULL
, NULL
);
1480 CFURLRef resourceForkURL
= NULL
;
1481 if (executableName
) {
1483 resourceForkURL
= CFBundleCopyResourceURL(bundle
, executableName
, CFSTR("rsrc"), NULL
);
1485 resourceForkURL
= CFBundleCopyResourceURLForLocalization(bundle
, executableName
, CFSTR("rsrc"), NULL
, NULL
);
1487 CFRelease(executableName
);
1490 return resourceForkURL
;
1493 CFURLRef
_CFBundleCopyResourceForkURL(CFBundleRef bundle
) {return _CFBundleCopyResourceForkURLMayBeLocal(bundle
, true);}
1495 static CFURLRef
_CFBundleCopyExecutableURLInDirectoryWithAllocator(CFAllocatorRef alloc
, CFBundleRef bundle
, CFURLRef url
, CFStringRef executableName
, Boolean ignoreCache
, Boolean useOtherPlatform
) {
1496 uint8_t version
= 0;
1497 CFDictionaryRef infoDict
= NULL
;
1498 CFStringRef executablePath
= NULL
;
1499 CFURLRef executableURL
= NULL
;
1500 Boolean foundIt
= false;
1501 Boolean lookupMainExe
= (executableName
? false : true);
1504 infoDict
= CFBundleGetInfoDictionary(bundle
);
1505 version
= bundle
->_version
;
1507 infoDict
= _CFBundleCopyInfoDictionaryInDirectory(alloc
, url
, &version
);
1510 // If we have a bundle instance and an info dict, see if we have already cached the path
1511 if (lookupMainExe
&& !ignoreCache
&& !useOtherPlatform
&& bundle
&& infoDict
) {
1512 executablePath
= (CFStringRef
)CFDictionaryGetValue(infoDict
, _kCFBundleExecutablePathKey
);
1513 if (executablePath
) {
1514 #if DEPLOYMENT_TARGET_MACOSX
1515 executableURL
= CFURLCreateWithFileSystemPath(alloc
, executablePath
, kCFURLPOSIXPathStyle
, false);
1517 if (executableURL
) foundIt
= true;
1519 executablePath
= NULL
;
1520 CFDictionaryRemoveValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleExecutablePathKey
);
1526 if (lookupMainExe
) {
1527 executableName
= _CFBundleCopyExecutableName(alloc
, bundle
, url
, infoDict
);
1529 if (executableName
) {
1530 #if DEPLOYMENT_TARGET_MACOSX
1531 Boolean doExecSearch
= true;
1533 // Now, look for the executable inside the bundle.
1534 if (doExecSearch
&& 0 != version
) {
1536 CFURLRef exeSubdirURL
;
1539 exeDirURL
= CFURLCreateWithString(alloc
, _CFBundleExecutablesURLFromBase1
, url
);
1540 } else if (2 == version
) {
1541 exeDirURL
= CFURLCreateWithString(alloc
, _CFBundleExecutablesURLFromBase2
, url
);
1543 #if DEPLOYMENT_TARGET_MACOSX
1544 exeDirURL
= (CFURLRef
)CFRetain(url
);
1547 CFStringRef platformSubDir
= useOtherPlatform
? _CFBundleGetOtherPlatformExecutablesSubdirectoryName() : _CFBundleGetPlatformExecutablesSubdirectoryName();
1548 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(alloc
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1549 executableURL
= _CFBundleCopyExecutableURLRaw(alloc
, exeSubdirURL
, executableName
);
1550 if (!executableURL
) {
1551 CFRelease(exeSubdirURL
);
1552 platformSubDir
= useOtherPlatform
? _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetAlternatePlatformExecutablesSubdirectoryName();
1553 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(alloc
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1554 executableURL
= _CFBundleCopyExecutableURLRaw(alloc
, exeSubdirURL
, executableName
);
1556 if (!executableURL
) {
1557 CFRelease(exeSubdirURL
);
1558 platformSubDir
= useOtherPlatform
? _CFBundleGetPlatformExecutablesSubdirectoryName() : _CFBundleGetOtherPlatformExecutablesSubdirectoryName();
1559 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(alloc
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1560 executableURL
= _CFBundleCopyExecutableURLRaw(alloc
, exeSubdirURL
, executableName
);
1562 if (!executableURL
) {
1563 CFRelease(exeSubdirURL
);
1564 platformSubDir
= useOtherPlatform
? _CFBundleGetAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName();
1565 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(alloc
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1566 executableURL
= _CFBundleCopyExecutableURLRaw(alloc
, exeSubdirURL
, executableName
);
1568 if (!executableURL
) {
1569 executableURL
= _CFBundleCopyExecutableURLRaw(alloc
, exeDirURL
, executableName
);
1572 CFRelease(exeDirURL
);
1573 CFRelease(exeSubdirURL
);
1576 // If this was an old bundle, or we did not find the executable in the Excutables subdirectory, look directly in the bundle wrapper.
1577 if (!executableURL
) executableURL
= _CFBundleCopyExecutableURLRaw(alloc
, url
, executableName
);
1579 if (lookupMainExe
&& !ignoreCache
&& !useOtherPlatform
&& bundle
&& infoDict
&& executableURL
) {
1580 // We found it. Cache the path.
1581 CFURLRef absURL
= CFURLCopyAbsoluteURL(executableURL
);
1582 #if DEPLOYMENT_TARGET_MACOSX
1583 executablePath
= CFURLCopyFileSystemPath(absURL
, kCFURLPOSIXPathStyle
);
1586 CFDictionarySetValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleExecutablePathKey
, executablePath
);
1587 CFRelease(executablePath
);
1589 if (lookupMainExe
&& !useOtherPlatform
&& bundle
&& !executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
1590 if (lookupMainExe
) CFRelease(executableName
);
1594 if (!bundle
&& infoDict
) CFRelease(infoDict
);
1596 return executableURL
;
1599 CFURLRef
_CFBundleCopyExecutableURLInDirectory(CFURLRef url
) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(kCFAllocatorSystemDefault
, NULL
, url
, NULL
, true, false);}
1601 CFURLRef
_CFBundleCopyOtherExecutableURLInDirectory(CFURLRef url
) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(kCFAllocatorSystemDefault
, NULL
, url
, NULL
, true, true);}
1603 CFURLRef
CFBundleCopyExecutableURL(CFBundleRef bundle
) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle
), bundle
, bundle
->_url
, NULL
, false, false);}
1605 static CFURLRef
_CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle
) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle
), bundle
, bundle
->_url
, NULL
, true, false);}
1607 CFURLRef
CFBundleCopyAuxiliaryExecutableURL(CFBundleRef bundle
, CFStringRef executableName
) {return _CFBundleCopyExecutableURLInDirectoryWithAllocator(CFGetAllocator(bundle
), bundle
, bundle
->_url
, executableName
, true, false);}
1609 Boolean
CFBundleIsExecutableLoaded(CFBundleRef bundle
) {return bundle
->_isLoaded
;}
1611 CFBundleExecutableType
CFBundleGetExecutableType(CFBundleRef bundle
) {
1612 CFBundleExecutableType result
= kCFBundleOtherExecutableType
;
1613 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
1615 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
1616 #if defined(BINARY_SUPPORT_DYLD)
1617 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
1618 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
1619 #if defined(BINARY_SUPPORT_CFM)
1620 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
1621 #endif /* BINARY_SUPPORT_CFM */
1623 #endif /* BINARY_SUPPORT_DYLD */
1624 if (executableURL
) CFRelease(executableURL
);
1626 if (bundle
->_binaryType
== __CFBundleCFMBinary
) {
1627 result
= kCFBundlePEFExecutableType
;
1628 } else if (bundle
->_binaryType
== __CFBundleDYLDExecutableBinary
|| bundle
->_binaryType
== __CFBundleDYLDBundleBinary
|| bundle
->_binaryType
== __CFBundleDYLDFrameworkBinary
) {
1629 result
= kCFBundleMachOExecutableType
;
1630 } else if (bundle
->_binaryType
== __CFBundleDLLBinary
) {
1631 result
= kCFBundleDLLExecutableType
;
1632 } else if (bundle
->_binaryType
== __CFBundleELFBinary
) {
1633 result
= kCFBundleELFExecutableType
;
1638 #define UNKNOWN_FILETYPE 0x0
1639 #define PEF_FILETYPE 0x1000
1640 #define PEF_MAGIC 0x4a6f7921
1641 #define PEF_CIGAM 0x21796f4a
1642 #define TEXT_SEGMENT "__TEXT"
1643 #define PLIST_SECTION "__info_plist"
1644 #define OBJC_SEGMENT "__OBJC"
1645 #define IMAGE_INFO_SECTION "__image_info"
1646 #define LIB_X11 "/usr/X11R6/lib/libX"
1648 #define XLS_NAME "Book"
1649 #define XLS_NAME2 "Workbook"
1650 #define DOC_NAME "WordDocument"
1651 #define PPT_NAME "PowerPoint Document"
1653 #define ustrncmp(x, y, z) strncmp((char *)(x), (char *)(y), (z))
1654 #define ustrncasecmp(x, y, z) strncasecmp_l((char *)(x), (char *)(y), (z), NULL)
1656 static const uint32_t __CFBundleMagicNumbersArray
[] = {
1657 0xcafebabe, 0xbebafeca, 0xfeedface, 0xcefaedfe, 0xfeedfacf, 0xcffaedfe, 0x4a6f7921, 0x21796f4a,
1658 0x7f454c46, 0xffd8ffe0, 0x4d4d002a, 0x49492a00, 0x47494638, 0x89504e47, 0x69636e73, 0x00000100,
1659 0x7b5c7274, 0x25504446, 0x2e7261fd, 0x2e524d46, 0x2e736e64, 0x2e736400, 0x464f524d, 0x52494646,
1660 0x38425053, 0x000001b3, 0x000001ba, 0x4d546864, 0x504b0304, 0x53495421, 0x53495432, 0x53495435,
1661 0x53495444, 0x53747566, 0x30373037, 0x3c212d2d, 0x25215053, 0xd0cf11e0, 0x62656769, 0x3d796265,
1662 0x6b6f6c79, 0x3026b275, 0x0000000c, 0xfe370023, 0x09020600, 0x09040600, 0x4f676753, 0x664c6143,
1663 0x00010000, 0x74727565, 0x4f54544f, 0x41433130, 0xc809fe02, 0x0809fe02, 0x2356524d, 0x67696d70,
1664 0x3c435058, 0x28445746, 0x424f4d53, 0x49544f4c, 0x72746664
1667 // string, with groups of 5 characters being 1 element in the array
1668 static const char * __CFBundleExtensionsArray
=
1669 "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "pef\0\0" "pef\0\0"
1670 "elf\0\0" "jpeg\0" "tiff\0" "tiff\0" "gif\0\0" "png\0\0" "icns\0" "ico\0\0"
1671 "rtf\0\0" "pdf\0\0" "ra\0\0\0""rm\0\0\0""au\0\0\0""au\0\0\0""iff\0\0" "riff\0"
1672 "psd\0\0" "mpeg\0" "mpeg\0" "mid\0\0" "zip\0\0" "sit\0\0" "sit\0\0" "sit\0\0"
1673 "sit\0\0" "sit\0\0" "cpio\0" "html\0" "ps\0\0\0""ole\0\0" "uu\0\0\0""ync\0\0"
1674 "dmg\0\0" "wmv\0\0" "jp2\0\0" "doc\0\0" "xls\0\0" "xls\0\0" "ogg\0\0" "flac\0"
1675 "ttf\0\0" "ttf\0\0" "otf\0\0" "dwg\0\0" "dgn\0\0" "dgn\0\0" "wrl\0\0" "xcf\0\0"
1676 "cpx\0\0" "dwf\0\0" "bom\0\0" "lit\0\0" "rtfd\0";
1678 static const char * __CFBundleOOExtensionsArray
= "sxc\0\0" "sxd\0\0" "sxg\0\0" "sxi\0\0" "sxm\0\0" "sxw\0\0";
1679 static const char * __CFBundleODExtensionsArray
= "odc\0\0" "odf\0\0" "odg\0\0" "oth\0\0" "odi\0\0" "odm\0\0" "odp\0\0" "ods\0\0" "odt\0\0";
1681 #define EXTENSION_LENGTH 5
1682 #define NUM_EXTENSIONS 61
1683 #define MAGIC_BYTES_TO_READ 512
1684 #define DMG_BYTES_TO_READ 512
1685 #define ZIP_BYTES_TO_READ 1024
1686 #define OLE_BYTES_TO_READ 512
1687 #define X11_BYTES_TO_READ 4096
1688 #define IMAGE_INFO_BYTES_TO_READ 4096
1690 #if defined(BINARY_SUPPORT_DYLD)
1692 CF_INLINE
uint32_t _CFBundleSwapInt32Conditional(uint32_t arg
, Boolean swap
) {return swap
? CFSwapInt32(arg
) : arg
;}
1693 CF_INLINE
uint32_t _CFBundleSwapInt64Conditional(uint64_t arg
, Boolean swap
) {return swap
? CFSwapInt64(arg
) : arg
;}
1695 static CFDictionaryRef
_CFBundleGrokInfoDictFromData(const char *bytes
, uint32_t length
) {
1696 CFMutableDictionaryRef result
= NULL
;
1697 CFDataRef infoData
= NULL
;
1698 if (bytes
&& 0 < length
) {
1699 infoData
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, (uint8_t *)bytes
, length
, kCFAllocatorNull
);
1701 result
= (CFMutableDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, infoData
, kCFPropertyListMutableContainers
, NULL
);
1702 if (result
&& CFDictionaryGetTypeID() != CFGetTypeID(result
)) {
1706 CFRelease(infoData
);
1708 if (!result
) result
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1713 static CFDictionaryRef
_CFBundleGrokInfoDictFromMainExecutable() {
1714 unsigned long length
= 0;
1715 char *bytes
= getsectdata(TEXT_SEGMENT
, PLIST_SECTION
, &length
);
1716 return _CFBundleGrokInfoDictFromData(bytes
, length
);
1719 static Boolean
_CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion
, uint32_t *objcFlags
) {
1720 Boolean retval
= false;
1721 uint32_t localVersion
= 0, localFlags
= 0;
1722 if (getsegbyname(OBJC_SEGMENT
)) {
1723 unsigned long length
= 0;
1724 char *bytes
= getsectdata(OBJC_SEGMENT
, IMAGE_INFO_SECTION
, &length
);
1725 if (bytes
&& length
>= 8) {
1726 localVersion
= *(uint32_t *)bytes
;
1727 localFlags
= *(uint32_t *)(bytes
+ 4);
1731 if (objcVersion
) *objcVersion
= localVersion
;
1732 if (objcFlags
) *objcFlags
= localFlags
;
1736 static Boolean
_CFBundleGrokX11FromFile(int fd
, const void *bytes
, CFIndex length
, uint32_t offset
, Boolean swapped
, Boolean sixtyFour
) {
1737 static const char libX11name
[] = LIB_X11
;
1738 char *buffer
= NULL
;
1739 const char *loc
= NULL
;
1741 Boolean result
= false;
1743 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
1744 buffer
= malloc(X11_BYTES_TO_READ
);
1745 if (buffer
&& read(fd
, buffer
, X11_BYTES_TO_READ
) >= X11_BYTES_TO_READ
) loc
= buffer
;
1746 } else if (bytes
&& length
>= offset
+ X11_BYTES_TO_READ
) {
1747 loc
= bytes
+ offset
;
1751 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->ncmds
, swapped
);
1752 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->sizeofcmds
, swapped
);
1753 const char *startofcmds
= loc
+ sizeof(struct mach_header_64
);
1754 const char *endofcmds
= startofcmds
+ sizeofcmds
;
1755 struct dylib_command
*dlp
= (struct dylib_command
*)startofcmds
;
1756 if (endofcmds
> loc
+ X11_BYTES_TO_READ
) endofcmds
= loc
+ X11_BYTES_TO_READ
;
1757 for (i
= 0; !result
&& i
< ncmds
&& startofcmds
<= (char *)dlp
&& (char *)dlp
< endofcmds
; i
++) {
1758 if (LC_LOAD_DYLIB
== _CFBundleSwapInt32Conditional(dlp
->cmd
, swapped
)) {
1759 uint32_t nameoffset
= _CFBundleSwapInt32Conditional(dlp
->dylib
.name
.offset
, swapped
);
1760 const char *name
= (const char *)dlp
+ nameoffset
;
1761 if (startofcmds
<= name
&& name
+ sizeof(libX11name
) <= endofcmds
&& 0 == strncmp(name
, libX11name
, sizeof(libX11name
) - 1)) result
= true;
1763 dlp
= (struct dylib_command
*)((char *)dlp
+ _CFBundleSwapInt32Conditional(dlp
->cmdsize
, swapped
));
1766 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->ncmds
, swapped
);
1767 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->sizeofcmds
, swapped
);
1768 const char *startofcmds
= loc
+ sizeof(struct mach_header
);
1769 const char *endofcmds
= startofcmds
+ sizeofcmds
;
1770 struct dylib_command
*dlp
= (struct dylib_command
*)startofcmds
;
1771 if (endofcmds
> loc
+ X11_BYTES_TO_READ
) endofcmds
= loc
+ X11_BYTES_TO_READ
;
1772 for (i
= 0; !result
&& i
< ncmds
&& startofcmds
<= (char *)dlp
&& (char *)dlp
< endofcmds
; i
++) {
1773 if (LC_LOAD_DYLIB
== _CFBundleSwapInt32Conditional(dlp
->cmd
, swapped
)) {
1774 uint32_t nameoffset
= _CFBundleSwapInt32Conditional(dlp
->dylib
.name
.offset
, swapped
);
1775 const char *name
= (const char *)dlp
+ nameoffset
;
1776 if (startofcmds
<= name
&& name
+ sizeof(libX11name
) <= endofcmds
&& 0 == strncmp(name
, libX11name
, sizeof(libX11name
) - 1)) result
= true;
1778 dlp
= (struct dylib_command
*)((char *)dlp
+ _CFBundleSwapInt32Conditional(dlp
->cmdsize
, swapped
));
1783 if (buffer
) free(buffer
);
1788 static CFDictionaryRef
_CFBundleGrokInfoDictFromFile(int fd
, const void *bytes
, CFIndex length
, uint32_t offset
, Boolean swapped
, Boolean sixtyFour
) {
1789 struct stat statBuf
;
1790 off_t fileLength
= 0;
1791 char *maploc
= NULL
;
1794 CFDictionaryRef result
= NULL
;
1795 Boolean foundit
= false;
1796 if (fd
>= 0 && fstat(fd
, &statBuf
) == 0 && (maploc
= mmap(0, statBuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0)) != (void *)-1) {
1798 fileLength
= statBuf
.st_size
;
1801 fileLength
= length
;
1803 if (fileLength
> offset
+ sizeof(struct mach_header_64
)) {
1805 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)(loc
+ offset
))->ncmds
, swapped
);
1806 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)(loc
+ offset
))->sizeofcmds
, swapped
);
1807 const char *startofcmds
= loc
+ offset
+ sizeof(struct mach_header_64
);
1808 const char *endofcmds
= startofcmds
+ sizeofcmds
;
1809 struct segment_command_64
*sgp
= (struct segment_command_64
*)startofcmds
;
1810 if (endofcmds
> loc
+ fileLength
) endofcmds
= loc
+ fileLength
;
1811 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
1812 if (LC_SEGMENT_64
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
1813 struct section_64
*sp
= (struct section_64
*)((char *)sgp
+ sizeof(struct segment_command_64
));
1814 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
1815 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
1816 if (0 == strncmp(sp
->sectname
, PLIST_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, TEXT_SEGMENT
, sizeof(sp
->segname
))) {
1817 uint64_t sectlength64
= _CFBundleSwapInt64Conditional(sp
->size
, swapped
);
1818 uint32_t sectlength
= (uint32_t)(sectlength64
& 0xffffffff);
1819 uint32_t sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
1820 const char *sectbytes
= loc
+ offset
+ sectoffset
;
1821 // we don't support huge-sized plists
1822 if (sectlength64
<= 0xffffffff && loc
<= sectbytes
&& sectbytes
+ sectlength
<= loc
+ fileLength
) result
= _CFBundleGrokInfoDictFromData(sectbytes
, sectlength
);
1825 sp
= (struct section_64
*)((char *)sp
+ sizeof(struct section_64
));
1828 sgp
= (struct segment_command_64
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
1831 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)(loc
+ offset
))->ncmds
, swapped
);
1832 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)(loc
+ offset
))->sizeofcmds
, swapped
);
1833 const char *startofcmds
= loc
+ offset
+ sizeof(struct mach_header
);
1834 const char *endofcmds
= startofcmds
+ sizeofcmds
;
1835 struct segment_command
*sgp
= (struct segment_command
*)startofcmds
;
1836 if (endofcmds
> loc
+ fileLength
) endofcmds
= loc
+ fileLength
;
1837 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
1838 if (LC_SEGMENT
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
1839 struct section
*sp
= (struct section
*)((char *)sgp
+ sizeof(struct segment_command
));
1840 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
1841 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
1842 if (0 == strncmp(sp
->sectname
, PLIST_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, TEXT_SEGMENT
, sizeof(sp
->segname
))) {
1843 uint32_t sectlength
= _CFBundleSwapInt32Conditional(sp
->size
, swapped
);
1844 uint32_t sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
1845 const char *sectbytes
= loc
+ offset
+ sectoffset
;
1846 if (loc
<= sectbytes
&& sectbytes
+ sectlength
<= loc
+ fileLength
) result
= _CFBundleGrokInfoDictFromData(sectbytes
, sectlength
);
1849 sp
= (struct section
*)((char *)sp
+ sizeof(struct section
));
1852 sgp
= (struct segment_command
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
1856 if (maploc
) munmap(maploc
, statBuf
.st_size
);
1860 static void _CFBundleGrokObjcImageInfoFromFile(int fd
, const void *bytes
, CFIndex length
, uint32_t offset
, Boolean swapped
, Boolean sixtyFour
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
1861 uint32_t sectlength
= 0, sectoffset
= 0, localVersion
= 0, localFlags
= 0;
1862 char *buffer
= NULL
;
1864 const char *loc
= NULL
;
1866 Boolean foundit
= false, localHasObjc
= false;
1868 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
1869 buffer
= malloc(IMAGE_INFO_BYTES_TO_READ
);
1870 if (buffer
&& read(fd
, buffer
, IMAGE_INFO_BYTES_TO_READ
) >= IMAGE_INFO_BYTES_TO_READ
) loc
= buffer
;
1871 } else if (bytes
&& length
>= offset
+ IMAGE_INFO_BYTES_TO_READ
) {
1872 loc
= bytes
+ offset
;
1876 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->ncmds
, swapped
);
1877 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->sizeofcmds
, swapped
);
1878 const char *startofcmds
= loc
+ sizeof(struct mach_header_64
);
1879 const char *endofcmds
= startofcmds
+ sizeofcmds
;
1880 struct segment_command_64
*sgp
= (struct segment_command_64
*)startofcmds
;
1881 if (endofcmds
> loc
+ IMAGE_INFO_BYTES_TO_READ
) endofcmds
= loc
+ IMAGE_INFO_BYTES_TO_READ
;
1882 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
1883 if (LC_SEGMENT_64
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
1884 struct section_64
*sp
= (struct section_64
*)((char *)sgp
+ sizeof(struct segment_command_64
));
1885 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
1886 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
1887 if (0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) localHasObjc
= true;
1888 if (0 == strncmp(sp
->sectname
, IMAGE_INFO_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) {
1889 uint64_t sectlength64
= _CFBundleSwapInt64Conditional(sp
->size
, swapped
);
1890 sectlength
= (uint32_t)(sectlength64
& 0xffffffff);
1891 sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
1894 sp
= (struct section_64
*)((char *)sp
+ sizeof(struct section_64
));
1897 sgp
= (struct segment_command_64
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
1900 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->ncmds
, swapped
);
1901 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->sizeofcmds
, swapped
);
1902 const char *startofcmds
= loc
+ sizeof(struct mach_header
);
1903 const char *endofcmds
= startofcmds
+ sizeofcmds
;
1904 struct segment_command
*sgp
= (struct segment_command
*)startofcmds
;
1905 if (endofcmds
> loc
+ IMAGE_INFO_BYTES_TO_READ
) endofcmds
= loc
+ IMAGE_INFO_BYTES_TO_READ
;
1906 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
1907 if (LC_SEGMENT
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
1908 struct section
*sp
= (struct section
*)((char *)sgp
+ sizeof(struct segment_command
));
1909 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
1910 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
1911 if (0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) localHasObjc
= true;
1912 if (0 == strncmp(sp
->sectname
, IMAGE_INFO_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) {
1913 sectlength
= _CFBundleSwapInt32Conditional(sp
->size
, swapped
);
1914 sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
1917 sp
= (struct section
*)((char *)sp
+ sizeof(struct section
));
1920 sgp
= (struct segment_command
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
1923 if (sectlength
>= 8) {
1924 if (fd
>= 0 && lseek(fd
, offset
+ sectoffset
, SEEK_SET
) == (off_t
)(offset
+ sectoffset
) && read(fd
, sectbuffer
, 8) >= 8) {
1925 localVersion
= _CFBundleSwapInt32Conditional(*(uint32_t *)sectbuffer
, swapped
);
1926 localFlags
= _CFBundleSwapInt32Conditional(*(uint32_t *)(sectbuffer
+ 4), swapped
);
1927 } else if (bytes
&& length
>= offset
+ sectoffset
+ 8) {
1928 localVersion
= _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes
+ offset
+ sectoffset
), swapped
);
1929 localFlags
= _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes
+ offset
+ sectoffset
+ 4), swapped
);
1934 if (buffer
) free(buffer
);
1936 if (hasObjc
) *hasObjc
= localHasObjc
;
1937 if (objcVersion
) *objcVersion
= localVersion
;
1938 if (objcFlags
) *objcFlags
= localFlags
;
1941 static UInt32
_CFBundleGrokMachTypeForFatFile(int fd
, const void *bytes
, CFIndex length
, Boolean
*isX11
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
1942 UInt32 machtype
= UNKNOWN_FILETYPE
, magic
, numFatHeaders
= ((struct fat_header
*)bytes
)->nfat_arch
, maxFatHeaders
= (length
- sizeof(struct fat_header
)) / sizeof(struct fat_arch
), i
;
1943 unsigned char buffer
[sizeof(struct mach_header_64
)];
1944 const unsigned char *moreBytes
= NULL
;
1945 const NXArchInfo
*archInfo
= NXGetLocalArchInfo();
1946 struct fat_arch
*fat
= NULL
;
1948 if (isX11
) *isX11
= false;
1949 if (architectures
) *architectures
= NULL
;
1950 if (infodict
) *infodict
= NULL
;
1951 if (hasObjc
) *hasObjc
= false;
1952 if (objcVersion
) *objcVersion
= 0;
1953 if (objcFlags
) *objcFlags
= 0;
1954 if (numFatHeaders
> maxFatHeaders
) numFatHeaders
= maxFatHeaders
;
1955 if (numFatHeaders
> 0) {
1956 fat
= NXFindBestFatArch(archInfo
->cputype
, archInfo
->cpusubtype
, (struct fat_arch
*)(bytes
+ sizeof(struct fat_header
)), numFatHeaders
);
1957 if (!fat
) fat
= (struct fat_arch
*)(bytes
+ sizeof(struct fat_header
));
1958 if (architectures
) {
1959 CFMutableArrayRef mutableArchitectures
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
1960 for (i
= 0; i
< numFatHeaders
; i
++) {
1961 CFNumberRef architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, bytes
+ sizeof(struct fat_header
) + i
* sizeof(struct fat_arch
));
1962 if (CFArrayGetFirstIndexOfValue(mutableArchitectures
, CFRangeMake(0, CFArrayGetCount(mutableArchitectures
)), architecture
) < 0) CFArrayAppendValue(mutableArchitectures
, architecture
);
1963 CFRelease(architecture
);
1965 *architectures
= (CFArrayRef
)mutableArchitectures
;
1969 if (fd
>= 0 && lseek(fd
, fat
->offset
, SEEK_SET
) == (off_t
)fat
->offset
&& read(fd
, buffer
, sizeof(struct mach_header_64
)) >= (int)sizeof(struct mach_header_64
)) {
1971 } else if (bytes
&& (uint32_t)length
>= fat
->offset
+ sizeof(struct mach_header_64
)) {
1972 moreBytes
= bytes
+ fat
->offset
;
1975 magic
= *((UInt32
*)moreBytes
);
1976 if (MH_MAGIC
== magic
) {
1977 machtype
= ((struct mach_header
*)moreBytes
)->filetype
;
1978 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, false, false);
1979 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, false, false);
1980 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, false, false, hasObjc
, objcVersion
, objcFlags
);
1981 } else if (MH_CIGAM
== magic
) {
1982 machtype
= CFSwapInt32(((struct mach_header
*)moreBytes
)->filetype
);
1983 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, true, false);
1984 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, true, false);
1985 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, true, false, hasObjc
, objcVersion
, objcFlags
);
1986 } else if (MH_MAGIC_64
== magic
) {
1987 machtype
= ((struct mach_header_64
*)moreBytes
)->filetype
;
1988 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, false, true);
1989 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, false, true);
1990 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, false, true, hasObjc
, objcVersion
, objcFlags
);
1991 } else if (MH_CIGAM_64
== magic
) {
1992 machtype
= CFSwapInt32(((struct mach_header_64
*)moreBytes
)->filetype
);
1993 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, true, true);
1994 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, true, true);
1995 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, true, true, hasObjc
, objcVersion
, objcFlags
);
2002 static UInt32
_CFBundleGrokMachType(int fd
, const void *bytes
, CFIndex length
, Boolean
*isX11
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2003 unsigned int magic
= *((UInt32
*)bytes
), machtype
= UNKNOWN_FILETYPE
;
2004 CFNumberRef architecture
= NULL
;
2007 if (isX11
) *isX11
= false;
2008 if (architectures
) *architectures
= NULL
;
2009 if (infodict
) *infodict
= NULL
;
2010 if (hasObjc
) *hasObjc
= false;
2011 if (objcVersion
) *objcVersion
= 0;
2012 if (objcFlags
) *objcFlags
= 0;
2013 if (MH_MAGIC
== magic
) {
2014 machtype
= ((struct mach_header
*)bytes
)->filetype
;
2015 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, false, false);
2016 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, bytes
+ 4);
2017 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, false, false);
2018 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, false, false, hasObjc
, objcVersion
, objcFlags
);
2019 } else if (MH_CIGAM
== magic
) {
2020 for (i
= 0; i
< length
; i
+= 4) *(UInt32
*)(bytes
+ i
) = CFSwapInt32(*(UInt32
*)(bytes
+ i
));
2021 machtype
= ((struct mach_header
*)bytes
)->filetype
;
2022 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, true, false);
2023 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, bytes
+ 4);
2024 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, true, false);
2025 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, true, false, hasObjc
, objcVersion
, objcFlags
);
2026 } else if (MH_MAGIC_64
== magic
) {
2027 machtype
= ((struct mach_header_64
*)bytes
)->filetype
;
2028 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, false, true);
2029 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, bytes
+ 4);
2030 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, false, true);
2031 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, false, true, hasObjc
, objcVersion
, objcFlags
);
2032 } else if (MH_CIGAM_64
== magic
) {
2033 for (i
= 0; i
< length
; i
+= 4) *(UInt32
*)(bytes
+ i
) = CFSwapInt32(*(UInt32
*)(bytes
+ i
));
2034 machtype
= ((struct mach_header_64
*)bytes
)->filetype
;
2035 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, true, true);
2036 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, bytes
+ 4);
2037 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, true, true);
2038 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, true, true, hasObjc
, objcVersion
, objcFlags
);
2039 } else if (FAT_MAGIC
== magic
) {
2040 machtype
= _CFBundleGrokMachTypeForFatFile(fd
, bytes
, length
, isX11
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2041 } else if (FAT_CIGAM
== magic
) {
2042 for (i
= 0; i
< length
; i
+= 4) *(UInt32
*)(bytes
+ i
) = CFSwapInt32(*(UInt32
*)(bytes
+ i
));
2043 machtype
= _CFBundleGrokMachTypeForFatFile(fd
, bytes
, length
, isX11
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2044 } else if (PEF_MAGIC
== magic
|| PEF_CIGAM
== magic
) {
2045 machtype
= PEF_FILETYPE
;
2047 if (architectures
&& architecture
) *architectures
= CFArrayCreate(kCFAllocatorSystemDefault
, (const void **)&architecture
, 1, &kCFTypeArrayCallBacks
);
2048 if (architecture
) CFRelease(architecture
);
2052 #endif /* BINARY_SUPPORT_DYLD */
2054 static Boolean
_CFBundleGrokFileTypeForZipMimeType(const unsigned char *bytes
, CFIndex length
, const char **ext
) {
2055 unsigned namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 26))), extralength
= CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 28)));
2056 const unsigned char *data
= bytes
+ 30 + namelength
+ extralength
;
2058 if (bytes
< data
&& data
+ 56 <= bytes
+ length
&& 0 == CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 8))) && (0 == ustrncasecmp(data
, "application/vnd.", 16) || 0 == ustrncasecmp(data
, "application/x-vnd.", 18))) {
2059 data
+= ('.' == *(data
+ 15)) ? 16 : 18;
2060 if (0 == ustrncasecmp(data
, "sun.xml.", 8)) {
2062 if (0 == ustrncasecmp(data
, "calc", 4)) i
= 0;
2063 else if (0 == ustrncasecmp(data
, "draw", 4)) i
= 1;
2064 else if (0 == ustrncasecmp(data
, "writer.global", 13)) i
= 2;
2065 else if (0 == ustrncasecmp(data
, "impress", 7)) i
= 3;
2066 else if (0 == ustrncasecmp(data
, "math", 4)) i
= 4;
2067 else if (0 == ustrncasecmp(data
, "writer", 6)) i
= 5;
2068 if (i
>= 0 && ext
) *ext
= __CFBundleOOExtensionsArray
+ i
* EXTENSION_LENGTH
;
2069 } else if (0 == ustrncasecmp(data
, "oasis.opendocument.", 19)) {
2071 if (0 == ustrncasecmp(data
, "chart", 5)) i
= 0;
2072 else if (0 == ustrncasecmp(data
, "formula", 7)) i
= 1;
2073 else if (0 == ustrncasecmp(data
, "graphics", 8)) i
= 2;
2074 else if (0 == ustrncasecmp(data
, "text-web", 8)) i
= 3;
2075 else if (0 == ustrncasecmp(data
, "image", 5)) i
= 4;
2076 else if (0 == ustrncasecmp(data
, "text-master", 11)) i
= 5;
2077 else if (0 == ustrncasecmp(data
, "presentation", 12)) i
= 6;
2078 else if (0 == ustrncasecmp(data
, "spreadsheet", 11)) i
= 7;
2079 else if (0 == ustrncasecmp(data
, "text", 4)) i
= 8;
2080 if (i
>= 0 && ext
) *ext
= __CFBundleODExtensionsArray
+ i
* EXTENSION_LENGTH
;
2082 } else if (bytes
< data
&& data
+ 41 <= bytes
+ length
&& 8 == CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 8))) && 0x4b2c28c8 == CFSwapInt32HostToBig(*((UInt32
*)data
)) && 0xc94c4e2c == CFSwapInt32HostToBig(*((UInt32
*)(data
+ 4)))) {
2083 // AbiWord compressed mimetype odt
2084 if (ext
) *ext
= "odt";
2089 static const char *_CFBundleGrokFileTypeForZipFile(int fd
, const unsigned char *bytes
, CFIndex length
, off_t fileLength
) {
2090 const char *ext
= "zip";
2091 const unsigned char *moreBytes
= NULL
;
2092 unsigned char *buffer
= NULL
;
2094 Boolean foundMimetype
= false, hasMetaInf
= false, hasContentXML
= false, hasManifestMF
= false, hasManifestXML
= false, hasRels
= false, hasContentTypes
= false, hasWordDocument
= false, hasExcelDocument
= false, hasPowerPointDocument
= false, hasOPF
= false, hasSMIL
= false;
2097 for (i
= 0; !foundMimetype
&& i
+ 30 < length
; i
++) {
2098 if (0x50 == bytes
[i
] && 0x4b == bytes
[i
+ 1]) {
2099 unsigned namelength
= 0, offset
= 0;
2100 if (0x01 == bytes
[i
+ 2] && 0x02 == bytes
[i
+ 3]) {
2101 namelength
= (unsigned)CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ i
+ 28)));
2103 } else if (0x03 == bytes
[i
+ 2] && 0x04 == bytes
[i
+ 3]) {
2104 namelength
= (unsigned)CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ i
+ 26)));
2107 if (offset
> 0 && (CFIndex
)(i
+ offset
+ namelength
) <= length
) {
2108 //printf("%.*s\n", namelength, bytes + i + offset);
2109 if (8 == namelength
&& 30 == offset
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "mimetype", 8)) foundMimetype
= _CFBundleGrokFileTypeForZipMimeType(bytes
+ i
, length
- i
, &ext
);
2110 else if (9 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/", 9)) hasMetaInf
= true;
2111 else if (11 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "content.xml", 11)) hasContentXML
= true;
2112 else if (11 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "_rels/.rels", 11)) hasRels
= true;
2113 else if (19 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "[Content_Types].xml", 19)) hasContentTypes
= true;
2114 else if (20 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/MANIFEST.MF", 20)) hasManifestMF
= true;
2115 else if (21 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/manifest.xml", 21)) hasManifestXML
= true;
2116 else if (4 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".opf", 4)) hasOPF
= true;
2117 else if (4 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".sml", 4)) hasSMIL
= true;
2118 else if (5 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 5, ".smil", 5)) hasSMIL
= true;
2119 else if (9 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "word/", 5) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasWordDocument
= true;
2120 else if (10 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "excel/", 6) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2121 else if (15 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "powerpoint/", 11) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2122 i
+= offset
+ namelength
- 1;
2127 if (!foundMimetype
) {
2128 if (fileLength
>= ZIP_BYTES_TO_READ
) {
2129 if (fd
>= 0 && lseek(fd
, fileLength
- ZIP_BYTES_TO_READ
, SEEK_SET
) == fileLength
- ZIP_BYTES_TO_READ
) {
2130 buffer
= (unsigned char *)malloc(ZIP_BYTES_TO_READ
);
2131 if (buffer
&& read(fd
, buffer
, ZIP_BYTES_TO_READ
) >= ZIP_BYTES_TO_READ
) moreBytes
= buffer
;
2132 } else if (bytes
&& length
>= ZIP_BYTES_TO_READ
) {
2133 moreBytes
= bytes
+ length
- ZIP_BYTES_TO_READ
;
2137 for (i
= 0; i
+ 30 < ZIP_BYTES_TO_READ
; i
++) {
2138 if (0x50 == moreBytes
[i
] && 0x4b == moreBytes
[i
+ 1]) {
2139 unsigned namelength
= 0, offset
= 0;
2140 if (0x01 == moreBytes
[i
+ 2] && 0x02 == moreBytes
[i
+ 3]) {
2141 namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(moreBytes
+ i
+ 28)));
2143 } else if (0x03 == moreBytes
[i
+ 2] && 0x04 == moreBytes
[i
+ 3]) {
2144 namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(moreBytes
+ i
+ 26)));
2147 if (offset
> 0 && i
+ offset
+ namelength
<= ZIP_BYTES_TO_READ
) {
2148 //printf("%.*s\n", namelength, moreBytes + i + offset);
2149 if (9 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/", 9)) hasMetaInf
= true;
2150 else if (11 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "content.xml", 11)) hasContentXML
= true;
2151 else if (11 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "_rels/.rels", 11)) hasRels
= true;
2152 else if (19 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "[Content_Types].xml", 19)) hasContentTypes
= true;
2153 else if (20 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/MANIFEST.MF", 20)) hasManifestMF
= true;
2154 else if (21 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/manifest.xml", 21)) hasManifestXML
= true;
2155 else if (4 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".opf", 4)) hasOPF
= true;
2156 else if (4 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".sml", 4)) hasSMIL
= true;
2157 else if (5 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 5, ".smil", 5)) hasSMIL
= true;
2158 else if (9 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "word/", 5) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasWordDocument
= true;
2159 else if (10 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "excel/", 6) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2160 else if (15 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "powerpoint/", 11) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2161 i
+= offset
+ namelength
- 1;
2166 //printf("hasManifestMF %d hasManifestXML %d hasContentXML %d hasRels %d hasContentTypes %d hasWordDocument %d hasExcelDocument %d hasPowerPointDocument %d hasMetaInf %d hasOPF %d hasSMIL %d\n", hasManifestMF, hasManifestXML, hasContentXML, hasRels, hasContentTypes, hasWordDocument, hasExcelDocument, hasPowerPointDocument, hasMetaInf, hasOPF, hasSMIL);
2167 if (hasManifestMF
) ext
= "jar";
2168 else if ((hasRels
|| hasContentTypes
) && hasWordDocument
) ext
= "docx";
2169 else if ((hasRels
|| hasContentTypes
) && hasExcelDocument
) ext
= "xlsx";
2170 else if ((hasRels
|| hasContentTypes
) && hasPowerPointDocument
) ext
= "pptx";
2171 else if (hasManifestXML
|| hasContentXML
) ext
= "odt";
2172 else if (hasMetaInf
) ext
= "jar";
2173 else if (hasOPF
&& hasSMIL
) ext
= "dtb";
2174 else if (hasOPF
) ext
= "oeb";
2176 if (buffer
) free(buffer
);
2181 static Boolean
_CFBundleCheckOLEName(const char *name
, const char *bytes
, unsigned length
) {
2182 Boolean retval
= true;
2184 for (j
= 0; retval
&& j
< length
; j
++) if (bytes
[2 * j
] != name
[j
]) retval
= false;
2188 static const char *_CFBundleGrokFileTypeForOLEFile(int fd
, const void *bytes
, CFIndex length
, off_t offset
) {
2189 const char *ext
= "ole", *moreBytes
= NULL
;
2190 char *buffer
= NULL
;
2192 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
2193 buffer
= (char *)malloc(OLE_BYTES_TO_READ
);
2194 if (buffer
&& read(fd
, buffer
, OLE_BYTES_TO_READ
) >= OLE_BYTES_TO_READ
) moreBytes
= buffer
;
2195 } else if (bytes
&& length
>= offset
+ OLE_BYTES_TO_READ
) {
2196 moreBytes
= (char *)bytes
+ offset
;
2199 Boolean foundit
= false;
2201 for (i
= 0; !foundit
&& i
< 4; i
++) {
2202 char namelength
= moreBytes
[128 * i
+ 64] / 2;
2204 if (sizeof(XLS_NAME
) == namelength
&& _CFBundleCheckOLEName(XLS_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "xls";
2205 else if (sizeof(XLS_NAME2
) == namelength
&& _CFBundleCheckOLEName(XLS_NAME2
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "xls";
2206 else if (sizeof(DOC_NAME
) == namelength
&& _CFBundleCheckOLEName(DOC_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "doc";
2207 else if (sizeof(PPT_NAME
) == namelength
&& _CFBundleCheckOLEName(PPT_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "ppt";
2208 else foundit
= false;
2212 if (buffer
) free(buffer
);
2217 static Boolean
_CFBundleGrokFileType(CFURLRef url
, CFDataRef data
, CFStringRef
*extension
, UInt32
*machtype
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2218 struct stat statBuf
;
2220 char path
[CFMaxPathSize
];
2221 const unsigned char *bytes
= NULL
;
2222 unsigned char buffer
[MAGIC_BYTES_TO_READ
];
2223 CFIndex i
, length
= 0;
2224 off_t fileLength
= 0;
2225 const char *ext
= NULL
;
2226 UInt32 mt
= UNKNOWN_FILETYPE
;
2227 #if defined(BINARY_SUPPORT_DYLD)
2228 Boolean isX11
= false;
2229 #endif /* BINARY_SUPPORT_DYLD */
2230 Boolean isFile
= false, isPlain
= true, isZero
= true, isHTML
= false;
2231 // extensions returned: o, tool, x11app, pef, core, dylib, bundle, elf, jpeg, jp2, tiff, gif, png, pict, icns, ico, rtf, rtfd, pdf, ra, rm, au, aiff, aifc, wav, avi, wmv, ogg, flac, psd, mpeg, mid, zip, jar, sit, cpio, html, ps, mov, qtif, ttf, otf, sfont, bmp, hqx, bin, class, tar, txt, gz, Z, uu, ync, bz, bz2, sh, pl, py, rb, dvi, sgi, tga, mp3, xml, plist, xls, doc, ppt, mp4, m4a, m4b, m4p, dmg, cwk, webarchive, dwg, dgn, pfa, pfb, afm, tfm, xcf, cpx, dwf, swf, swc, abw, bom, lit, svg, rdf, x3d, oeb, dtb, docx, xlsx, pptx, sxc, sxd, sxg, sxi, sxm, sxw, odc, odf, odg, oth, odi, odm, odp, ods
2232 // ??? we do not distinguish between different wm types, returning wmv for any of wmv, wma, or asf
2233 // ??? we do not distinguish between ordinary documents and template versions (often there is no difference in file contents)
2234 // ??? the distinctions between docx, xlsx, and pptx may not be entirely reliable
2235 if (architectures
) *architectures
= NULL
;
2236 if (infodict
) *infodict
= NULL
;
2237 if (hasObjc
) *hasObjc
= false;
2238 if (objcVersion
) *objcVersion
= 0;
2239 if (objcFlags
) *objcFlags
= 0;
2240 if (url
&& CFURLGetFileSystemRepresentation(url
, true, (uint8_t *)path
, CFMaxPathSize
) && stat(path
, &statBuf
) == 0 && (statBuf
.st_mode
& S_IFMT
) == S_IFREG
&& (fd
= open(path
, O_RDONLY
, 0777)) >= 0) {
2241 length
= read(fd
, buffer
, MAGIC_BYTES_TO_READ
);
2242 fileLength
= statBuf
.st_size
;
2246 length
= CFDataGetLength(data
);
2247 fileLength
= (off_t
)length
;
2248 bytes
= CFDataGetBytePtr(data
);
2249 if (length
== 0) ext
= "txt";
2253 UInt32 magic
= CFSwapInt32HostToBig(*((UInt32
*)bytes
));
2254 for (i
= 0; !ext
&& i
< NUM_EXTENSIONS
; i
++) {
2255 if (__CFBundleMagicNumbersArray
[i
] == magic
) ext
= __CFBundleExtensionsArray
+ i
* EXTENSION_LENGTH
;
2258 if (0xcafebabe == magic
&& 8 <= length
&& 0 != *((UInt16
*)(bytes
+ 4))) ext
= "class";
2259 #if defined(BINARY_SUPPORT_DYLD)
2260 else if ((int)sizeof(struct mach_header_64
) <= length
) mt
= _CFBundleGrokMachType(fd
, bytes
, length
, extension
? &isX11
: NULL
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2262 if (MH_OBJECT
== mt
) ext
= "o";
2263 else if (MH_EXECUTE
== mt
) ext
= isX11
? "x11app" : "tool";
2264 else if (PEF_FILETYPE
== mt
) ext
= "pef";
2265 else if (MH_CORE
== mt
) ext
= "core";
2266 else if (MH_DYLIB
== mt
) ext
= "dylib";
2267 else if (MH_BUNDLE
== mt
) ext
= "bundle";
2268 #endif /* BINARY_SUPPORT_DYLD */
2269 else if (0x7b5c7274 == magic
&& (6 > length
|| 'f' != bytes
[4])) ext
= NULL
;
2270 else if (0x00010000 == magic
&& (6 > length
|| 0 != bytes
[4])) ext
= NULL
;
2271 else if (0x47494638 == magic
&& (6 > length
|| (0x3761 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))) && 0x3961 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4)))))) ext
= NULL
;
2272 else if (0x0000000c == magic
&& (6 > length
|| 0x6a50 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2273 else if (0x2356524d == magic
&& (6 > length
|| 0x4c20 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2274 else if (0x28445746 == magic
&& (6 > length
|| 0x2056 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2275 else if (0x30373037 == magic
&& (6 > length
|| 0x30 != bytes
[4] || !isdigit(bytes
[5]))) ext
= NULL
;
2276 else if (0x41433130 == magic
&& (6 > length
|| 0x31 != bytes
[4] || !isdigit(bytes
[5]))) ext
= NULL
;
2277 else if (0x89504e47 == magic
&& (8 > length
|| 0x0d0a1a0a != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2278 else if (0x53747566 == magic
&& (8 > length
|| 0x66497420 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2279 else if (0x3026b275 == magic
&& (8 > length
|| 0x8e66cf11 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2280 else if (0x67696d70 == magic
&& (8 > length
|| 0x20786366 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2281 else if (0x424f4d53 == magic
&& (8 > length
|| 0x746f7265 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2282 else if (0x49544f4c == magic
&& (8 > length
|| 0x49544c53 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2283 else if (0x72746664 == magic
&& (8 > length
|| 0x00000000 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2284 else if (0x3d796265 == magic
&& (12 > length
|| 0x67696e20 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || (0x6c696e65 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8))) && 0x70617274 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)))))) ext
= NULL
;
2285 else if (0x25215053 == magic
&& 14 <= length
&& 0 == ustrncmp(bytes
+ 4, "-AdobeFont", 10)) ext
= "pfa";
2286 else if (0x504b0304 == magic
) ext
= _CFBundleGrokFileTypeForZipFile(fd
, bytes
, length
, fileLength
);
2287 else if (0x464f524d == magic
) {
2291 UInt32 iffMagic
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2292 if (0x41494646 == iffMagic
) ext
= "aiff";
2293 else if (0x414946 == iffMagic
) ext
= "aifc";
2295 } else if (0x52494646 == magic
) {
2299 UInt32 riffMagic
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2300 if (0x57415645 == riffMagic
) ext
= "wav";
2301 else if (0x41564920 == riffMagic
) ext
= "avi";
2303 } else if (0xd0cf11e0 == magic
) {
2305 if (52 <= length
) ext
= _CFBundleGrokFileTypeForOLEFile(fd
, bytes
, length
, 512 * (1 + CFSwapInt32HostToLittle(*((UInt32
*)(bytes
+ 48)))));
2306 } else if (0x62656769 == magic
) {
2309 if (76 <= length
&& 'n' == bytes
[4] && ' ' == bytes
[5] && isdigit(bytes
[6]) && isdigit(bytes
[7]) && isdigit(bytes
[8]) && ' ' == bytes
[9]) {
2310 CFIndex endOfLine
= 0;
2311 for (i
= 10; 0 == endOfLine
&& i
< length
; i
++) if ('\n' == bytes
[i
]) endOfLine
= i
;
2312 if (10 <= endOfLine
&& endOfLine
+ 62 < length
&& 'M' == bytes
[endOfLine
+ 1] && '\n' == bytes
[endOfLine
+ 62]) {
2314 for (i
= endOfLine
+ 1; ext
&& i
< endOfLine
+ 62; i
++) if (!isprint(bytes
[i
])) ext
= NULL
;
2319 if (extension
&& !ext
) {
2320 UInt16 shortMagic
= CFSwapInt16HostToBig(*((UInt16
*)bytes
));
2321 if (5 <= length
&& 0 == bytes
[3] && 0 == bytes
[4] && ((1 == bytes
[1] && 1 == (0xf7 & bytes
[2])) || (0 == bytes
[1] && (2 == (0xf7 & bytes
[2]) || (3 == (0xf7 & bytes
[2])))))) ext
= "tga";
2322 else if (8 <= length
&& (0x6d6f6f76 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x6d646174 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x77696465 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "mov";
2323 else if (8 <= length
&& (0x69647363 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x69646174 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "qtif";
2324 else if (8 <= length
&& 0x424f424f == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4)))) ext
= "cwk";
2325 else if (8 <= length
&& 0x62706c69 == magic
&& 0x7374 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))) && isdigit(bytes
[6]) && isdigit(bytes
[7])) {
2326 for (i
= 8; !ext
&& i
< 128 && i
+ 16 <= length
; i
++) {
2327 if (0 == ustrncmp(bytes
+ i
, "WebMainResource", 15)) ext
= "webarchive";
2329 if (!ext
) ext
= "plist";
2330 } else if (12 <= length
&& 0x66747970 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4)))) {
2331 // ??? list of ftyp values needs to be checked
2332 if (0x6d703432 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)))) ext
= "mp4";
2333 else if (0x4d344120 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)))) ext
= "m4a";
2334 else if (0x4d344220 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)))) ext
= "m4b";
2335 else if (0x4d345020 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)))) ext
= "m4p";
2336 } else if (0x424d == shortMagic
&& 18 <= length
&& 40 == CFSwapInt32HostToLittle(*((UInt32
*)(bytes
+ 14)))) ext
= "bmp";
2337 else if (20 <= length
&& 0 == ustrncmp(bytes
+ 6, "%!PS-AdobeFont", 14)) ext
= "pfb";
2338 else if (40 <= length
&& 0x42696e48 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 34))) && 0x6578 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 38)))) ext
= "hqx";
2339 else if (128 <= length
&& 0x6d42494e == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 102)))) ext
= "bin";
2340 else if (128 <= length
&& 0 == bytes
[0] && 0 < bytes
[1] && bytes
[1] < 64 && 0 == bytes
[74] && 0 == bytes
[82] && 0 == (fileLength
% 128)) {
2341 unsigned df
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 83))), rf
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 87))), blocks
= 1 + (df
+ 127) / 128 + (rf
+ 127) / 128;
2342 if (df
< 0x00800000 && rf
< 0x00800000 && 1 < blocks
&& (off_t
)(128 * blocks
) == fileLength
) ext
= "bin";
2343 } else if (265 <= length
&& 0x75737461 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 257))) && (0x72202000 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 261))) || 0x7200 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 261))))) ext
= "tar";
2344 else if (0xfeff == shortMagic
|| 0xfffe == shortMagic
) ext
= "txt";
2345 else if (0x1f9d == shortMagic
) ext
= "Z";
2346 else if (0x1f8b == shortMagic
) ext
= "gz";
2347 else if (0x71c7 == shortMagic
|| 0xc771 == shortMagic
) ext
= "cpio";
2348 else if (0xf702 == shortMagic
) ext
= "dvi";
2349 else if (0x01da == shortMagic
&& (0 == bytes
[2] || 1 == bytes
[2]) && (0 < bytes
[3] && 16 > bytes
[3])) ext
= "sgi";
2350 else if (0x2321 == shortMagic
) {
2351 CFIndex endOfLine
= 0, lastSlash
= 0;
2352 for (i
= 2; 0 == endOfLine
&& i
< length
; i
++) if ('\n' == bytes
[i
]) endOfLine
= i
;
2353 if (endOfLine
> 3) {
2354 for (i
= endOfLine
- 1; 0 == lastSlash
&& i
> 1; i
--) if ('/' == bytes
[i
]) lastSlash
= i
;
2355 if (lastSlash
> 0) {
2356 if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "perl", 4)) ext
= "pl";
2357 else if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "python", 6)) ext
= "py";
2358 else if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "ruby", 4)) ext
= "rb";
2362 } else if (0xffd8 == shortMagic
&& 0xff == bytes
[2]) ext
= "jpeg";
2363 else if (0x4657 == shortMagic
&& 0x53 == bytes
[2]) ext
= "swf";
2364 else if (0x4357 == shortMagic
&& 0x53 == bytes
[2]) ext
= "swc";
2365 else if (0x4944 == shortMagic
&& '3' == bytes
[2] && 0x20 > bytes
[3]) ext
= "mp3";
2366 else if (0x425a == shortMagic
&& isdigit(bytes
[2]) && isdigit(bytes
[3])) ext
= "bz";
2367 else if (0x425a == shortMagic
&& 'h' == bytes
[2] && isdigit(bytes
[3]) && 8 <= length
&& (0x31415926 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x17724538 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "bz2";
2368 else if (0x0011 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 2))) || 0x0012 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 2)))) ext
= "tfm";
2369 else if ('<' == bytes
[0] && 14 <= length
) {
2370 if (0 == ustrncasecmp(bytes
+ 1, "!doctype html", 13) || 0 == ustrncasecmp(bytes
+ 1, "head", 4) || 0 == ustrncasecmp(bytes
+ 1, "title", 5) || 0 == ustrncasecmp(bytes
+ 1, "html", 4)) {
2372 } else if (0 == ustrncasecmp(bytes
+ 1, "?xml", 4)) {
2373 for (i
= 4; !ext
&& i
< 128 && i
+ 20 <= length
; i
++) {
2374 if ('<' == bytes
[i
]) {
2375 if (0 == ustrncasecmp(bytes
+ i
+ 1, "abiword", 7)) ext
= "abw";
2376 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype svg", 12)) ext
= "svg";
2377 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype rdf", 12)) ext
= "rdf";
2378 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype x3d", 12)) ext
= "x3d";
2379 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype html", 13)) ext
= "html";
2380 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype plist", 14)) ext
= "plist";
2381 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype posingfont", 19)) ext
= "sfont";
2384 if (!ext
) ext
= "xml";
2389 if (extension
&& !ext
) {
2390 //??? what about MacOSRoman?
2391 for (i
= 0; (isPlain
|| isZero
) && !isHTML
&& i
< length
&& i
< 512; i
++) {
2393 if (0x7f <= c
|| (0x20 > c
&& !isspace(c
))) isPlain
= false;
2394 if (0 != c
) isZero
= false;
2395 if (isPlain
&& '<' == c
&& i
+ 14 <= length
&& 0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype html", 13)) isHTML
= true;
2399 } else if (isPlain
) {
2400 if (16 <= length
&& 0 == ustrncmp(bytes
, "StartFontMetrics", 16)) ext
= "afm";
2402 } else if (isZero
&& length
>= MAGIC_BYTES_TO_READ
&& fileLength
>= 526) {
2404 if (lseek(fd
, 512, SEEK_SET
) == 512 && read(fd
, buffer
, MAGIC_BYTES_TO_READ
) >= 14) {
2405 if (0x001102ff == CFSwapInt32HostToBig(*((UInt32
*)(buffer
+ 10)))) ext
= "pict";
2408 if (526 <= length
&& 0x001102ff == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 522)))) ext
= "pict";
2412 if (extension
&& (!ext
|| 0 == strcmp(ext
, "bz2")) && length
>= MAGIC_BYTES_TO_READ
&& fileLength
>= DMG_BYTES_TO_READ
) {
2414 if (lseek(fd
, fileLength
- DMG_BYTES_TO_READ
, SEEK_SET
) == fileLength
- DMG_BYTES_TO_READ
&& read(fd
, buffer
, DMG_BYTES_TO_READ
) >= DMG_BYTES_TO_READ
) {
2415 if (0x6b6f6c79 == CFSwapInt32HostToBig(*((UInt32
*)buffer
)) || (0x63647361 == CFSwapInt32HostToBig(*((UInt32
*)(buffer
+ DMG_BYTES_TO_READ
- 8))) && 0x656e6372 == CFSwapInt32HostToBig(*((UInt32
*)(buffer
+ DMG_BYTES_TO_READ
- 4))))) ext
= "dmg";
2418 if (DMG_BYTES_TO_READ
<= length
&& (0x6b6f6c79 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ length
- DMG_BYTES_TO_READ
))) || (0x63647361 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ length
- 8))) && 0x656e6372 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ length
- 4)))))) ext
= "dmg";
2422 if (extension
) *extension
= ext
? CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault
, ext
, kCFStringEncodingUTF8
, kCFAllocatorNull
) : NULL
;
2423 if (machtype
) *machtype
= mt
;
2424 if (fd
>= 0) close(fd
);
2425 return (ext
? true : false);
2428 CFStringRef
_CFBundleCopyFileTypeForFileURL(CFURLRef url
) {
2429 CFStringRef extension
= NULL
;
2430 (void)_CFBundleGrokFileType(url
, NULL
, &extension
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2434 CFStringRef
_CFBundleCopyFileTypeForFileData(CFDataRef data
) {
2435 CFStringRef extension
= NULL
;
2436 (void)_CFBundleGrokFileType(NULL
, data
, &extension
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2440 __private_extern__ CFDictionaryRef
_CFBundleCopyInfoDictionaryInExecutable(CFURLRef url
) {
2441 CFDictionaryRef result
= NULL
;
2442 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, NULL
, &result
, NULL
, NULL
, NULL
);
2446 __private_extern__ CFArrayRef
_CFBundleCopyArchitecturesForExecutable(CFURLRef url
) {
2447 CFArrayRef result
= NULL
;
2448 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, &result
, NULL
, NULL
, NULL
, NULL
);
2452 static Boolean
_CFBundleGetObjCImageInfoForExecutable(CFURLRef url
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2453 Boolean retval
= false;
2454 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, NULL
, NULL
, &retval
, objcVersion
, objcFlags
);
2458 #if defined(BINARY_SUPPORT_DYLD)
2460 __private_extern__ __CFPBinaryType
_CFBundleGrokBinaryType(CFURLRef executableURL
) {
2461 // Attempt to grok the type of the binary by looking for DYLD magic numbers. If one of the DYLD magic numbers is found, find out what type of Mach-o file it is. Otherwise, look for the PEF magic numbers to see if it is CFM (if we understand CFM).
2462 __CFPBinaryType result
= executableURL
? __CFBundleUnreadableBinary
: __CFBundleNoBinary
;
2463 UInt32 machtype
= UNKNOWN_FILETYPE
;
2464 if (_CFBundleGrokFileType(executableURL
, NULL
, NULL
, &machtype
, NULL
, NULL
, NULL
, NULL
, NULL
)) {
2467 result
= __CFBundleDYLDExecutableBinary
;
2470 result
= __CFBundleDYLDBundleBinary
;
2473 result
= __CFBundleDYLDFrameworkBinary
;
2475 #if defined(BINARY_SUPPORT_CFM)
2477 result
= __CFBundleCFMBinary
;
2479 #endif /* BINARY_SUPPORT_CFM */
2485 #endif /* BINARY_SUPPORT_DYLD */
2487 void _CFBundleSetCFMConnectionID(CFBundleRef bundle
, void *connectionID
) {
2488 #if defined(BINARY_SUPPORT_CFM)
2489 if (bundle
->_binaryType
== __CFBundleUnknownBinary
|| bundle
->_binaryType
== __CFBundleUnreadableBinary
) {
2490 bundle
->_binaryType
= __CFBundleCFMBinary
;
2492 #endif /* BINARY_SUPPORT_CFM */
2493 bundle
->_connectionCookie
= connectionID
;
2494 bundle
->_isLoaded
= true;
2497 static CFStringRef
_CFBundleCopyLastPathComponent(CFBundleRef bundle
) {
2498 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
);
2499 CFStringRef str
= CFURLCopyFileSystemPath(bundleURL
, kCFURLPOSIXPathStyle
);
2500 UniChar buff
[CFMaxPathSize
];
2501 CFIndex buffLen
= CFStringGetLength(str
), startOfLastDir
= 0;
2503 CFRelease(bundleURL
);
2504 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
2505 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
2507 if (buffLen
> 0) startOfLastDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
2508 return CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfLastDir
]), buffLen
- startOfLastDir
);
2511 static CFErrorRef
_CFBundleCreateErrorDebug(CFAllocatorRef allocator
, CFBundleRef bundle
, CFIndex code
, CFStringRef debugString
) {
2512 const void *userInfoKeys
[6], *userInfoValues
[6];
2513 CFIndex numKeys
= 0;
2514 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
), absoluteURL
= CFURLCopyAbsoluteURL(bundleURL
), executableURL
= CFBundleCopyExecutableURL(bundle
);
2515 CFBundleRef bdl
= CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreFoundation"));
2516 CFStringRef bundlePath
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
), executablePath
= executableURL
? CFURLCopyFileSystemPath(executableURL
, PLATFORM_PATH_STYLE
) : NULL
, descFormat
= NULL
, desc
= NULL
, reason
= NULL
, suggestion
= NULL
;
2519 CFStringRef name
= (CFStringRef
)CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleNameKey
);
2520 name
= name
? (CFStringRef
)CFRetain(name
) : _CFBundleCopyLastPathComponent(bundle
);
2521 if (CFBundleExecutableNotFoundError
== code
) {
2522 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because its executable could not be located."), "NSFileNoSuchFileError");
2523 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl
, CFSTR("The bundle\\U2019s executable could not be located."), "NSFileNoSuchFileError");
2524 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSFileNoSuchFileError");
2525 } else if (CFBundleExecutableNotLoadableError
== code
) {
2526 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because its executable is not loadable."), "NSExecutableNotLoadableError");
2527 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl
, CFSTR("The bundle\\U2019s executable is not loadable."), "NSExecutableNotLoadableError");
2528 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableNotLoadableError");
2529 } else if (CFBundleExecutableArchitectureMismatchError
== code
) {
2530 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because it does not contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
2531 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl
, CFSTR("The bundle does not contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
2532 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-R"), CFSTR("Error"), bdl
, CFSTR("Try installing a universal version of the bundle."), "NSExecutableArchitectureMismatchError");
2533 } else if (CFBundleExecutableRuntimeMismatchError
== code
) {
2534 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because it is not compatible with the current application."), "NSExecutableRuntimeMismatchError");
2535 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl
, CFSTR("The bundle is not compatible with this application."), "NSExecutableRuntimeMismatchError");
2536 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-R"), CFSTR("Error"), bdl
, CFSTR("Try installing a newer version of the bundle."), "NSExecutableRuntimeMismatchError");
2537 } else if (CFBundleExecutableLoadError
== code
) {
2538 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d could not be loaded because it is damaged or missing necessary resources."), "NSExecutableLoadError");
2539 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-C"), CFSTR("Error"), bdl
, CFSTR("The bundle is damaged or missing necessary resources."), "NSExecutableLoadError");
2540 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableLoadError");
2541 } else if (CFBundleExecutableLinkError
== code
) {
2542 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d could not be loaded."), "NSExecutableLinkError");
2543 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl
, CFSTR("The bundle could not be loaded."), "NSExecutableLinkError");
2544 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableLinkError");
2547 desc
= CFStringCreateWithFormat(allocator
, NULL
, descFormat
, name
);
2548 CFRelease(descFormat
);
2553 userInfoKeys
[numKeys
] = CFSTR("NSBundlePath");
2554 userInfoValues
[numKeys
] = bundlePath
;
2557 if (executablePath
) {
2558 userInfoKeys
[numKeys
] = CFSTR("NSFilePath");
2559 userInfoValues
[numKeys
] = executablePath
;
2563 userInfoKeys
[numKeys
] = kCFErrorLocalizedDescriptionKey
;
2564 userInfoValues
[numKeys
] = desc
;
2568 userInfoKeys
[numKeys
] = kCFErrorLocalizedFailureReasonKey
;
2569 userInfoValues
[numKeys
] = reason
;
2573 userInfoKeys
[numKeys
] = kCFErrorLocalizedRecoverySuggestionKey
;
2574 userInfoValues
[numKeys
] = suggestion
;
2578 userInfoKeys
[numKeys
] = CFSTR("NSDebugDescription");
2579 userInfoValues
[numKeys
] = debugString
;
2582 error
= CFErrorCreateWithUserInfoKeysAndValues(allocator
, kCFErrorDomainCocoa
, code
, userInfoKeys
, userInfoValues
, numKeys
);
2583 if (bundleURL
) CFRelease(bundleURL
);
2584 if (absoluteURL
) CFRelease(absoluteURL
);
2585 if (executableURL
) CFRelease(executableURL
);
2586 if (bundlePath
) CFRelease(bundlePath
);
2587 if (executablePath
) CFRelease(executablePath
);
2588 if (desc
) CFRelease(desc
);
2589 if (reason
) CFRelease(reason
);
2590 if (suggestion
) CFRelease(suggestion
);
2594 CFErrorRef
_CFBundleCreateError(CFAllocatorRef allocator
, CFBundleRef bundle
, CFIndex code
) {
2595 return _CFBundleCreateErrorDebug(allocator
, bundle
, code
, NULL
);
2598 Boolean
_CFBundleLoadExecutableAndReturnError(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
2599 Boolean result
= false;
2600 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
2601 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
2603 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
2604 // make sure we know whether bundle is already loaded or not
2605 #if defined(BINARY_SUPPORT_DLFCN)
2606 if (!bundle
->_isLoaded
&& _useDlfcn
) _CFBundleDlfcnCheckLoaded(bundle
);
2607 #endif /* BINARY_SUPPORT_DLFCN */
2608 #if defined(BINARY_SUPPORT_DYLD)
2609 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
2610 // We might need to figure out what it is
2611 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
2612 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
2613 #if defined(BINARY_SUPPORT_CFM)
2614 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
2615 #endif /* BINARY_SUPPORT_CFM */
2617 #endif /* BINARY_SUPPORT_DYLD */
2618 if (executableURL
) CFRelease(executableURL
);
2620 if (bundle
->_isLoaded
) {
2621 // Remove from the scheduled unload set if we are there.
2622 __CFSpinLock(&CFBundleGlobalDataLock
);
2623 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
2624 __CFSpinUnlock(&CFBundleGlobalDataLock
);
2628 // Unload bundles scheduled for unloading
2629 if (!_scheduledBundlesAreUnloading
) _CFBundleUnloadScheduledBundles();
2631 switch (bundle
->_binaryType
) {
2632 #if defined(BINARY_SUPPORT_CFM)
2633 case __CFBundleCFMBinary
:
2634 case __CFBundleUnreadableBinary
:
2635 result
= _CFBundleCFMLoad(bundle
, subError
);
2637 #elif defined(BINARY_SUPPORT_DLFCN)
2638 case __CFBundleUnreadableBinary
:
2639 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
2641 #endif /* BINARY_SUPPORT_CFM */
2642 #if defined(BINARY_SUPPORT_DYLD)
2643 case __CFBundleDYLDBundleBinary
:
2644 #if defined(BINARY_SUPPORT_DLFCN)
2645 if (_useDlfcn
) result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
); else
2646 #endif /* BINARY_SUPPORT_DLFCN */
2647 result
= _CFBundleDYLDLoadBundle(bundle
, forceGlobal
, subError
);
2649 case __CFBundleDYLDFrameworkBinary
:
2650 #if defined(BINARY_SUPPORT_DLFCN)
2651 if (_useDlfcn
) result
= _CFBundleDlfcnLoadFramework(bundle
, subError
); else
2652 #endif /* BINARY_SUPPORT_DLFCN */
2653 result
= _CFBundleDYLDLoadFramework(bundle
, subError
);
2655 case __CFBundleDYLDExecutableBinary
:
2656 CFLog(__kCFLogBundle
, CFSTR("Attempt to load executable of a type that cannot be dynamically loaded for %@"), bundle
);
2657 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
2659 #endif /* BINARY_SUPPORT_DYLD */
2660 #if defined(BINARY_SUPPORT_DLFCN)
2661 case __CFBundleUnknownBinary
:
2662 case __CFBundleELFBinary
:
2663 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
2665 #endif /* BINARY_SUPPORT_DLFCN */
2666 #if defined(BINARY_SUPPORT_DLL)
2667 case __CFBundleDLLBinary
:
2668 result
= _CFBundleDLLLoad(bundle
, subError
);
2670 #endif /* BINARY_SUPPORT_DLL */
2671 case __CFBundleNoBinary
:
2672 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for %@"), bundle
);
2673 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
2676 CFLog(__kCFLogBundle
, CFSTR("Cannot recognize type of executable for %@"), bundle
);
2677 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
2680 if (result
&& bundle
->_plugInData
._isPlugIn
) _CFBundlePlugInLoaded(bundle
);
2682 if (!result
&& error
) *error
= localError
;
2686 Boolean
CFBundleLoadExecutableAndReturnError(CFBundleRef bundle
, CFErrorRef
*error
) {
2687 return _CFBundleLoadExecutableAndReturnError(bundle
, false, error
);
2690 Boolean
CFBundleLoadExecutable(CFBundleRef bundle
) {
2691 return _CFBundleLoadExecutableAndReturnError(bundle
, false, NULL
);
2694 Boolean
CFBundlePreflightExecutable(CFBundleRef bundle
, CFErrorRef
*error
) {
2695 Boolean result
= false;
2696 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
2697 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
2699 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
2700 // make sure we know whether bundle is already loaded or not
2701 #if defined(BINARY_SUPPORT_DLFCN)
2702 if (!bundle
->_isLoaded
&& _useDlfcn
) _CFBundleDlfcnCheckLoaded(bundle
);
2703 #endif /* BINARY_SUPPORT_DLFCN */
2704 #if defined(BINARY_SUPPORT_DYLD)
2705 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
2706 // We might need to figure out what it is
2707 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
2708 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
2709 #if defined(BINARY_SUPPORT_CFM)
2710 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
2711 #endif /* BINARY_SUPPORT_CFM */
2713 #endif /* BINARY_SUPPORT_DYLD */
2714 if (executableURL
) CFRelease(executableURL
);
2716 if (bundle
->_isLoaded
) return true;
2718 switch (bundle
->_binaryType
) {
2719 #if defined(BINARY_SUPPORT_CFM)
2720 case __CFBundleCFMBinary
:
2721 case __CFBundleUnreadableBinary
:
2724 #elif defined(BINARY_SUPPORT_DLFCN)
2725 case __CFBundleUnreadableBinary
:
2726 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
2728 #endif /* BINARY_SUPPORT_CFM */
2729 #if defined(BINARY_SUPPORT_DYLD)
2730 case __CFBundleDYLDBundleBinary
:
2732 #if defined(BINARY_SUPPORT_DLFCN)
2733 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
2734 #endif /* BINARY_SUPPORT_DLFCN */
2736 case __CFBundleDYLDFrameworkBinary
:
2738 #if defined(BINARY_SUPPORT_DLFCN)
2739 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
2740 #endif /* BINARY_SUPPORT_DLFCN */
2742 case __CFBundleDYLDExecutableBinary
:
2743 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
2745 #endif /* BINARY_SUPPORT_DYLD */
2746 #if defined(BINARY_SUPPORT_DLFCN)
2747 case __CFBundleUnknownBinary
:
2748 case __CFBundleELFBinary
:
2749 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
2751 #endif /* BINARY_SUPPORT_DLFCN */
2752 #if defined(BINARY_SUPPORT_DLL)
2753 case __CFBundleDLLBinary
:
2756 #endif /* BINARY_SUPPORT_DLL */
2757 case __CFBundleNoBinary
:
2758 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
2761 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
2764 if (!result
&& error
) *error
= localError
;
2768 CFArrayRef
CFBundleCopyExecutableArchitectures(CFBundleRef bundle
) {
2769 CFArrayRef result
= NULL
;
2770 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
2771 if (executableURL
) {
2772 result
= _CFBundleCopyArchitecturesForExecutable(executableURL
);
2773 CFRelease(executableURL
);
2778 static Boolean
_CFBundleGetObjCImageInfo(CFBundleRef bundle
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2779 Boolean retval
= false;
2780 uint32_t localVersion
= 0, localFlags
= 0;
2781 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
2782 if (executableURL
) {
2783 retval
= _CFBundleGetObjCImageInfoForExecutable(executableURL
, &localVersion
, &localFlags
);
2784 CFRelease(executableURL
);
2786 if (objcVersion
) *objcVersion
= localVersion
;
2787 if (objcFlags
) *objcFlags
= localFlags
;
2791 void CFBundleUnloadExecutable(CFBundleRef bundle
) {
2792 // First unload bundles scheduled for unloading (if that's not what we are already doing.)
2793 if (!_scheduledBundlesAreUnloading
) _CFBundleUnloadScheduledBundles();
2795 if (!bundle
->_isLoaded
) return;
2797 // Remove from the scheduled unload set if we are there.
2798 if (!_scheduledBundlesAreUnloading
) __CFSpinLock(&CFBundleGlobalDataLock
);
2799 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
2800 if (!_scheduledBundlesAreUnloading
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
2802 // Give the plugIn code a chance to realize this...
2803 _CFPlugInWillUnload(bundle
);
2805 switch (bundle
->_binaryType
) {
2806 #if defined(BINARY_SUPPORT_CFM)
2807 case __CFBundleCFMBinary
:
2808 _CFBundleCFMUnload(bundle
);
2810 #endif /* BINARY_SUPPORT_CFM */
2811 #if defined(BINARY_SUPPORT_DYLD)
2812 case __CFBundleDYLDBundleBinary
:
2813 #if defined(BINARY_SUPPORT_DLFCN)
2814 if (bundle
->_handleCookie
) _CFBundleDlfcnUnload(bundle
); else
2815 #endif /* BINARY_SUPPORT_DLFCN */
2816 _CFBundleDYLDUnloadBundle(bundle
);
2818 case __CFBundleDYLDFrameworkBinary
:
2819 #if defined(BINARY_SUPPORT_DLFCN)
2820 if (bundle
->_handleCookie
&& _CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard
)) _CFBundleDlfcnUnload(bundle
);
2821 #endif /* BINARY_SUPPORT_DLFCN */
2823 #endif /* BINARY_SUPPORT_DYLD */
2824 #if defined(BINARY_SUPPORT_DLL)
2825 case __CFBundleDLLBinary
:
2826 _CFBundleDLLUnload(bundle
);
2828 #endif /* BINARY_SUPPORT_DLL */
2830 #if defined(BINARY_SUPPORT_DLFCN)
2831 if (bundle
->_handleCookie
) _CFBundleDlfcnUnload(bundle
);
2832 #endif /* BINARY_SUPPORT_DLFCN */
2835 if (!bundle
->_isLoaded
&& bundle
->_glueDict
) {
2836 CFDictionaryApplyFunction(bundle
->_glueDict
, _CFBundleDeallocateGlue
, (void *)CFGetAllocator(bundle
));
2837 CFRelease(bundle
->_glueDict
);
2838 bundle
->_glueDict
= NULL
;
2842 __private_extern__
void _CFBundleScheduleForUnloading(CFBundleRef bundle
) {
2843 __CFSpinLock(&CFBundleGlobalDataLock
);
2844 if (!_bundlesToUnload
) {
2845 // Create this from the default allocator
2846 CFSetCallBacks nonRetainingCallbacks
= kCFTypeSetCallBacks
;
2847 nonRetainingCallbacks
.retain
= NULL
;
2848 nonRetainingCallbacks
.release
= NULL
;
2849 _bundlesToUnload
= CFSetCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingCallbacks
);
2851 CFSetAddValue(_bundlesToUnload
, bundle
);
2852 __CFSpinUnlock(&CFBundleGlobalDataLock
);
2855 __private_extern__
void _CFBundleUnscheduleForUnloading(CFBundleRef bundle
) {
2856 __CFSpinLock(&CFBundleGlobalDataLock
);
2857 if (_bundlesToUnload
) {
2858 CFSetRemoveValue(_bundlesToUnload
, bundle
);
2860 __CFSpinUnlock(&CFBundleGlobalDataLock
);
2863 __private_extern__
void _CFBundleUnloadScheduledBundles(void) {
2864 __CFSpinLock(&CFBundleGlobalDataLock
);
2865 if (_bundlesToUnload
) {
2866 CFIndex c
= CFSetGetCount(_bundlesToUnload
);
2869 CFBundleRef
*unloadThese
= (CFBundleRef
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(CFBundleRef
) * c
, 0);
2870 CFSetGetValues(_bundlesToUnload
, (const void **)unloadThese
);
2871 _scheduledBundlesAreUnloading
= true;
2872 for (i
= 0; i
< c
; i
++) {
2873 // This will cause them to be removed from the set. (Which is why we copied all the values out of the set up front.)
2874 CFBundleUnloadExecutable(unloadThese
[i
]);
2876 _scheduledBundlesAreUnloading
= false;
2877 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, unloadThese
);
2880 __CFSpinUnlock(&CFBundleGlobalDataLock
);
2883 void *CFBundleGetFunctionPointerForName(CFBundleRef bundle
, CFStringRef funcName
) {
2885 // Load if necessary
2886 if (!bundle
->_isLoaded
) {
2887 if (!CFBundleLoadExecutable(bundle
)) return NULL
;
2890 switch (bundle
->_binaryType
) {
2891 #if defined(BINARY_SUPPORT_CFM)
2892 case __CFBundleCFMBinary
:
2893 tvp
= _CFBundleCFMGetSymbolByName(bundle
, funcName
, kTVectorCFragSymbol
);
2895 #endif /* BINARY_SUPPORT_CFM */
2896 #if defined(BINARY_SUPPORT_DYLD)
2897 case __CFBundleDYLDBundleBinary
:
2898 case __CFBundleDYLDFrameworkBinary
:
2899 case __CFBundleDYLDExecutableBinary
:
2900 #if defined(BINARY_SUPPORT_DLFCN)
2901 if (bundle
->_handleCookie
) return _CFBundleDlfcnGetSymbolByName(bundle
, funcName
);
2902 #endif /* BINARY_SUPPORT_DLFCN */
2903 return _CFBundleDYLDGetSymbolByName(bundle
, funcName
);
2905 #endif /* BINARY_SUPPORT_DYLD */
2906 #if defined(BINARY_SUPPORT_DLL)
2907 case __CFBundleDLLBinary
:
2908 tvp
= _CFBundleDLLGetSymbolByName(bundle
, funcName
);
2910 #endif /* BINARY_SUPPORT_DLL */
2912 #if defined(BINARY_SUPPORT_DLFCN)
2913 if (bundle
->_handleCookie
) return _CFBundleDlfcnGetSymbolByName(bundle
, funcName
);
2914 #endif /* BINARY_SUPPORT_DLFCN */
2917 #if defined(BINARY_SUPPORT_DYLD) && defined(BINARY_SUPPORT_CFM)
2919 if (!bundle
->_glueDict
) bundle
->_glueDict
= CFDictionaryCreateMutable(CFGetAllocator(bundle
), 0, NULL
, NULL
);
2920 void *fp
= (void *)CFDictionaryGetValue(bundle
->_glueDict
, tvp
);
2922 fp
= _CFBundleFunctionPointerForTVector(CFGetAllocator(bundle
), tvp
);
2923 CFDictionarySetValue(bundle
->_glueDict
, tvp
, fp
);
2927 #endif /* BINARY_SUPPORT_DYLD && BINARY_SUPPORT_CFM */
2931 void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle
, CFStringRef funcName
) {
2933 // Load if necessary
2934 if (!bundle
->_isLoaded
) {
2935 if (!CFBundleLoadExecutable(bundle
)) return NULL
;
2937 #if defined (BINARY_SUPPORT_CFM) || defined (BINARY_SUPPORT_DYLD) || defined (BINARY_SUPPORT_DLFCN)
2938 switch (bundle
->_binaryType
) {
2939 #if defined(BINARY_SUPPORT_CFM)
2940 case __CFBundleCFMBinary
:
2941 return _CFBundleCFMGetSymbolByName(bundle
, funcName
, kTVectorCFragSymbol
);
2943 #endif /* BINARY_SUPPORT_CFM */
2944 #if defined(BINARY_SUPPORT_DYLD)
2945 case __CFBundleDYLDBundleBinary
:
2946 case __CFBundleDYLDFrameworkBinary
:
2947 case __CFBundleDYLDExecutableBinary
:
2948 #if defined(BINARY_SUPPORT_DLFCN)
2949 if (bundle
->_handleCookie
) fp
= _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, funcName
, true); else
2950 #endif /* BINARY_SUPPORT_DLFCN */
2951 fp
= _CFBundleDYLDGetSymbolByNameWithSearch(bundle
, funcName
, true);
2953 #endif /* BINARY_SUPPORT_DYLD */
2955 #if defined(BINARY_SUPPORT_DLFCN)
2956 if (bundle
->_handleCookie
) fp
= _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, funcName
, true);
2957 #endif /* BINARY_SUPPORT_DLFCN */
2960 #endif /* BINARY_SUPPORT_CFM || BINARY_SUPPORT_DYLD || BINARY_SUPPORT_DLFCN */
2961 #if defined(BINARY_SUPPORT_DYLD) && defined(BINARY_SUPPORT_CFM)
2963 if (!bundle
->_glueDict
) bundle
->_glueDict
= CFDictionaryCreateMutable(CFGetAllocator(bundle
), 0, NULL
, NULL
);
2964 void *tvp
= (void *)CFDictionaryGetValue(bundle
->_glueDict
, fp
);
2966 tvp
= _CFBundleTVectorForFunctionPointer(CFGetAllocator(bundle
), fp
);
2967 CFDictionarySetValue(bundle
->_glueDict
, fp
, tvp
);
2971 #endif /* BINARY_SUPPORT_DYLD && BINARY_SUPPORT_CFM */
2975 void CFBundleGetFunctionPointersForNames(CFBundleRef bundle
, CFArrayRef functionNames
, void *ftbl
[]) {
2980 c
= CFArrayGetCount(functionNames
);
2981 for (i
= 0; i
< c
; i
++) {
2982 ftbl
[i
] = CFBundleGetFunctionPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(functionNames
, i
));
2986 void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle
, CFArrayRef functionNames
, void *ftbl
[]) {
2991 c
= CFArrayGetCount(functionNames
);
2992 for (i
= 0; i
< c
; i
++) {
2993 ftbl
[i
] = _CFBundleGetCFMFunctionPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(functionNames
, i
));
2997 void *CFBundleGetDataPointerForName(CFBundleRef bundle
, CFStringRef symbolName
) {
2999 // Load if necessary
3000 if (!bundle
->_isLoaded
) {
3001 if (!CFBundleLoadExecutable(bundle
)) return NULL
;
3004 switch (bundle
->_binaryType
) {
3005 #if defined(BINARY_SUPPORT_CFM)
3006 case __CFBundleCFMBinary
:
3007 dp
= _CFBundleCFMGetSymbolByName(bundle
, symbolName
, kDataCFragSymbol
);
3009 #endif /* BINARY_SUPPORT_CFM */
3010 #if defined(BINARY_SUPPORT_DYLD)
3011 case __CFBundleDYLDBundleBinary
:
3012 case __CFBundleDYLDFrameworkBinary
:
3013 case __CFBundleDYLDExecutableBinary
:
3014 #if defined(BINARY_SUPPORT_DLFCN)
3015 if (bundle
->_handleCookie
) dp
= _CFBundleDlfcnGetSymbolByName(bundle
, symbolName
); else
3016 #endif /* BINARY_SUPPORT_DLFCN */
3017 dp
= _CFBundleDYLDGetSymbolByName(bundle
, symbolName
);
3019 #endif /* BINARY_SUPPORT_DYLD */
3020 #if defined(BINARY_SUPPORT_DLL)
3021 case __CFBundleDLLBinary
:
3022 /* MF:!!! Handle this someday */
3024 #endif /* BINARY_SUPPORT_DLL */
3026 #if defined(BINARY_SUPPORT_DLFCN)
3027 if (bundle
->_handleCookie
) dp
= _CFBundleDlfcnGetSymbolByName(bundle
, symbolName
);
3028 #endif /* BINARY_SUPPORT_DLFCN */
3034 void CFBundleGetDataPointersForNames(CFBundleRef bundle
, CFArrayRef symbolNames
, void *stbl
[]) {
3039 c
= CFArrayGetCount(symbolNames
);
3040 for (i
= 0; i
< c
; i
++) {
3041 stbl
[i
] = CFBundleGetDataPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(symbolNames
, i
));
3045 __private_extern__ _CFResourceData
*__CFBundleGetResourceData(CFBundleRef bundle
) {
3046 return &(bundle
->_resourceData
);
3049 CFPlugInRef
CFBundleGetPlugIn(CFBundleRef bundle
) {
3050 if (bundle
->_plugInData
._isPlugIn
) {
3051 return (CFPlugInRef
)bundle
;
3057 __private_extern__ _CFPlugInData
*__CFBundleGetPlugInData(CFBundleRef bundle
) {
3058 return &(bundle
->_plugInData
);
3061 __private_extern__ Boolean
_CFBundleCouldBeBundle(CFURLRef url
) {
3062 Boolean result
= false;
3066 if (_CFGetFileProperties(kCFAllocatorSystemDefault
, url
, &exists
, &mode
, NULL
, NULL
, NULL
, NULL
) == 0) {
3067 result
= (exists
&& ((mode
& S_IFMT
) == S_IFDIR
) && ((mode
& 0444) != 0));
3072 #define LENGTH_OF(A) (sizeof(A) / sizeof(A[0]))
3074 __private_extern__ CFURLRef
_CFBundleCopyFrameworkURLForExecutablePath(CFAllocatorRef alloc
, CFStringRef executablePath
) {
3075 // MF:!!! Implement me. We need to be able to find the bundle from the exe, dealing with old vs. new as well as the Executables dir business on Windows.
3076 UniChar pathBuff
[CFMaxPathSize
];
3077 UniChar nameBuff
[CFMaxPathSize
];
3078 CFIndex length
, nameStart
, nameLength
, savedLength
;
3079 CFMutableStringRef cheapStr
= CFStringCreateMutableWithExternalCharactersNoCopy(alloc
, NULL
, 0, 0, NULL
);
3080 CFURLRef bundleURL
= NULL
;
3082 length
= CFStringGetLength(executablePath
);
3083 if (length
> CFMaxPathSize
) length
= CFMaxPathSize
;
3084 CFStringGetCharacters(executablePath
, CFRangeMake(0, length
), pathBuff
);
3086 // Save the name in nameBuff
3087 length
= _CFLengthAfterDeletingPathExtension(pathBuff
, length
);
3088 nameStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3089 nameLength
= length
- nameStart
;
3090 memmove(nameBuff
, &(pathBuff
[nameStart
]), nameLength
* sizeof(UniChar
));
3092 // Strip the name from pathBuff
3093 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3094 savedLength
= length
;
3096 // * Finally check the executable inside the framework case.
3098 // MF:!!! This should ensure the framework name is the same as the library name!
3101 length
= savedLength
;
3102 // To catch all the cases, we just peel off level looking for one ending in .framework or one called "Supporting Files".
3104 while (length
> 0) {
3105 curStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3106 if (curStart
>= length
) {
3109 CFStringSetExternalCharactersNoCopy(cheapStr
, &(pathBuff
[curStart
]), length
- curStart
, CFMaxPathSize
- curStart
);
3110 if (CFEqual(cheapStr
, _CFBundleSupportFilesDirectoryName1
) || CFEqual(cheapStr
, _CFBundleSupportFilesDirectoryName2
)) {
3111 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3112 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3113 bundleURL
= CFURLCreateWithFileSystemPath(alloc
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3114 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3115 CFRelease(bundleURL
);
3119 } else if (CFStringHasSuffix(cheapStr
, CFSTR(".framework"))) {
3120 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3121 bundleURL
= CFURLCreateWithFileSystemPath(alloc
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3122 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3123 CFRelease(bundleURL
);
3128 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3132 CFStringSetExternalCharactersNoCopy(cheapStr
, NULL
, 0, 0);
3133 CFRelease(cheapStr
);
3138 static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath
) {
3139 // This finds the bundle for the given path.
3140 // If an image path corresponds to a bundle, we see if there is already a bundle instance. If there is and it is NOT in the _dynamicBundles array, it is added to the staticBundles. Do not add the main bundle to the list here.
3142 CFURLRef curURL
= _CFBundleCopyFrameworkURLForExecutablePath(kCFAllocatorSystemDefault
, imagePath
);
3143 Boolean doFinalProcessing
= false;
3146 bundle
= _CFBundleFindByURL(curURL
, true);
3148 bundle
= _CFBundleCreate(kCFAllocatorSystemDefault
, curURL
, true, false);
3149 doFinalProcessing
= true;
3151 if (bundle
&& !bundle
->_isLoaded
) {
3152 // make sure that these bundles listed as loaded, and mark them frameworks (we probably can't see anything else here, and we cannot unload them)
3153 #if defined(BINARY_SUPPORT_DLFCN)
3154 if (!bundle
->_isLoaded
&& _useDlfcn
) _CFBundleDlfcnCheckLoaded(bundle
);
3155 #endif /* BINARY_SUPPORT_DLFCN */
3156 #if defined(BINARY_SUPPORT_DYLD)
3157 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= __CFBundleDYLDFrameworkBinary
;
3158 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
3159 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
3160 #endif /* BINARY_SUPPORT_DYLD */
3162 if (!bundle
->_isLoaded
) printf("ensure bundle %p set loaded fallback, handle %p image %p conn %p\n", bundle
, bundle
->_handleCookie
, bundle
->_imageCookie
, bundle
->_connectionCookie
);
3163 #endif /* LOG_BUNDLE_LOAD */
3164 bundle
->_isLoaded
= true;
3166 // Perform delayed final processing steps.
3167 // This must be done after _isLoaded has been set.
3168 if (bundle
&& doFinalProcessing
) {
3169 _CFBundleCheckWorkarounds(bundle
);
3170 if (_CFBundleNeedsInitPlugIn(bundle
)) {
3171 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3172 _CFBundleInitPlugIn(bundle
);
3173 __CFSpinLock(&CFBundleGlobalDataLock
);
3180 static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths
) {
3181 // This finds the bundles for the given paths.
3182 // If an image path corresponds to a bundle, we see if there is already a bundle instance. If there is and it is NOT in the _dynamicBundles array, it is added to the staticBundles. Do not add the main bundle to the list here (even if it appears in imagePaths).
3183 CFIndex i
, imagePathCount
= CFArrayGetCount(imagePaths
);
3185 for (i
= 0; i
< imagePathCount
; i
++) {
3186 _CFBundleEnsureBundleExistsForImagePath((CFStringRef
)CFArrayGetValueAtIndex(imagePaths
, i
));
3190 static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint
) {
3191 CFArrayRef imagePaths
= NULL
;
3192 // Tickle the main bundle into existence
3193 (void)_CFBundleGetMainBundleAlreadyLocked();
3194 #if defined(BINARY_SUPPORT_DYLD)
3195 imagePaths
= _CFBundleDYLDCopyLoadedImagePathsForHint(hint
);
3196 #endif /* BINARY_SUPPORT_DYLD */
3198 _CFBundleEnsureBundlesExistForImagePaths(imagePaths
);
3199 CFRelease(imagePaths
);
3203 static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void) {
3204 // This method returns all the statically linked bundles. This includes the main bundle as well as any frameworks that the process was linked against at launch time. It does not include frameworks or opther bundles that were loaded dynamically.
3205 CFArrayRef imagePaths
= NULL
;
3207 // Tickle the main bundle into existence
3208 (void)_CFBundleGetMainBundleAlreadyLocked();
3210 #if defined(BINARY_SUPPORT_DLL)
3211 // Dont know how to find static bundles for DLLs
3212 #endif /* BINARY_SUPPORT_DLL */
3214 #if defined(BINARY_SUPPORT_CFM)
3215 // CFM bundles are supplied to us by CFM, so we do not need to figure them out ourselves
3216 #endif /* BINARY_SUPPORT_CFM */
3218 #if defined(BINARY_SUPPORT_DYLD)
3219 imagePaths
= _CFBundleDYLDCopyLoadedImagePathsIfChanged();
3220 #endif /* BINARY_SUPPORT_DYLD */
3222 _CFBundleEnsureBundlesExistForImagePaths(imagePaths
);
3223 CFRelease(imagePaths
);
3227 CFArrayRef
CFBundleGetAllBundles(void) {
3228 // To answer this properly, we have to have created the static bundles!
3229 __CFSpinLock(&CFBundleGlobalDataLock
);
3230 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
3231 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3235 uint8_t _CFBundleLayoutVersion(CFBundleRef bundle
) {return bundle
->_version
;}
3237 CF_EXPORT CFURLRef
_CFBundleCopyInfoPlistURL(CFBundleRef bundle
) {
3238 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
3239 CFURLRef url
= (CFURLRef
)CFDictionaryGetValue(infoDict
, _kCFBundleInfoPlistURLKey
);
3240 if (!url
) url
= (CFURLRef
)CFDictionaryGetValue(infoDict
, _kCFBundleRawInfoPlistURLKey
);
3241 return (url
? (CFURLRef
)CFRetain(url
) : NULL
);
3244 CF_EXPORT CFURLRef
_CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle
) {return CFBundleCopyPrivateFrameworksURL(bundle
);}
3246 CF_EXPORT CFURLRef
CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle
) {
3247 CFURLRef result
= NULL
;
3249 if (1 == bundle
->_version
) {
3250 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase1
, bundle
->_url
);
3251 } else if (2 == bundle
->_version
) {
3252 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase2
, bundle
->_url
);
3254 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase0
, bundle
->_url
);
3259 CF_EXPORT CFURLRef
_CFBundleCopySharedFrameworksURL(CFBundleRef bundle
) {return CFBundleCopySharedFrameworksURL(bundle
);}
3261 CF_EXPORT CFURLRef
CFBundleCopySharedFrameworksURL(CFBundleRef bundle
) {
3262 CFURLRef result
= NULL
;
3264 if (1 == bundle
->_version
) {
3265 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase1
, bundle
->_url
);
3266 } else if (2 == bundle
->_version
) {
3267 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase2
, bundle
->_url
);
3269 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase0
, bundle
->_url
);
3274 CF_EXPORT CFURLRef
_CFBundleCopySharedSupportURL(CFBundleRef bundle
) {return CFBundleCopySharedSupportURL(bundle
);}
3276 CF_EXPORT CFURLRef
CFBundleCopySharedSupportURL(CFBundleRef bundle
) {
3277 CFURLRef result
= NULL
;
3279 if (1 == bundle
->_version
) {
3280 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase1
, bundle
->_url
);
3281 } else if (2 == bundle
->_version
) {
3282 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase2
, bundle
->_url
);
3284 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase0
, bundle
->_url
);
3289 __private_extern__ CFURLRef
_CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle
) {return CFBundleCopyBuiltInPlugInsURL(bundle
);}
3291 CF_EXPORT CFURLRef
CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle
) {
3292 CFURLRef result
= NULL
, alternateResult
= NULL
;
3294 CFAllocatorRef alloc
= CFGetAllocator(bundle
);
3295 if (1 == bundle
->_version
) {
3296 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase1
, bundle
->_url
);
3297 } else if (2 == bundle
->_version
) {
3298 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase2
, bundle
->_url
);
3300 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase0
, bundle
->_url
);
3302 if (!result
|| !_urlExists(alloc
, result
)) {
3303 if (1 == bundle
->_version
) {
3304 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase1
, bundle
->_url
);
3305 } else if (2 == bundle
->_version
) {
3306 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase2
, bundle
->_url
);
3308 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase0
, bundle
->_url
);
3310 if (alternateResult
&& _urlExists(alloc
, alternateResult
)) {
3311 if (result
) CFRelease(result
);
3312 result
= alternateResult
;
3314 if (alternateResult
) CFRelease(alternateResult
);
3322 #if defined(BINARY_SUPPORT_DYLD)
3324 static const void *__CFBundleDYLDFindImage(char *buff
) {
3325 const void *header
= NULL
;
3326 uint32_t i
, numImages
= _dyld_image_count(), numMatches
= 0;
3327 const char *curName
, *p
, *q
;
3329 for (i
= 0; !header
&& i
< numImages
; i
++) {
3330 curName
= _dyld_get_image_name(i
);
3331 if (curName
&& 0 == strncmp(curName
, buff
, CFMaxPathSize
)) {
3332 header
= _dyld_get_image_header(i
);
3337 for (i
= 0; i
< numImages
; i
++) {
3338 curName
= _dyld_get_image_name(i
);
3340 for (p
= buff
, q
= curName
; *p
&& *q
&& (q
- curName
< CFMaxPathSize
); p
++, q
++) {
3341 if (*p
!= *q
&& (q
- curName
> 11) && 0 == strncmp(q
- 11, ".framework/Versions/", 20) && *(q
+ 9) && '/' == *(q
+ 10)) q
+= 11;
3342 else if (*p
!= *q
&& (q
- curName
> 12) && 0 == strncmp(q
- 12, ".framework/Versions/", 20) && *(q
+ 8) && '/' == *(q
+ 9)) q
+= 10;
3343 if (*p
!= *q
) break;
3346 header
= _dyld_get_image_header(i
);
3352 return (numMatches
== 1) ? header
: NULL
;
3355 __private_extern__ Boolean
_CFBundleDYLDCheckLoaded(CFBundleRef bundle
) {
3356 if (!bundle
->_isLoaded
) {
3357 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3358 char buff
[CFMaxPathSize
];
3360 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3361 const void *header
= __CFBundleDYLDFindImage(buff
);
3363 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= __CFBundleDYLDFrameworkBinary
;
3364 if (!bundle
->_imageCookie
) {
3365 bundle
->_imageCookie
= header
;
3367 printf("dyld check load bundle %p, find %s getting image %p\n", bundle
, buff
, bundle
->_imageCookie
);
3368 #endif /* LOG_BUNDLE_LOAD */
3370 bundle
->_isLoaded
= true;
3373 printf("dyld check load bundle %p, find %s no image\n", bundle
, buff
);
3374 #endif /* LOG_BUNDLE_LOAD */
3377 if (executableURL
) CFRelease(executableURL
);
3379 return bundle
->_isLoaded
;
3382 __private_extern__ Boolean
_CFBundleDYLDLoadBundle(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
3383 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
3384 NSLinkEditErrors c
= NSLinkEditUndefinedError
;
3385 int errorNumber
= 0;
3386 const char *fileName
= NULL
;
3387 const char *errorString
= NULL
;
3389 if (!bundle
->_isLoaded
) {
3390 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3391 char buff
[CFMaxPathSize
];
3393 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3394 NSObjectFileImage image
;
3395 NSObjectFileImageReturnCode retCode
= NSCreateObjectFileImageFromFile(buff
, &image
);
3397 printf("dyld load bundle %p, create image of %s returns image %p retcode %d\n", bundle
, buff
, image
, retCode
);
3398 #endif /* LOG_BUNDLE_LOAD */
3399 if (retCode
== NSObjectFileImageSuccess
) {
3400 uint32_t options
= forceGlobal
? NSLINKMODULE_OPTION_RETURN_ON_ERROR
: (NSLINKMODULE_OPTION_BINDNOW
| NSLINKMODULE_OPTION_PRIVATE
| NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
3401 NSModule
module = NSLinkModule(image
, buff
, options
);
3403 printf("dyld load bundle %p, link module of %s options 0x%x returns module %p image %p\n", bundle
, buff
, options
, module, image
);
3404 #endif /* LOG_BUNDLE_LOAD */
3406 bundle
->_imageCookie
= image
;
3407 bundle
->_moduleCookie
= module;
3408 bundle
->_isLoaded
= true;
3410 NSLinkEditError(&c
, &errorNumber
, &fileName
, &errorString
);
3411 CFLog(__kCFLogBundle
, CFSTR("Error loading %s: error code %d, error number %d (%s)"), fileName
, c
, errorNumber
, errorString
);
3413 #if defined(BINARY_SUPPORT_DLFCN)
3414 _CFBundleDlfcnPreflight(bundle
, subError
);
3415 #endif /* BINARY_SUPPORT_DLFCN */
3417 CFStringRef debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("error code %d, error number %d (%s)"), c
, errorNumber
, errorString
);
3418 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
3419 CFRelease(debugString
);
3422 (void)NSDestroyObjectFileImage(image
);
3425 CFLog(__kCFLogBundle
, CFSTR("dyld returns %d when trying to load %@"), retCode
, executableURL
);
3427 if (retCode
== NSObjectFileImageArch
) {
3428 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableArchitectureMismatchError
);
3429 } else if (retCode
== NSObjectFileImageInappropriateFile
) {
3430 Boolean hasRuntimeMismatch
= false;
3431 uint32_t mainFlags
= 0, bundleFlags
= 0;
3432 if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL
, &mainFlags
) && (mainFlags
& 0x2) != 0) {
3433 if (_CFBundleGetObjCImageInfo(bundle
, NULL
, &bundleFlags
) && (bundleFlags
& 0x2) == 0) hasRuntimeMismatch
= true;
3435 if (hasRuntimeMismatch
) {
3436 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableRuntimeMismatchError
);
3438 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3441 #if defined(BINARY_SUPPORT_DLFCN)
3442 _CFBundleDlfcnPreflight(bundle
, subError
);
3443 #endif /* BINARY_SUPPORT_DLFCN */
3445 CFStringRef debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("dyld returns %d"), retCode
);
3446 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
3447 CFRelease(debugString
);
3453 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
3454 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3456 if (executableURL
) CFRelease(executableURL
);
3458 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
3459 return bundle
->_isLoaded
;
3462 __private_extern__ Boolean
_CFBundleDYLDLoadFramework(CFBundleRef bundle
, CFErrorRef
*error
) {
3463 // !!! Framework loading should be better. Can't unload frameworks.
3464 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
3465 NSLinkEditErrors c
= NSLinkEditUndefinedError
;
3466 int errorNumber
= 0;
3467 const char *fileName
= NULL
;
3468 const char *errorString
= NULL
;
3470 if (!bundle
->_isLoaded
) {
3471 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3472 char buff
[CFMaxPathSize
];
3474 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3475 void *image
= (void *)NSAddImage(buff
, NSADDIMAGE_OPTION_RETURN_ON_ERROR
);
3477 printf("dyld load framework %p, add image of %s returns image %p\n", bundle
, buff
, image
);
3478 #endif /* LOG_BUNDLE_LOAD */
3480 bundle
->_imageCookie
= image
;
3481 bundle
->_isLoaded
= true;
3483 NSLinkEditError(&c
, &errorNumber
, &fileName
, &errorString
);
3484 CFLog(__kCFLogBundle
, CFSTR("Error loading %s: error code %d, error number %d (%s)"), fileName
, c
, errorNumber
, errorString
);
3486 #if defined(BINARY_SUPPORT_DLFCN)
3487 _CFBundleDlfcnPreflight(bundle
, subError
);
3488 #endif /* BINARY_SUPPORT_DLFCN */
3490 CFStringRef debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("error code %d, error number %d (%s)"), c
, errorNumber
, errorString
);
3491 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
3492 CFRelease(debugString
);
3497 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
3498 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3500 if (executableURL
) CFRelease(executableURL
);
3502 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
3503 return bundle
->_isLoaded
;
3506 __private_extern__
void _CFBundleDYLDUnloadBundle(CFBundleRef bundle
) {
3507 if (bundle
->_isLoaded
) {
3509 printf("dyld unload bundle %p, handle %p module %p image %p\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
);
3510 #endif /* LOG_BUNDLE_LOAD */
3511 if (bundle
->_moduleCookie
&& !NSUnLinkModule((NSModule
)(bundle
->_moduleCookie
), NSUNLINKMODULE_OPTION_NONE
)) {
3512 CFLog(__kCFLogBundle
, CFSTR("Internal error unloading bundle %@"), bundle
);
3514 if (bundle
->_moduleCookie
&& bundle
->_imageCookie
) (void)NSDestroyObjectFileImage((NSObjectFileImage
)(bundle
->_imageCookie
));
3515 bundle
->_connectionCookie
= bundle
->_handleCookie
= NULL
;
3516 bundle
->_imageCookie
= bundle
->_moduleCookie
= NULL
;
3517 bundle
->_isLoaded
= false;
3522 __private_extern__
void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {return _CFBundleDYLDGetSymbolByNameWithSearch(bundle
, symbolName
, false);}
3524 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
) {
3525 void *result
= NULL
;
3527 NSSymbol symbol
= NULL
;
3530 if (CFStringGetCString(symbolName
, &(buff
[1]), 1024, kCFStringEncodingUTF8
)) {
3531 if (bundle
->_moduleCookie
) {
3532 symbol
= NSLookupSymbolInModule((NSModule
)(bundle
->_moduleCookie
), buff
);
3533 } else if (bundle
->_imageCookie
) {
3534 symbol
= NSLookupSymbolInImage(bundle
->_imageCookie
, buff
, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
|NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
);
3536 if (!symbol
&& !bundle
->_moduleCookie
&& (!bundle
->_imageCookie
|| globalSearch
)) {
3537 char hintBuff
[1026];
3538 CFStringRef executableName
= _CFBundleCopyExecutableName(kCFAllocatorSystemDefault
, bundle
, NULL
, NULL
);
3540 if (executableName
) {
3541 if (!CFStringGetCString(executableName
, hintBuff
, 1024, kCFStringEncodingUTF8
)) hintBuff
[0] = '\0';
3542 CFRelease(executableName
);
3544 // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint()
3545 // are identical, except the first just returns a bool, so checking with the
3546 // Is function first just causes a redundant lookup.
3547 // This returns NULL on failure.
3548 symbol
= NSLookupAndBindSymbolWithHint(buff
, hintBuff
);
3550 if (symbol
) result
= NSAddressOfSymbol(symbol
);
3552 if (!result
) CFLog(__kCFLogBundle
, CFSTR("dyld cannot find symbol %s in %@"), buff
, bundle
);
3555 printf("bundle %p handle %p module %p image %p dyld returns symbol %p for %s\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
, result
, buff
+ 1);
3556 #endif /* LOG_BUNDLE_LOAD */
3561 static CFStringRef
_CFBundleDYLDCopyLoadedImagePathForPointer(void *p
) {
3562 CFStringRef result
= NULL
;
3564 uint32_t i
, j
, n
= _dyld_image_count();
3565 Boolean foundit
= false;
3568 #define MACH_HEADER_TYPE struct mach_header_64
3569 #define MACH_SEGMENT_CMD_TYPE struct segment_command_64
3570 #define MACH_SEGMENT_FLAVOR LC_SEGMENT_64
3572 #define MACH_HEADER_TYPE struct mach_header
3573 #define MACH_SEGMENT_CMD_TYPE struct segment_command
3574 #define MACH_SEGMENT_FLAVOR LC_SEGMENT
3576 for (i
= 0; !foundit
&& i
< n
; i
++) {
3577 const MACH_HEADER_TYPE
*mh
= (const MACH_HEADER_TYPE
*)_dyld_get_image_header(i
);
3578 uintptr_t addr
= (uintptr_t)p
- _dyld_get_image_vmaddr_slide(i
);
3580 struct load_command
*lc
= (struct load_command
*)((char *)mh
+ sizeof(MACH_HEADER_TYPE
));
3581 for (j
= 0; !foundit
&& j
< mh
->ncmds
; j
++, lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
)) {
3582 if (MACH_SEGMENT_FLAVOR
== lc
->cmd
&& ((MACH_SEGMENT_CMD_TYPE
*)lc
)->vmaddr
<= addr
&& addr
< ((MACH_SEGMENT_CMD_TYPE
*)lc
)->vmaddr
+ ((MACH_SEGMENT_CMD_TYPE
*)lc
)->vmsize
) {
3584 name
= _dyld_get_image_name(i
);
3585 if (name
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, name
);
3590 #undef MACH_HEADER_TYPE
3591 #undef MACH_SEGMENT_CMD_TYPE
3592 #undef MACH_SEGMENT_FLAVOR
3595 printf("dyld image path for pointer %p is %p\n", p
, result
);
3596 #endif /* LOG_BUNDLE_LOAD */
3600 __private_extern__ CFArrayRef
_CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint
) {
3601 uint32_t i
, numImages
= _dyld_image_count();
3602 CFMutableArrayRef result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
3603 CFRange range
= CFRangeMake(0, CFStringGetLength(hint
));
3604 const char *processPath
= _CFProcessPath();
3606 for (i
= 0; i
< numImages
; i
++) {
3607 const char *curName
= _dyld_get_image_name(i
), *lastComponent
= NULL
;
3608 if (curName
&& (!processPath
|| 0 != strcmp(curName
, processPath
))) lastComponent
= strrchr(curName
, '/');
3609 if (lastComponent
) {
3610 CFStringRef str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, lastComponent
+ 1);
3612 if (CFStringFindWithOptions(hint
, str
, range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
)) {
3613 CFStringRef curStr
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, curName
);
3615 CFArrayAppendValue(result
, curStr
);
3626 static char *_cleanedPathForPath(const char *curName
) {
3627 char *thePath
= strdup(curName
);
3629 // We are going to process the buffer replacing all "/./" and "//" with "/"
3630 CFIndex srcIndex
= 0, dstIndex
= 0;
3631 CFIndex len
= strlen(thePath
);
3632 for (srcIndex
=0; srcIndex
<len
; srcIndex
++) {
3633 thePath
[dstIndex
] = thePath
[srcIndex
];
3635 while (srcIndex
< len
-1 && thePath
[srcIndex
] == '/' && (thePath
[srcIndex
+1] == '/' || (thePath
[srcIndex
+1] == '.' && srcIndex
< len
-2 && thePath
[srcIndex
+2] == '/'))) srcIndex
+= (thePath
[srcIndex
+1] == '/' ? 1 : 2);
3637 thePath
[dstIndex
] = 0;
3642 __private_extern__ CFArrayRef
_CFBundleDYLDCopyLoadedImagePathsIfChanged(void) {
3643 // This returns an array of the paths of all the dyld images in the process. These paths may not be absolute, they may point at things that are not bundles, they may be staticly linked bundles or dynamically loaded bundles, they may be NULL.
3644 static uint32_t _cachedDYLDImageCount
= -1;
3646 uint32_t i
, numImages
= _dyld_image_count();
3647 CFMutableArrayRef result
= NULL
;
3649 if (numImages
!= _cachedDYLDImageCount
) {
3650 const char *curName
;
3651 char *cleanedCurName
= NULL
;
3653 const char *processPath
= _CFProcessPath();
3655 result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
3657 for (i
= 0; i
< numImages
; i
++) {
3658 curName
= _dyld_get_image_name(i
);
3659 if (curName
&& i
== 0) cleanedCurName
= _cleanedPathForPath(curName
);
3660 if (curName
&& (!processPath
|| 0 != strcmp(curName
, processPath
)) && (!processPath
|| !cleanedCurName
|| 0 != strcmp(cleanedCurName
, processPath
))) {
3661 curStr
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, curName
);
3663 CFArrayAppendValue(result
, curStr
);
3667 if (cleanedCurName
) {
3668 free(cleanedCurName
);
3669 cleanedCurName
= NULL
;
3672 _cachedDYLDImageCount
= numImages
;
3677 #endif /* BINARY_SUPPORT_DYLD */
3679 #if defined(BINARY_SUPPORT_DLFCN)
3681 __private_extern__ Boolean
_CFBundleDlfcnCheckLoaded(CFBundleRef bundle
) {
3682 if (!bundle
->_isLoaded
) {
3683 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3684 char buff
[CFMaxPathSize
];
3686 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3687 int mode
= RTLD_LAZY
| RTLD_LOCAL
| RTLD_NOLOAD
| RTLD_FIRST
;
3688 void *handle
= dlopen(buff
, mode
);
3690 if (!bundle
->_handleCookie
) {
3691 bundle
->_handleCookie
= handle
;
3693 printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x getting handle %p\n", bundle
, buff
, mode
, bundle
->_handleCookie
);
3694 #endif /* LOG_BUNDLE_LOAD */
3696 bundle
->_isLoaded
= true;
3699 printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x no handle\n", bundle
, buff
, mode
);
3700 #endif /* LOG_BUNDLE_LOAD */
3703 if (executableURL
) CFRelease(executableURL
);
3705 return bundle
->_isLoaded
;
3708 static SInt32
_CFBundleCurrentArchitecture(void) {
3710 #if defined(__ppc__)
3711 arch
= kCFBundleExecutableArchitecturePPC
;
3712 #elif defined(__ppc64__)
3713 arch
= kCFBundleExecutableArchitecturePPC64
;
3714 #elif defined(__i386__)
3715 arch
= kCFBundleExecutableArchitectureI386
;
3716 #elif defined(__x86_64__)
3717 arch
= kCFBundleExecutableArchitectureX86_64
;
3718 #elif defined(BINARY_SUPPORT_DYLD)
3719 const NXArchInfo
*archInfo
= NXGetLocalArchInfo();
3720 if (archInfo
) arch
= archInfo
->cputype
;
3725 extern Boolean
_CFBundleDlfcnPreflight(CFBundleRef bundle
, CFErrorRef
*error
) {
3726 Boolean retval
= true;
3727 CFErrorRef localError
= NULL
;
3728 if (!bundle
->_isLoaded
) {
3729 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3730 char buff
[CFMaxPathSize
];
3733 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3734 retval
= dlopen_preflight(buff
);
3735 if (!retval
&& error
) {
3736 CFArrayRef archs
= CFBundleCopyExecutableArchitectures(bundle
);
3737 CFStringRef debugString
= NULL
;
3738 const char *errorString
= dlerror();
3739 if (errorString
&& strlen(errorString
) > 0) debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
3741 Boolean hasSuitableArch
= false, hasRuntimeMismatch
= false;
3742 CFIndex i
, count
= CFArrayGetCount(archs
);
3743 SInt32 arch
, curArch
= _CFBundleCurrentArchitecture();
3744 for (i
= 0; !hasSuitableArch
&& i
< count
; i
++) {
3745 if (CFNumberGetValue((CFNumberRef
)CFArrayGetValueAtIndex(archs
, i
), kCFNumberSInt32Type
, (void *)&arch
) && arch
== curArch
) hasSuitableArch
= true;
3747 #if defined(BINARY_SUPPORT_DYLD)
3748 if (hasSuitableArch
) {
3749 uint32_t mainFlags
= 0, bundleFlags
= 0;
3750 if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL
, &mainFlags
) && (mainFlags
& 0x2) != 0) {
3751 if (_CFBundleGetObjCImageInfo(bundle
, NULL
, &bundleFlags
) && (bundleFlags
& 0x2) == 0) hasRuntimeMismatch
= true;
3754 #endif /* BINARY_SUPPORT_DYLD */
3755 if (hasRuntimeMismatch
) {
3756 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableRuntimeMismatchError
, debugString
);
3757 } else if (!hasSuitableArch
) {
3758 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableArchitectureMismatchError
, debugString
);
3760 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLoadError
, debugString
);
3764 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLoadError
, debugString
);
3766 if (debugString
) CFRelease(debugString
);
3769 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3771 if (executableURL
) CFRelease(executableURL
);
3773 if (!retval
&& error
) *error
= localError
;
3777 __private_extern__ Boolean
_CFBundleDlfcnLoadBundle(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
3778 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
3779 if (!bundle
->_isLoaded
) {
3780 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3781 char buff
[CFMaxPathSize
];
3782 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3783 int mode
= forceGlobal
? (RTLD_LAZY
| RTLD_GLOBAL
| RTLD_FIRST
) : (RTLD_NOW
| RTLD_LOCAL
| RTLD_FIRST
);
3784 bundle
->_handleCookie
= dlopen(buff
, mode
);
3786 printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle
, buff
, mode
, bundle
->_handleCookie
);
3787 #endif /* LOG_BUNDLE_LOAD */
3788 if (bundle
->_handleCookie
) {
3789 bundle
->_isLoaded
= true;
3791 CFStringRef debugString
= NULL
;
3792 const char *errorString
= dlerror();
3794 CFLog(__kCFLogBundle
, CFSTR("Error loading %s: %s"), buff
, errorString
);
3795 debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
3797 CFLog(__kCFLogBundle
, CFSTR("Error loading %s"), buff
);
3799 if (error
&& _CFBundleDlfcnPreflight(bundle
, subError
)) localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
3800 if (debugString
) CFRelease(debugString
);
3803 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
3804 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3806 if (executableURL
) CFRelease(executableURL
);
3808 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
3809 return bundle
->_isLoaded
;
3812 __private_extern__ Boolean
_CFBundleDlfcnLoadFramework(CFBundleRef bundle
, CFErrorRef
*error
) {
3813 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
3814 if (!bundle
->_isLoaded
) {
3815 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3816 char buff
[CFMaxPathSize
];
3817 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3818 int mode
= RTLD_LAZY
| RTLD_GLOBAL
| RTLD_FIRST
;
3819 bundle
->_handleCookie
= dlopen(buff
, mode
);
3821 printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle
, buff
, mode
, bundle
->_handleCookie
);
3822 #endif /* LOG_BUNDLE_LOAD */
3823 if (bundle
->_handleCookie
) {
3824 bundle
->_isLoaded
= true;
3826 CFStringRef debugString
= NULL
;
3827 const char *errorString
= dlerror();
3829 CFLog(__kCFLogBundle
, CFSTR("Error loading %s: %s"), buff
, errorString
);
3830 debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
3832 CFLog(__kCFLogBundle
, CFSTR("Error loading %s"), buff
);
3834 if (error
&& _CFBundleDlfcnPreflight(bundle
, subError
)) localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
3835 if (debugString
) CFRelease(debugString
);
3838 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
3839 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3841 if (executableURL
) CFRelease(executableURL
);
3843 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
3844 return bundle
->_isLoaded
;
3847 __private_extern__
void _CFBundleDlfcnUnload(CFBundleRef bundle
) {
3848 if (bundle
->_isLoaded
) {
3850 printf("dlfcn unload bundle %p, handle %p module %p image %p\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
);
3851 #endif /* LOG_BUNDLE_LOAD */
3852 if (0 != dlclose(bundle
->_handleCookie
)) {
3853 CFLog(__kCFLogBundle
, CFSTR("Internal error unloading bundle %@"), bundle
);
3855 bundle
->_connectionCookie
= bundle
->_handleCookie
= NULL
;
3856 bundle
->_imageCookie
= bundle
->_moduleCookie
= NULL
;
3857 bundle
->_isLoaded
= false;
3862 __private_extern__
void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, symbolName
, false);}
3864 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
) {
3865 void *result
= NULL
;
3868 if (CFStringGetCString(symbolName
, buff
, 1024, kCFStringEncodingUTF8
)) {
3869 result
= dlsym(bundle
->_handleCookie
, buff
);
3870 if (!result
&& globalSearch
) result
= dlsym(RTLD_DEFAULT
, buff
);
3872 if (!result
) CFLog(__kCFLogBundle
, CFSTR("dlsym cannot find symbol %s in %@"), buff
, bundle
);
3875 printf("bundle %p handle %p module %p image %p dlsym returns symbol %p for %s\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
, result
, buff
);
3876 #endif /* LOG_BUNDLE_LOAD */
3881 static CFStringRef
_CFBundleDlfcnCopyLoadedImagePathForPointer(void *p
) {
3882 CFStringRef result
= NULL
;
3884 if (0 != dladdr(p
, &info
) && info
.dli_fname
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, info
.dli_fname
);
3886 printf("dlfcn image path for pointer %p is %p\n", p
, result
);
3887 #endif /* LOG_BUNDLE_LOAD */
3891 #endif /* BINARY_SUPPORT_DLFCN */
3894 #if defined(BINARY_SUPPORT_DLL)
3896 __private_extern__ Boolean
_CFBundleDLLLoad(CFBundleRef bundle
, CFErrorRef
*error
) {
3897 CFErrorRef localError
= NULL
;
3898 if (!bundle
->_isLoaded
) {
3899 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3900 TCHAR buff
[CFMaxPathSize
];
3902 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
3903 bundle
->_hModule
= LoadLibrary(buff
);
3904 if (bundle
->_hModule
) {
3905 bundle
->_isLoaded
= true;
3907 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
);
3910 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
3911 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3913 if (executableURL
) CFRelease(executableURL
);
3915 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
3916 return bundle
->_isLoaded
;
3919 __private_extern__
void _CFBundleDLLUnload(CFBundleRef bundle
) {
3920 if (bundle
->_isLoaded
) {
3921 FreeLibrary(bundle
->_hModule
);
3922 bundle
->_hModule
= NULL
;
3923 bundle
->_isLoaded
= false;
3927 __private_extern__
void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {
3928 void *result
= NULL
;
3930 if (CFStringGetCString(symbolName
, buff
, 1024, kCFStringEncodingWindowsLatin1
)) result
= GetProcAddress(bundle
->_hModule
, buff
);
3934 #endif /* BINARY_SUPPORT_DLL */
3936 /* Workarounds to be applied in the presence of certain bundles can go here. This is called on every bundle creation.
3938 extern void _CFStringSetCompatibility(CFOptionFlags
);
3940 static void _CFBundleCheckWorkarounds(CFBundleRef bundle
) {