2 * Copyright (c) 2011 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@
25 Copyright (c) 1999-2011, Apple Inc. All rights reserved.
26 Responsibility: David Smith
29 #include "CFBundle_Internal.h"
30 #include <CoreFoundation/CFPropertyList.h>
31 #include <CoreFoundation/CFNumber.h>
32 #include <CoreFoundation/CFSet.h>
33 #include <CoreFoundation/CFURLAccess.h>
34 #include <CoreFoundation/CFError.h>
36 #include <CoreFoundation/CFPriv.h>
37 #include "CFInternal.h"
38 #include <CoreFoundation/CFByteOrder.h>
39 #include "CFBundle_BinaryTypes.h"
40 #include <CoreFoundation/CFVersionCheck.h>
45 #define AVOID_WEAK_COLLECTIONS 1
47 #if !defined(AVOID_WEAK_COLLECTIONS)
48 #include "CFHashTable.h"
49 #include "CFMapTable.h"
50 #include "CFPointerArray.h"
51 #endif /* !AVOID_WEAK_COLLECTIONS */
53 #if defined(BINARY_SUPPORT_DYLD)
54 // Import the mach-o headers that define the macho magic numbers
55 #include <mach-o/loader.h>
56 #include <mach-o/fat.h>
57 #include <mach-o/arch.h>
58 #include <mach-o/dyld.h>
59 #include <mach-o/getsect.h>
63 #include <crt_externs.h>
64 #if defined(USE_DYLD_PRIV)
65 #include <mach-o/dyld_priv.h>
66 #endif /* USE_DYLD_PRIV */
67 #endif /* BINARY_SUPPORT_DYLD */
69 #if defined(BINARY_SUPPORT_DLFCN)
71 #endif /* BINARY_SUPPORT_DLFCN */
73 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
75 #elif DEPLOYMENT_TARGET_WINDOWS
80 #define stat(x,y) _NS_stat(x,y)
83 #error Unknown or unspecified DEPLOYMENT_TARGET
86 extern void _processInfoDictionary(CFMutableDictionaryRef dict
, CFStringRef platformSuffix
, CFStringRef productSuffix
);
87 extern CFStringRef
_CFGetProductName(void);
88 extern CFStringRef
_CFGetPlatformName(void);
89 extern CFStringRef
_CFGetAlternatePlatformName(void);
91 static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle
, Boolean alreadyLocked
);
93 #define LOG_BUNDLE_LOAD 0
95 // Public CFBundle Info plist keys
96 CONST_STRING_DECL(kCFBundleInfoDictionaryVersionKey
, "CFBundleInfoDictionaryVersion")
97 CONST_STRING_DECL(kCFBundleExecutableKey
, "CFBundleExecutable")
98 CONST_STRING_DECL(kCFBundleIdentifierKey
, "CFBundleIdentifier")
99 CONST_STRING_DECL(kCFBundleVersionKey
, "CFBundleVersion")
100 CONST_STRING_DECL(kCFBundleDevelopmentRegionKey
, "CFBundleDevelopmentRegion")
101 CONST_STRING_DECL(kCFBundleLocalizationsKey
, "CFBundleLocalizations")
103 // Private CFBundle Info plist keys, possible candidates for public constants
104 CONST_STRING_DECL(_kCFBundleAllowMixedLocalizationsKey
, "CFBundleAllowMixedLocalizations")
105 CONST_STRING_DECL(_kCFBundleSupportedPlatformsKey
, "CFBundleSupportedPlatforms")
106 CONST_STRING_DECL(_kCFBundleResourceSpecificationKey
, "CFBundleResourceSpecification")
109 CONST_STRING_DECL(_kCFBundlePackageTypeKey
, "CFBundlePackageType")
110 CONST_STRING_DECL(_kCFBundleSignatureKey
, "CFBundleSignature")
111 CONST_STRING_DECL(_kCFBundleIconFileKey
, "CFBundleIconFile")
112 CONST_STRING_DECL(_kCFBundleDocumentTypesKey
, "CFBundleDocumentTypes")
113 CONST_STRING_DECL(_kCFBundleURLTypesKey
, "CFBundleURLTypes")
115 // Keys that are usually localized in InfoPlist.strings
116 CONST_STRING_DECL(kCFBundleNameKey
, "CFBundleName")
117 CONST_STRING_DECL(_kCFBundleDisplayNameKey
, "CFBundleDisplayName")
118 CONST_STRING_DECL(_kCFBundleShortVersionStringKey
, "CFBundleShortVersionString")
119 CONST_STRING_DECL(_kCFBundleGetInfoStringKey
, "CFBundleGetInfoString")
120 CONST_STRING_DECL(_kCFBundleGetInfoHTMLKey
, "CFBundleGetInfoHTML")
122 // Sub-keys for CFBundleDocumentTypes dictionaries
123 CONST_STRING_DECL(_kCFBundleTypeNameKey
, "CFBundleTypeName")
124 CONST_STRING_DECL(_kCFBundleTypeRoleKey
, "CFBundleTypeRole")
125 CONST_STRING_DECL(_kCFBundleTypeIconFileKey
, "CFBundleTypeIconFile")
126 CONST_STRING_DECL(_kCFBundleTypeOSTypesKey
, "CFBundleTypeOSTypes")
127 CONST_STRING_DECL(_kCFBundleTypeExtensionsKey
, "CFBundleTypeExtensions")
128 CONST_STRING_DECL(_kCFBundleTypeMIMETypesKey
, "CFBundleTypeMIMETypes")
130 // Sub-keys for CFBundleURLTypes dictionaries
131 CONST_STRING_DECL(_kCFBundleURLNameKey
, "CFBundleURLName")
132 CONST_STRING_DECL(_kCFBundleURLIconFileKey
, "CFBundleURLIconFile")
133 CONST_STRING_DECL(_kCFBundleURLSchemesKey
, "CFBundleURLSchemes")
135 // Compatibility key names
136 CONST_STRING_DECL(_kCFBundleOldExecutableKey
, "NSExecutable")
137 CONST_STRING_DECL(_kCFBundleOldInfoDictionaryVersionKey
, "NSInfoPlistVersion")
138 CONST_STRING_DECL(_kCFBundleOldNameKey
, "NSHumanReadableName")
139 CONST_STRING_DECL(_kCFBundleOldIconFileKey
, "NSIcon")
140 CONST_STRING_DECL(_kCFBundleOldDocumentTypesKey
, "NSTypes")
141 CONST_STRING_DECL(_kCFBundleOldShortVersionStringKey
, "NSAppVersion")
143 // Compatibility CFBundleDocumentTypes key names
144 CONST_STRING_DECL(_kCFBundleOldTypeNameKey
, "NSName")
145 CONST_STRING_DECL(_kCFBundleOldTypeRoleKey
, "NSRole")
146 CONST_STRING_DECL(_kCFBundleOldTypeIconFileKey
, "NSIcon")
147 CONST_STRING_DECL(_kCFBundleOldTypeExtensions1Key
, "NSUnixExtensions")
148 CONST_STRING_DECL(_kCFBundleOldTypeExtensions2Key
, "NSDOSExtensions")
149 CONST_STRING_DECL(_kCFBundleOldTypeOSTypesKey
, "NSMacOSType")
151 // Internally used keys for loaded Info plists.
152 CONST_STRING_DECL(_kCFBundleInfoPlistURLKey
, "CFBundleInfoPlistURL")
153 CONST_STRING_DECL(_kCFBundleRawInfoPlistURLKey
, "CFBundleRawInfoPlistURL")
154 CONST_STRING_DECL(_kCFBundleNumericVersionKey
, "CFBundleNumericVersion")
155 CONST_STRING_DECL(_kCFBundleExecutablePathKey
, "CFBundleExecutablePath")
156 CONST_STRING_DECL(_kCFBundleResourcesFileMappedKey
, "CSResourcesFileMapped")
157 CONST_STRING_DECL(_kCFBundleCFMLoadAsBundleKey
, "CFBundleCFMLoadAsBundle")
159 // Keys used by NSBundle for loaded Info plists.
160 CONST_STRING_DECL(_kCFBundleInitialPathKey
, "NSBundleInitialPath")
161 CONST_STRING_DECL(_kCFBundleResolvedPathKey
, "NSBundleResolvedPath")
162 CONST_STRING_DECL(_kCFBundlePrincipalClassKey
, "NSPrincipalClass")
164 static char __CFBundleMainID__
[1026] = {0};
165 __private_extern__
char *__CFBundleMainID
= __CFBundleMainID__
;
167 static CFTypeID __kCFBundleTypeID
= _kCFRuntimeNotATypeID
;
175 __strong CFDictionaryRef _infoDict
; // the ref stored in here must always be allocated with kCFAllocatorSystemDefaultGCRefZero
176 __strong CFDictionaryRef _localInfoDict
; // the ref stored in here must always be allocated with kCFAllocatorSystemDefaultGCRefZero
177 CFArrayRef _searchLanguages
;
179 __CFPBinaryType _binaryType
;
182 Boolean _sharesStringsFiles
;
186 void *_connectionCookie
;
189 const void *_imageCookie
;
190 const void *_moduleCookie
;
195 /* CFM<->DYLD glue */
196 CFMutableDictionaryRef _glueDict
;
198 /* Resource fork goop */
199 _CFResourceData _resourceData
;
201 _CFPlugInData _plugInData
;
203 CFSpinLock_t _bundleLoadingLock
;
205 #if defined(BINARY_SUPPORT_DLL)
207 #endif /* BINARY_SUPPORT_DLL */
211 static CFSpinLock_t CFBundleGlobalDataLock
= CFSpinLockInit
;
213 static CFMutableDictionaryRef _bundlesByIdentifier
= NULL
;
214 #if defined(AVOID_WEAK_COLLECTIONS)
215 static CFMutableDictionaryRef _bundlesByURL
= NULL
;
216 static CFMutableArrayRef _allBundles
= NULL
;
217 static CFMutableSetRef _bundlesToUnload
= NULL
;
218 #else /* AVOID_WEAK_COLLECTIONS */
219 static __CFHashTable
*_allBundles
= nil
;
220 static __CFHashTable
*_bundlesToUnload
= nil
;
221 #endif /* AVOID_WEAK_COLLECTIONS */
222 static Boolean _scheduledBundlesAreUnloading
= false;
224 static Boolean _initedMainBundle
= false;
225 static CFBundleRef _mainBundle
= NULL
;
226 static CFStringRef _defaultLocalization
= NULL
;
228 // Forward declares functions.
229 static CFBundleRef
_CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
, Boolean alreadyLocked
, Boolean doFinalProcessing
);
230 static CFStringRef
_CFBundleCopyExecutableName(CFBundleRef bundle
, CFURLRef url
, CFDictionaryRef infoDict
);
231 static CFURLRef
_CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle
);
232 static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint
);
233 static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void);
234 static void _CFBundleCheckWorkarounds(CFBundleRef bundle
);
235 static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath
);
236 static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths
);
237 #if defined(BINARY_SUPPORT_DYLD)
238 static CFMutableDictionaryRef
_CFBundleGrokInfoDictFromMainExecutable(void);
239 static Boolean
_CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion
, uint32_t *objcFlags
);
240 static CFStringRef
_CFBundleDYLDCopyLoadedImagePathForPointer(void *p
);
241 #if !defined(BINARY_SUPPORT_DLFCN)
242 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
);
243 #endif /* !BINARY_SUPPORT_DLFCN */
244 #endif /* BINARY_SUPPORT_DYLD */
245 #if defined(BINARY_SUPPORT_DLFCN)
246 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
);
247 #if !defined(BINARY_SUPPORT_DYLD)
248 static CFStringRef
_CFBundleDlfcnCopyLoadedImagePathForPointer(void *p
);
249 #endif /* !BINARY_SUPPORT_DYLD */
250 #endif /* BINARY_SUPPORT_DLFCN */
253 #if defined(AVOID_WEAK_COLLECTIONS)
255 static void _CFBundleAddToTables(CFBundleRef bundle
, Boolean alreadyLocked
) {
256 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
258 if (!alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
260 // Add to the _allBundles list
262 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
263 nonRetainingArrayCallbacks
.retain
= NULL
;
264 nonRetainingArrayCallbacks
.release
= NULL
;
265 _allBundles
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
267 CFArrayAppendValue(_allBundles
, bundle
);
269 // Add to the table that maps urls to bundles
270 if (!_bundlesByURL
) {
271 CFDictionaryValueCallBacks nonRetainingDictionaryValueCallbacks
= kCFTypeDictionaryValueCallBacks
;
272 nonRetainingDictionaryValueCallbacks
.retain
= NULL
;
273 nonRetainingDictionaryValueCallbacks
.release
= NULL
;
274 _bundlesByURL
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &nonRetainingDictionaryValueCallbacks
);
276 CFDictionarySetValue(_bundlesByURL
, bundle
->_url
, bundle
);
278 // Add to the table that maps identifiers to bundles
280 CFMutableArrayRef bundlesWithThisID
= NULL
;
281 CFBundleRef existingBundle
= NULL
;
282 if (!_bundlesByIdentifier
) {
283 _bundlesByIdentifier
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
285 bundlesWithThisID
= (CFMutableArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
286 if (bundlesWithThisID
) {
287 CFIndex i
, count
= CFArrayGetCount(bundlesWithThisID
);
288 UInt32 existingVersion
, newVersion
= CFBundleGetVersionNumber(bundle
);
289 for (i
= 0; i
< count
; i
++) {
290 existingBundle
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, i
);
291 existingVersion
= CFBundleGetVersionNumber(existingBundle
);
292 // If you load two bundles with the same identifier and the same version, the last one wins.
293 if (newVersion
>= existingVersion
) break;
295 CFArrayInsertValueAtIndex(bundlesWithThisID
, i
, bundle
);
297 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
298 nonRetainingArrayCallbacks
.retain
= NULL
;
299 nonRetainingArrayCallbacks
.release
= NULL
;
300 bundlesWithThisID
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
301 CFArrayAppendValue(bundlesWithThisID
, bundle
);
302 CFDictionarySetValue(_bundlesByIdentifier
, bundleID
, bundlesWithThisID
);
303 CFRelease(bundlesWithThisID
);
306 if (!alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
309 static void _CFBundleRemoveFromTables(CFBundleRef bundle
, CFURLRef bundleURL
, CFStringRef bundleID
) {
310 __CFSpinLock(&CFBundleGlobalDataLock
);
311 // Remove from the various lists
313 CFIndex i
= CFArrayGetFirstIndexOfValue(_allBundles
, CFRangeMake(0, CFArrayGetCount(_allBundles
)), bundle
);
314 if (i
>= 0) CFArrayRemoveValueAtIndex(_allBundles
, i
);
317 // Remove from the table that maps urls to bundles
318 if (bundleURL
&& _bundlesByURL
) {
319 CFBundleRef bundleForURL
= (CFBundleRef
)CFDictionaryGetValue(_bundlesByURL
, bundleURL
);
320 if (bundleForURL
== bundle
) CFDictionaryRemoveValue(_bundlesByURL
, bundleURL
);
323 // Remove from the table that maps identifiers to bundles
324 if (bundleID
&& _bundlesByIdentifier
) {
325 CFMutableArrayRef bundlesWithThisID
= (CFMutableArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
326 if (bundlesWithThisID
) {
327 CFIndex count
= CFArrayGetCount(bundlesWithThisID
);
328 while (count
-- > 0) if (bundle
== (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, count
)) CFArrayRemoveValueAtIndex(bundlesWithThisID
, count
);
329 if (0 == CFArrayGetCount(bundlesWithThisID
)) CFDictionaryRemoveValue(_bundlesByIdentifier
, bundleID
);
332 __CFSpinUnlock(&CFBundleGlobalDataLock
);
335 static CFBundleRef
_CFBundleCopyBundleForURL(CFURLRef url
, Boolean alreadyLocked
) {
336 CFBundleRef result
= NULL
;
337 if (!alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
338 if (_bundlesByURL
) result
= (CFBundleRef
)CFDictionaryGetValue(_bundlesByURL
, url
);
339 if (result
&& !result
->_url
) {
341 CFDictionaryRemoveValue(_bundlesByURL
, url
);
343 if (result
) CFRetain(result
);
344 if (!alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
348 static CFBundleRef
_CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID
) {
349 CFBundleRef result
= NULL
, bundle
;
350 if (_bundlesByIdentifier
&& bundleID
) {
351 // Note that this array is maintained in descending order by version number
352 CFArrayRef bundlesWithThisID
= (CFArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
353 if (bundlesWithThisID
) {
354 CFIndex i
, count
= CFArrayGetCount(bundlesWithThisID
);
356 // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
357 for (i
= 0; !result
&& i
< count
; i
++) {
358 bundle
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, i
);
359 if (CFBundleIsExecutableLoaded(bundle
)) result
= bundle
;
361 // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
362 if (!result
) result
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, 0);
369 #else /* AVOID_WEAK_COLLECTIONS */
372 An explanation of what I'm doing here is probably in order.
373 8029300 has cast suspicion on the correctness of __CFMapTable with strong keys and weak values, at least under non-GC.
374 An early attempt to work around it by inserting dummy values instead of removing things succeeded, as did turning on the AVOID_WEAK_COLLECTIONS #ifdef
375 This indicates that it's not an overrelease in securityd, since AVOID_WEAK_COLLECTIONS wouldn't help in that case.
376 Therefore, these functions following this comment allow us to have _bundlesByURL be a CFDictionary on non-GC and keep __CFMapTable to GC where it's needed.
378 static inline id
_getBundlesByURL() {
379 static id _bundles
= nil
;
380 static dispatch_once_t onceToken
;
381 dispatch_once(&onceToken
, ^{
382 if (CF_USING_COLLECTABLE_MEMORY
) {
383 _bundles
= [[__CFMapTable alloc
] initWithKeyOptions
:CFPointerFunctionsStrongMemory valueOptions
:CFPointerFunctionsZeroingWeakMemory capacity
:0];
385 CFDictionaryValueCallBacks nonRetainingDictionaryValueCallbacks
= kCFTypeDictionaryValueCallBacks
;
386 nonRetainingDictionaryValueCallbacks
.retain
= NULL
;
387 nonRetainingDictionaryValueCallbacks
.release
= NULL
;
388 _bundles
= (id
)CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &nonRetainingDictionaryValueCallbacks
);
394 #define _bundlesByURL _getBundlesByURL()
396 static void _setInBundlesByURL(CFURLRef key
, CFBundleRef bundle
) {
397 if (CF_USING_COLLECTABLE_MEMORY
) {
398 [(__CFMapTable
*)_bundlesByURL setObject
:(id
)bundle forKey
:(id
)key
];
400 CFDictionarySetValue((CFMutableDictionaryRef
)_bundlesByURL
, key
, bundle
);
404 static void _removeFromBundlesByURL(CFURLRef key
) {
405 if (CF_USING_COLLECTABLE_MEMORY
) {
406 [(__CFMapTable
*)_bundlesByURL removeObjectForKey
:(id
)key
];
408 CFDictionaryRemoveValue((CFMutableDictionaryRef
)_bundlesByURL
, key
);
412 static CFBundleRef
_getFromBundlesByURL(CFURLRef key
) {
413 if (CF_USING_COLLECTABLE_MEMORY
) {
414 return (CFBundleRef
)[(__CFMapTable
*)_bundlesByURL objectForKey
:(id
)key
];
416 return (CFBundleRef
)CFDictionaryGetValue((CFMutableDictionaryRef
)_bundlesByURL
, key
);
420 static void _CFBundleAddToTables(CFBundleRef bundle
, Boolean alreadyLocked
) {
421 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
423 if (!alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
425 // Add to the _allBundles list
426 if (!_allBundles
) _allBundles
= [[__CFHashTable alloc
] initWithOptions
:CFPointerFunctionsZeroingWeakMemory capacity
:0];
427 [_allBundles addObject
:(id
)bundle
];
429 // Add to the table that maps urls to bundles
430 _setInBundlesByURL(bundle
->_url
, bundle
);
432 // Add to the table that maps identifiers to bundles
434 __CFPointerArray
*bundlesWithThisID
= nil
;
435 CFBundleRef existingBundle
= NULL
;
436 if (!_bundlesByIdentifier
) {
437 _bundlesByIdentifier
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
439 bundlesWithThisID
= (__CFPointerArray
*)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
440 if (bundlesWithThisID
) {
441 CFIndex i
, count
= (CFIndex
)[bundlesWithThisID count
];
442 UInt32 existingVersion
, newVersion
= CFBundleGetVersionNumber(bundle
);
443 for (i
= 0; i
< count
; i
++) {
444 existingBundle
= (CFBundleRef
)[bundlesWithThisID pointerAtIndex
:i
];
445 if (!existingBundle
) continue;
446 existingVersion
= CFBundleGetVersionNumber(existingBundle
);
447 // If you load two bundles with the same identifier and the same version, the last one wins.
448 if (newVersion
>= existingVersion
) break;
451 [bundlesWithThisID insertPointer
:bundle atIndex
:i
];
453 [bundlesWithThisID addPointer
:bundle
];
456 bundlesWithThisID
= [[__CFPointerArray alloc
] initWithOptions
:CFPointerFunctionsZeroingWeakMemory
];
457 [bundlesWithThisID addPointer
:bundle
];
458 CFDictionarySetValue(_bundlesByIdentifier
, bundleID
, bundlesWithThisID
);
459 [bundlesWithThisID release
];
462 if (!alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
465 static void _CFBundleRemoveFromTables(CFBundleRef bundle
, CFURLRef bundleURL
, CFStringRef bundleID
) {
466 __CFSpinLock(&CFBundleGlobalDataLock
);
467 // Remove from the various lists
468 if (_allBundles
&& [_allBundles member
:(id
)bundle
]) [_allBundles removeObject
:(id
)bundle
];
470 // Remove from the table that maps urls to bundles
472 _removeFromBundlesByURL(bundleURL
);
475 // Remove from the table that maps identifiers to bundles
476 if (bundleID
&& _bundlesByIdentifier
) {
477 __CFPointerArray
*bundlesWithThisID
= (__CFPointerArray
*)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
478 if (bundlesWithThisID
) {
479 CFIndex count
= (CFIndex
)[bundlesWithThisID count
];
480 while (count
-- > 0) if (bundle
== (CFBundleRef
)[bundlesWithThisID pointerAtIndex
:count
]) [bundlesWithThisID removePointerAtIndex
:count
];
481 [bundlesWithThisID compact
];
482 if (0 == [bundlesWithThisID count
]) CFDictionaryRemoveValue(_bundlesByIdentifier
, bundleID
);
485 __CFSpinUnlock(&CFBundleGlobalDataLock
);
488 static CFBundleRef
_CFBundleCopyBundleForURL(CFURLRef url
, Boolean alreadyLocked
) {
489 CFBundleRef result
= NULL
;
490 if (!alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
491 result
= _getFromBundlesByURL(url
);
492 if (result
&& !result
->_url
) {
494 _removeFromBundlesByURL(url
);
496 if (result
) CFRetain(result
);
497 if (!alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
501 static CFBundleRef
_CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID
) {
502 CFBundleRef result
= NULL
;
503 if (_bundlesByIdentifier
&& bundleID
) {
504 // Note that this array is maintained in descending order by version number
505 __CFPointerArray
*bundlesWithThisID
= (__CFPointerArray
*)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
506 if (bundlesWithThisID
&& [bundlesWithThisID count
] > 0) {
507 // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
508 for (id bundle in bundlesWithThisID
) {
509 if (bundle
&& CFBundleIsExecutableLoaded((CFBundleRef
)bundle
)) {
510 result
= (CFBundleRef
)bundle
;
514 // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
516 for (id bundle in bundlesWithThisID
) {
518 result
= (CFBundleRef
)bundle
;
528 #endif /* AVOID_WEAK_COLLECTIONS */
530 #if 0 && DEPLOYMENT_TARGET_WINDOWS
531 static CFStringRef
_CFBundleCopyWrapperInBinaryDirectory(CFStringRef strippedExeName
) {
532 char buff
[CFMaxPathSize
];
536 CFArrayRef binaryDirs
= _CFGetWindowsBinaryDirectories();
537 int count
= CFArrayGetCount(binaryDirs
);
540 for (i
= 0; i
< count
; i
++) {
541 str
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@\\%@.app"), CFArrayGetValueAtIndex(binaryDirs
,i
), strippedExeName
);
542 buffLen
= CFStringGetLength(str
);
543 CFStringGetFileSystemRepresentation(str
, buff
, CFMaxPathSize
);
544 if (stat(buff
, &garbage
) == 0) return str
;
549 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
551 #error Unknown or unspecified DEPLOYMENT_TARGET
554 static CFURLRef
_CFBundleCopyBundleURLForExecutablePath(CFStringRef str
) {
555 //!!! need to handle frameworks, NT; need to integrate with NSBundle - drd
556 UniChar buff
[CFMaxPathSize
];
561 buffLen
= CFStringGetLength(str
);
562 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
563 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
565 #if 0 && DEPLOYMENT_TARGET_WINDOWS
566 CFIndex startOfBinaryName
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
) + 1; // Remove exe name
567 CFIndex endOfBinaryName
= _CFLengthAfterDeletingPathExtension(buff
, buffLen
);
568 if (startOfBinaryName
> 0 && startOfBinaryName
< buffLen
&& endOfBinaryName
> 0 && endOfBinaryName
<= buffLen
) {
569 CFStringRef strippedExeName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfBinaryName
]), endOfBinaryName
- startOfBinaryName
);
570 CFStringRef wrapperInBinaryDirectory
= _CFBundleCopyWrapperInBinaryDirectory(strippedExeName
);
571 if (wrapperInBinaryDirectory
) {
572 buffLen
= CFStringGetLength(wrapperInBinaryDirectory
);
573 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
574 CFStringGetCharacters(wrapperInBinaryDirectory
, CFRangeMake(0, buffLen
), buff
);
575 CFRelease(wrapperInBinaryDirectory
);
576 outstr
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, buff
, buffLen
, kCFAllocatorNull
);
577 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, outstr
, PLATFORM_PATH_STYLE
, true);
582 #elif DEPLOYMENT_TARGET_WINDOWS
583 // Is this a .dll or .exe?
584 if (buffLen
>= 5 && (_wcsnicmp((wchar_t *)&(buff
[buffLen
-4]), L
".dll", 4) == 0 || _wcsnicmp((wchar_t *)&(buff
[buffLen
-4]), L
".exe", 4) == 0)) {
585 CFIndex extensionLength
= CFStringGetLength(_CFBundleWindowsResourceDirectoryExtension
);
587 // If this is an _debug, we should strip that before looking for the bundle
588 if (buffLen
>= 7 && (_wcsnicmp((wchar_t *)&buff
[buffLen
-6], L
"_debug", 6) == 0)) buffLen
-= 6;
590 if (buffLen
+ 1 + extensionLength
< CFMaxPathSize
) {
593 CFStringGetCharacters(_CFBundleWindowsResourceDirectoryExtension
, CFRangeMake(0, extensionLength
), buff
+ buffLen
);
594 buffLen
+= extensionLength
;
595 outstr
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, buff
, buffLen
, kCFAllocatorNull
);
596 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, outstr
, PLATFORM_PATH_STYLE
, true);
600 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
602 #error Unknown or unspecified DEPLOYMENT_TARGET
606 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
); // Remove exe name
608 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
610 // See if this is a new bundle. If it is, we have to remove more path components.
611 CFIndex startOfLastDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
612 if (startOfLastDir
> 0 && startOfLastDir
< buffLen
) {
613 CFStringRef lastDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfLastDir
]), buffLen
- startOfLastDir
);
615 if (CFEqual(lastDirName
, _CFBundleGetPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetAlternatePlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName())) {
616 // This is a new bundle. Back off a few more levels
618 // Remove platform folder
619 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
622 // Remove executables folder (if present)
623 CFIndex startOfNextDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
624 if (startOfNextDir
> 0 && startOfNextDir
< buffLen
) {
625 CFStringRef nextDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfNextDir
]), buffLen
- startOfNextDir
);
626 if (CFEqual(nextDirName
, _CFBundleExecutablesDirectoryName
)) buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
627 CFRelease(nextDirName
);
631 // Remove support files folder
632 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
633 #elif 0 && DEPLOYMENT_TARGET_WINDOWS
635 // See if this is a new bundle. If it is, we have to remove more path components.
636 CFIndex startOfLastDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
637 if (startOfLastDir
> 0 && startOfLastDir
< buffLen
) {
638 CFStringRef lastDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfLastDir
]), buffLen
- startOfLastDir
);
640 if (CFEqual(lastDirName
, _CFBundleGetPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetAlternatePlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName())) {
641 // This is a new bundle. Back off a few more levels
643 // Remove platform folder
644 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
647 // Remove executables folder (if present)
648 CFIndex startOfNextDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
649 if (startOfNextDir
> 0 && startOfNextDir
< buffLen
) {
650 CFStringRef nextDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfNextDir
]), buffLen
- startOfNextDir
);
651 if (CFEqual(nextDirName
, _CFBundleExecutablesDirectoryName
)) buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
652 CFRelease(nextDirName
);
654 #error Unknown or unspecified DEPLOYMENT_TARGET
658 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_WINDOWS
659 CFRelease(lastDirName
);
662 #elif 0 && DEPLOYMENT_TARGET_WINDOWS
664 // Remove support files folder
665 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
668 CFRelease(lastDirName
);
672 #error Unknown or unspecified DEPLOYMENT_TARGET
676 outstr
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, buff
, buffLen
, kCFAllocatorNull
);
677 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, outstr
, PLATFORM_PATH_STYLE
, true);
684 static CFURLRef
_CFBundleCopyResolvedURLForExecutableURL(CFURLRef url
) {
685 // this is necessary so that we match any sanitization CFURL may perform on the result of _CFBundleCopyBundleURLForExecutableURL()
686 CFURLRef absoluteURL
, url1
, url2
, outURL
= NULL
;
687 CFStringRef str
, str1
, str2
;
688 absoluteURL
= CFURLCopyAbsoluteURL(url
);
689 str
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
);
691 UniChar buff
[CFMaxPathSize
];
692 CFIndex buffLen
= CFStringGetLength(str
), len1
;
693 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
694 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
695 len1
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
696 if (len1
> 0 && len1
+ 1 < buffLen
) {
697 str1
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, buff
, len1
);
698 CFIndex skipSlashCount
= 1;
699 #if DEPLOYMENT_TARGET_WINDOWS
700 // On Windows, _CFLengthAfterDeletingLastPathComponent will return a value of 3 if the path is at the root (e.g. C:\). This includes the \, which is not the case for URLs with subdirectories
701 if (len1
== 3 && buff
[1] == ':' && buff
[2] == '\\') {
705 str2
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, buff
+ len1
+ skipSlashCount
, buffLen
- len1
- skipSlashCount
);
707 url1
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str1
, PLATFORM_PATH_STYLE
, true);
709 url2
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, str2
, PLATFORM_PATH_STYLE
, false, url1
);
711 outURL
= CFURLCopyAbsoluteURL(url2
);
717 if (str1
) CFRelease(str1
);
718 if (str2
) CFRelease(str2
);
723 outURL
= absoluteURL
;
725 CFRelease(absoluteURL
);
730 CFURLRef
_CFBundleCopyBundleURLForExecutableURL(CFURLRef url
) {
731 CFURLRef resolvedURL
, outurl
= NULL
;
733 resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
734 str
= CFURLCopyFileSystemPath(resolvedURL
, PLATFORM_PATH_STYLE
);
736 outurl
= _CFBundleCopyBundleURLForExecutablePath(str
);
739 CFRelease(resolvedURL
);
743 static uint8_t _CFBundleEffectiveLayoutVersion(CFBundleRef bundle
) {
744 uint8_t localVersion
= bundle
->_version
;
745 // exclude type 0 bundles with no binary (or CFM binary) and no Info.plist, since they give too many false positives
746 if (0 == localVersion
) {
747 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
748 if (!infoDict
|| 0 == CFDictionaryGetCount(infoDict
)) {
749 #if defined(BINARY_SUPPORT_DYLD)
750 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
752 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
753 if (bundle
->_binaryType
== __CFBundleCFMBinary
|| bundle
->_binaryType
== __CFBundleUnreadableBinary
) {
756 bundle
->_resourceData
._executableLacksResourceFork
= true;
758 CFRelease(executableURL
);
763 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
765 CFRelease(executableURL
);
769 #endif /* BINARY_SUPPORT_DYLD */
775 CFBundleRef
_CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
776 CFBundleRef bundle
= CFBundleCreate(allocator
, url
);
778 uint8_t localVersion
= _CFBundleEffectiveLayoutVersion(bundle
);
779 if (3 == localVersion
|| 4 == localVersion
) {
787 CFBundleRef
_CFBundleGetMainBundleIfLooksLikeBundle(void) {
788 CFBundleRef mainBundle
= CFBundleGetMainBundle();
789 if (mainBundle
&& (3 == mainBundle
->_version
|| 4 == mainBundle
->_version
)) mainBundle
= NULL
;
793 Boolean
_CFBundleMainBundleInfoDictionaryComesFromResourceFork(void) {
794 CFBundleRef mainBundle
= CFBundleGetMainBundle();
795 return (mainBundle
&& mainBundle
->_resourceData
._infoDictionaryFromResourceFork
);
798 CFBundleRef
_CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
799 CFBundleRef bundle
= NULL
;
800 CFURLRef bundleURL
= _CFBundleCopyBundleURLForExecutableURL(url
), resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
801 if (bundleURL
&& resolvedURL
) {
802 bundle
= _CFBundleCreateIfLooksLikeBundle(allocator
, bundleURL
);
804 CFURLRef executableURL
= _CFBundleCopyExecutableURLIgnoringCache(bundle
);
805 char buff1
[CFMaxPathSize
], buff2
[CFMaxPathSize
];
806 if (!executableURL
|| !CFURLGetFileSystemRepresentation(resolvedURL
, true, (uint8_t *)buff1
, CFMaxPathSize
) || !CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff2
, CFMaxPathSize
) || 0 != strcmp(buff1
, buff2
)) {
810 if (executableURL
) CFRelease(executableURL
);
813 if (bundleURL
) CFRelease(bundleURL
);
814 if (resolvedURL
) CFRelease(resolvedURL
);
818 CFBundleRef
_CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
819 CFBundleRef bundle
= CFBundleCreate(allocator
, url
);
821 Boolean mightBeBundle
= true, isDir
= false;
822 uint8_t localVersion
= _CFBundleEffectiveLayoutVersion(bundle
);
823 if (3 == localVersion
) {
824 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
825 CFURLRef executableURL
, supportFilesURL
, resourceSpecificationFileURL
;
826 CFArrayRef supportedPlatforms
;
827 CFStringRef resourceSpecificationFile
;
829 mightBeBundle
= false;
830 if (infoDict
&& CFDictionaryGetValue(infoDict
, kCFBundleExecutableKey
) && (executableURL
= _CFBundleCopyExecutableURLIgnoringCache(bundle
))) {
831 supportedPlatforms
= _CFBundleGetSupportedPlatforms(bundle
);
832 resourceSpecificationFile
= (CFStringRef
)CFDictionaryGetValue(infoDict
, _kCFBundleResourceSpecificationKey
);
833 if (supportedPlatforms
&& CFArrayGetCount(supportedPlatforms
) > 0 && CFArrayGetFirstIndexOfValue(supportedPlatforms
, CFRangeMake(0, CFArrayGetCount(supportedPlatforms
)), CFSTR("iPhoneOS")) >= 0) {
834 mightBeBundle
= true;
835 } else if (resourceSpecificationFile
&& CFGetTypeID(resourceSpecificationFile
) == CFStringGetTypeID() && (supportFilesURL
= CFBundleCopySupportFilesDirectoryURL(bundle
))) {
836 resourceSpecificationFileURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, resourceSpecificationFile
, kCFURLPOSIXPathStyle
, false, supportFilesURL
);
837 if (resourceSpecificationFileURL
) {
838 if (_CFIsResourceAtURL(resourceSpecificationFileURL
, &isDir
) && !isDir
) mightBeBundle
= true;
839 CFRelease(resourceSpecificationFileURL
);
841 CFRelease(supportFilesURL
);
843 CFRelease(executableURL
);
845 } else if (4 == localVersion
) {
846 mightBeBundle
= false;
848 if (!mightBeBundle
) {
856 CFBundleRef
_CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
857 CFBundleRef bundle
= NULL
;
858 CFURLRef bundleURL
= _CFBundleCopyBundleURLForExecutableURL(url
), resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
859 if (bundleURL
&& resolvedURL
) {
860 bundle
= _CFBundleCreateIfMightBeBundle(allocator
, bundleURL
);
862 CFURLRef executableURL
= _CFBundleCopyExecutableURLIgnoringCache(bundle
);
863 char buff1
[CFMaxPathSize
], buff2
[CFMaxPathSize
];
864 if (!executableURL
|| !CFURLGetFileSystemRepresentation(resolvedURL
, true, (uint8_t *)buff1
, CFMaxPathSize
) || !CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff2
, CFMaxPathSize
) || 0 != strcmp(buff1
, buff2
)) {
868 if (executableURL
) CFRelease(executableURL
);
871 if (bundleURL
) CFRelease(bundleURL
);
872 if (resolvedURL
) CFRelease(resolvedURL
);
876 CFURLRef
_CFBundleCopyMainBundleExecutableURL(Boolean
*looksLikeBundle
) {
877 // This function is for internal use only; _mainBundle is deliberately accessed outside of the lock to get around a reentrancy issue
878 const char *processPath
;
879 CFStringRef str
= NULL
;
880 CFURLRef executableURL
= NULL
;
881 processPath
= _CFProcessPath();
883 str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, processPath
);
885 executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str
, PLATFORM_PATH_STYLE
, false);
889 if (looksLikeBundle
) {
890 CFBundleRef mainBundle
= _mainBundle
;
891 if (mainBundle
&& (3 == mainBundle
->_version
|| 4 == mainBundle
->_version
)) mainBundle
= NULL
;
892 *looksLikeBundle
= (mainBundle
? true : false);
894 return executableURL
;
897 static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef executablePath
) {
898 CFBundleGetInfoDictionary(_mainBundle
);
899 if (!_mainBundle
->_infoDict
|| CFDictionaryGetCount(_mainBundle
->_infoDict
) == 0) {
900 // if type 3 bundle and no Info.plist, treat as unbundled, since this gives too many false positives
901 if (_mainBundle
->_version
== 3) _mainBundle
->_version
= 4;
902 if (_mainBundle
->_version
== 0) {
903 // if type 0 bundle and no Info.plist and not main executable for bundle, treat as unbundled, since this gives too many false positives
904 CFStringRef executableName
= _CFBundleCopyExecutableName(_mainBundle
, NULL
, NULL
);
905 if (!executableName
|| !executablePath
|| !CFStringHasSuffix(executablePath
, executableName
)) _mainBundle
->_version
= 4;
906 if (executableName
) CFRelease(executableName
);
908 #if defined(BINARY_SUPPORT_DYLD)
909 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
) {
910 if (_mainBundle
->_infoDict
&& !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(_mainBundle
->_infoDict
);
911 _mainBundle
->_infoDict
= (CFDictionaryRef
)_CFBundleGrokInfoDictFromMainExecutable();
913 #endif /* BINARY_SUPPORT_DYLD */
915 #if defined(BINARY_SUPPORT_DYLD)
916 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
) {
917 // if dyld and not main executable for bundle, prefer info dictionary from executable
918 CFStringRef executableName
= _CFBundleCopyExecutableName(_mainBundle
, NULL
, NULL
);
919 if (!executableName
|| !executablePath
|| !CFStringHasSuffix(executablePath
, executableName
)) {
920 CFDictionaryRef infoDictFromExecutable
= (CFDictionaryRef
)_CFBundleGrokInfoDictFromMainExecutable();
921 if (infoDictFromExecutable
&& CFDictionaryGetCount(infoDictFromExecutable
) > 0) {
922 if (_mainBundle
->_infoDict
&& !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(_mainBundle
->_infoDict
);
923 _mainBundle
->_infoDict
= infoDictFromExecutable
;
926 if (executableName
) CFRelease(executableName
);
928 #endif /* BINARY_SUPPORT_DYLD */
930 if (!_mainBundle
->_infoDict
) _mainBundle
->_infoDict
= CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
931 if (!CFDictionaryGetValue(_mainBundle
->_infoDict
, _kCFBundleExecutablePathKey
)) CFDictionarySetValue((CFMutableDictionaryRef
)(_mainBundle
->_infoDict
), _kCFBundleExecutablePathKey
, executablePath
);
932 CFStringRef bundleID
= (CFStringRef
)CFDictionaryGetValue(_mainBundle
->_infoDict
, kCFBundleIdentifierKey
);
934 if (!CFStringGetCString(bundleID
, __CFBundleMainID__
, sizeof(__CFBundleMainID__
) - 2, kCFStringEncodingUTF8
)) {
935 __CFBundleMainID__
[0] = '\0';
940 static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle
, Boolean alreadyLocked
) {
941 CFDictionaryRef oldInfoDict
= bundle
->_infoDict
;
944 _CFBundleFlushCachesForURL(bundle
->_url
);
945 bundle
->_infoDict
= NULL
;
946 if (bundle
->_localInfoDict
) {
947 if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(bundle
->_localInfoDict
);
948 bundle
->_localInfoDict
= NULL
;
950 if (bundle
->_searchLanguages
) {
951 CFRelease(bundle
->_searchLanguages
);
952 bundle
->_searchLanguages
= NULL
;
954 if (bundle
->_resourceData
._stringTableCache
) {
955 CFRelease(bundle
->_resourceData
._stringTableCache
);
956 bundle
->_resourceData
._stringTableCache
= NULL
;
958 if (bundle
== _mainBundle
) {
959 CFStringRef executablePath
= oldInfoDict
? (CFStringRef
)CFDictionaryGetValue(oldInfoDict
, _kCFBundleExecutablePathKey
) : NULL
;
960 if (!alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
961 _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(executablePath
);
962 if (!alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
964 CFBundleGetInfoDictionary(bundle
);
967 if (!bundle
->_infoDict
) bundle
->_infoDict
= CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
968 val
= CFDictionaryGetValue(oldInfoDict
, _kCFBundleInitialPathKey
);
969 if (val
) CFDictionarySetValue((CFMutableDictionaryRef
)bundle
->_infoDict
, _kCFBundleInitialPathKey
, val
);
970 val
= CFDictionaryGetValue(oldInfoDict
, _kCFBundleResolvedPathKey
);
971 if (val
) CFDictionarySetValue((CFMutableDictionaryRef
)bundle
->_infoDict
, _kCFBundleResolvedPathKey
, val
);
972 val
= CFDictionaryGetValue(oldInfoDict
, _kCFBundlePrincipalClassKey
);
973 if (val
) CFDictionarySetValue((CFMutableDictionaryRef
)bundle
->_infoDict
, _kCFBundlePrincipalClassKey
, val
);
974 if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(oldInfoDict
);
978 CF_EXPORT
void _CFBundleFlushBundleCaches(CFBundleRef bundle
) {
979 _CFBundleFlushBundleCachesAlreadyLocked(bundle
, false);
982 static CFBundleRef
_CFBundleGetMainBundleAlreadyLocked(void) {
983 if (!_initedMainBundle
) {
984 const char *processPath
;
985 CFStringRef str
= NULL
;
986 CFURLRef executableURL
= NULL
, bundleURL
= NULL
;
987 _initedMainBundle
= true;
988 processPath
= _CFProcessPath();
990 str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, processPath
);
991 if (!executableURL
) executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str
, PLATFORM_PATH_STYLE
, false);
993 if (executableURL
) bundleURL
= _CFBundleCopyBundleURLForExecutableURL(executableURL
);
995 // make sure that main bundle has executable path
996 //??? what if we are not the main executable in the bundle?
997 // NB doFinalProcessing must be false here, see below
998 _mainBundle
= _CFBundleCreate(kCFAllocatorSystemDefault
, bundleURL
, true, false);
1000 // make sure that the main bundle is listed as loaded, and mark it as executable
1001 _mainBundle
->_isLoaded
= true;
1002 #if defined(BINARY_SUPPORT_DYLD)
1003 if (_mainBundle
->_binaryType
== __CFBundleUnknownBinary
) {
1004 if (!executableURL
) {
1005 _mainBundle
->_binaryType
= __CFBundleNoBinary
;
1007 _mainBundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
1008 if (_mainBundle
->_binaryType
!= __CFBundleCFMBinary
&& _mainBundle
->_binaryType
!= __CFBundleUnreadableBinary
) _mainBundle
->_resourceData
._executableLacksResourceFork
= true;
1011 #endif /* BINARY_SUPPORT_DYLD */
1012 // get cookie for already-loaded main bundle
1013 #if defined(BINARY_SUPPORT_DLFCN)
1014 if (!_mainBundle
->_handleCookie
) {
1015 _mainBundle
->_handleCookie
= dlopen(NULL
, RTLD_NOLOAD
| RTLD_FIRST
);
1017 printf("main bundle %p getting handle %p\n", _mainBundle
, _mainBundle
->_handleCookie
);
1018 #endif /* LOG_BUNDLE_LOAD */
1020 #elif defined(BINARY_SUPPORT_DYLD)
1021 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
&& !_mainBundle
->_imageCookie
) {
1022 _mainBundle
->_imageCookie
= (void *)_dyld_get_image_header(0);
1024 printf("main bundle %p getting image %p\n", _mainBundle
, _mainBundle
->_imageCookie
);
1025 #endif /* LOG_BUNDLE_LOAD */
1027 #endif /* BINARY_SUPPORT_DLFCN */
1028 _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(str
);
1029 // Perform delayed final processing steps.
1030 // This must be done after _isLoaded has been set, for security reasons (3624341).
1031 _CFBundleCheckWorkarounds(_mainBundle
);
1032 if (_CFBundleNeedsInitPlugIn(_mainBundle
)) {
1033 __CFSpinUnlock(&CFBundleGlobalDataLock
);
1034 _CFBundleInitPlugIn(_mainBundle
);
1035 __CFSpinLock(&CFBundleGlobalDataLock
);
1039 if (bundleURL
) CFRelease(bundleURL
);
1040 if (str
) CFRelease(str
);
1041 if (executableURL
) CFRelease(executableURL
);
1046 CFBundleRef
CFBundleGetMainBundle(void) {
1047 CFBundleRef mainBundle
;
1048 __CFSpinLock(&CFBundleGlobalDataLock
);
1049 mainBundle
= _CFBundleGetMainBundleAlreadyLocked();
1050 __CFSpinUnlock(&CFBundleGlobalDataLock
);
1054 CFBundleRef
CFBundleGetBundleWithIdentifier(CFStringRef bundleID
) {
1055 CFBundleRef result
= NULL
;
1057 __CFSpinLock(&CFBundleGlobalDataLock
);
1058 (void)_CFBundleGetMainBundleAlreadyLocked();
1059 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
1060 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1062 // Try to create the bundle for the caller and try again
1063 void *p
= __builtin_return_address(0);
1065 CFStringRef imagePath
= NULL
;
1066 #if defined(BINARY_SUPPORT_DYLD)
1067 if (!imagePath
) imagePath
= _CFBundleDYLDCopyLoadedImagePathForPointer(p
);
1068 #elif defined(BINARY_SUPPORT_DLFCN)
1069 if (!imagePath
) imagePath
= _CFBundleDlfcnCopyLoadedImagePathForPointer(p
);
1070 #endif /* BINARY_SUPPORT_DYLD */
1072 _CFBundleEnsureBundleExistsForImagePath(imagePath
);
1073 CFRelease(imagePath
);
1075 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
1078 #elif DEPLOYMENT_TARGET_WINDOWS
1080 #error Unknown or unspecified DEPLOYMENT_TARGET
1083 // Try to guess the bundle from the identifier and try again
1084 _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(bundleID
);
1085 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
1088 // Make sure all bundles have been created and try again.
1089 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
1090 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
1092 __CFSpinUnlock(&CFBundleGlobalDataLock
);
1097 static CFStringRef
__CFBundleCopyDescription(CFTypeRef cf
) {
1098 char buff
[CFMaxPathSize
];
1099 CFStringRef path
= NULL
, binaryType
= NULL
, retval
= NULL
;
1100 if (((CFBundleRef
)cf
)->_url
&& CFURLGetFileSystemRepresentation(((CFBundleRef
)cf
)->_url
, true, (uint8_t *)buff
, CFMaxPathSize
)) path
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, buff
);
1101 switch (((CFBundleRef
)cf
)->_binaryType
) {
1102 case __CFBundleCFMBinary
:
1103 binaryType
= CFSTR("");
1105 case __CFBundleDYLDExecutableBinary
:
1106 binaryType
= CFSTR("executable, ");
1108 case __CFBundleDYLDBundleBinary
:
1109 binaryType
= CFSTR("bundle, ");
1111 case __CFBundleDYLDFrameworkBinary
:
1112 binaryType
= CFSTR("framework, ");
1114 case __CFBundleDLLBinary
:
1115 binaryType
= CFSTR("DLL, ");
1117 case __CFBundleUnreadableBinary
:
1118 binaryType
= CFSTR("");
1121 binaryType
= CFSTR("");
1124 if (((CFBundleRef
)cf
)->_plugInData
._isPlugIn
) {
1125 retval
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("CFBundle/CFPlugIn %p <%@> (%@%@loaded)"), cf
, path
, binaryType
, ((CFBundleRef
)cf
)->_isLoaded
? CFSTR("") : CFSTR("not "));
1127 retval
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("CFBundle %p <%@> (%@%@loaded)"), cf
, path
, binaryType
, ((CFBundleRef
)cf
)->_isLoaded
? CFSTR("") : CFSTR("not "));
1129 if (path
) CFRelease(path
);
1133 static void _CFBundleDeallocateGlue(const void *key
, const void *value
, void *context
) {
1134 CFAllocatorRef allocator
= (CFAllocatorRef
)context
;
1135 if (value
) CFAllocatorDeallocate(allocator
, (void *)value
);
1138 static void __CFBundleDeallocate(CFTypeRef cf
) {
1139 CFBundleRef bundle
= (CFBundleRef
)cf
;
1141 CFStringRef bundleID
= NULL
;
1143 __CFGenericValidateType(cf
, __kCFBundleTypeID
);
1144 bundleURL
= bundle
->_url
;
1145 bundle
->_url
= NULL
;
1146 if (bundle
->_infoDict
) bundleID
= (CFStringRef
)CFDictionaryGetValue(bundle
->_infoDict
, kCFBundleIdentifierKey
);
1147 _CFBundleRemoveFromTables(bundle
, bundleURL
, bundleID
);
1148 CFBundleUnloadExecutable(bundle
);
1149 _CFBundleDeallocatePlugIn(bundle
);
1151 _CFBundleFlushCachesForURL(bundleURL
);
1152 CFRelease(bundleURL
);
1154 if (bundle
->_infoDict
&& !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(bundle
->_infoDict
);
1155 if (bundle
->_modDate
) CFRelease(bundle
->_modDate
);
1156 if (bundle
->_localInfoDict
&& !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(bundle
->_localInfoDict
);
1157 if (bundle
->_searchLanguages
) CFRelease(bundle
->_searchLanguages
);
1158 if (bundle
->_glueDict
) {
1159 CFDictionaryApplyFunction(bundle
->_glueDict
, _CFBundleDeallocateGlue
, (void *)CFGetAllocator(bundle
));
1160 CFRelease(bundle
->_glueDict
);
1162 if (bundle
->_resourceData
._stringTableCache
) CFRelease(bundle
->_resourceData
._stringTableCache
);
1165 static const CFRuntimeClass __CFBundleClass
= {
1166 _kCFRuntimeScannedObject
,
1170 __CFBundleDeallocate
,
1174 __CFBundleCopyDescription
1177 // From CFBundle_Resources.c
1178 void _CFBundleResourcesInitialize();
1180 __private_extern__
void __CFBundleInitialize(void) {
1181 __kCFBundleTypeID
= _CFRuntimeRegisterClass(&__CFBundleClass
);
1182 _CFBundleResourcesInitialize();
1185 CFTypeID
CFBundleGetTypeID(void) {
1186 return __kCFBundleTypeID
;
1189 CFBundleRef
_CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL
) {
1190 CFBundleRef bundle
= NULL
;
1191 char buff
[CFMaxPathSize
];
1192 CFURLRef newURL
= NULL
;
1194 if (!CFURLGetFileSystemRepresentation(bundleURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) return NULL
;
1196 newURL
= CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault
, (uint8_t *)buff
, strlen(buff
), true);
1197 if (!newURL
) newURL
= (CFURLRef
)CFRetain(bundleURL
);
1198 bundle
= _CFBundleCopyBundleForURL(newURL
, false);
1199 if (bundle
) CFRelease(bundle
);
1204 static CFBundleRef
_CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
, Boolean alreadyLocked
, Boolean doFinalProcessing
) {
1205 allocator
= _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator
);
1206 CFBundleRef bundle
= NULL
;
1207 char buff
[CFMaxPathSize
];
1208 CFDateRef modDate
= NULL
; // do not actually fetch the modDate, since that can cause something like 7609956, unless absolutely found to be necessary in the future
1209 Boolean exists
= false;
1211 CFURLRef newURL
= NULL
;
1212 uint8_t localVersion
= 0;
1214 if (!CFURLGetFileSystemRepresentation(bundleURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) return NULL
;
1216 newURL
= CFURLCreateFromFileSystemRepresentation(allocator
, (uint8_t *)buff
, strlen(buff
), true);
1217 if (!newURL
) newURL
= (CFURLRef
)CFRetain(bundleURL
);
1218 bundle
= _CFBundleCopyBundleForURL(newURL
, alreadyLocked
);
1224 if (!_CFBundleURLLooksLikeBundleVersion(newURL
, &localVersion
)) {
1226 SInt32 res
= _CFGetPathProperties(allocator
, (char *)buff
, &exists
, &mode
, NULL
, NULL
, NULL
, NULL
);
1227 #if DEPLOYMENT_TARGET_WINDOWS
1228 if (!(res
== 0 && exists
&& ((mode
& S_IFMT
) == S_IFDIR
))) {
1229 // 2nd chance at finding a bundle path - remove the last path component (e.g., mybundle.resources) and try again
1234 CFURLRef shorterPath
= CFURLCreateCopyDeletingLastPathComponent(allocator
, newURL
);
1236 newURL
= shorterPath
;
1237 res
= _CFGetFileProperties(allocator
, newURL
, &exists
, &mode
, NULL
, NULL
, NULL
, NULL
);
1241 if (!exists
|| ((mode
& S_IFMT
) != S_IFDIR
)) {
1242 if (modDate
) CFRelease(modDate
);
1252 bundle
= (CFBundleRef
)_CFRuntimeCreateInstance(allocator
, __kCFBundleTypeID
, sizeof(struct __CFBundle
) - sizeof(CFRuntimeBase
), NULL
);
1258 bundle
->_url
= newURL
;
1260 bundle
->_modDate
= modDate
;
1261 bundle
->_version
= localVersion
;
1262 bundle
->_infoDict
= NULL
;
1263 bundle
->_localInfoDict
= NULL
;
1264 bundle
->_searchLanguages
= NULL
;
1266 #if defined(BINARY_SUPPORT_DYLD)
1267 /* We'll have to figure it out later */
1268 bundle
->_binaryType
= __CFBundleUnknownBinary
;
1269 #elif defined(BINARY_SUPPORT_DLL)
1270 /* We support DLL only */
1271 bundle
->_binaryType
= __CFBundleDLLBinary
;
1272 bundle
->_hModule
= NULL
;
1274 /* We'll have to figure it out later */
1275 bundle
->_binaryType
= __CFBundleUnknownBinary
;
1276 #endif /* BINARY_SUPPORT_DYLD */
1278 bundle
->_isLoaded
= false;
1279 bundle
->_sharesStringsFiles
= false;
1281 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1282 if (!__CFgetenv("CFBundleDisableStringsSharing") &&
1283 (strncmp(buff
, "/System/Library/Frameworks", 26) == 0) &&
1284 (strncmp(buff
+ strlen(buff
) - 10, ".framework", 10) == 0)) bundle
->_sharesStringsFiles
= true;
1285 #elif DEPLOYMENT_TARGET_WINDOWS
1287 #error Unknown or unspecified DEPLOYMENT_TARGET
1290 bundle
->_connectionCookie
= NULL
;
1291 bundle
->_handleCookie
= NULL
;
1292 bundle
->_imageCookie
= NULL
;
1293 bundle
->_moduleCookie
= NULL
;
1295 bundle
->_glueDict
= NULL
;
1297 bundle
->_resourceData
._executableLacksResourceFork
= false;
1298 bundle
->_resourceData
._infoDictionaryFromResourceFork
= false;
1299 bundle
->_resourceData
._stringTableCache
= NULL
;
1301 bundle
->_plugInData
._isPlugIn
= false;
1302 bundle
->_plugInData
._loadOnDemand
= false;
1303 bundle
->_plugInData
._isDoingDynamicRegistration
= false;
1304 bundle
->_plugInData
._instanceCount
= 0;
1305 bundle
->_plugInData
._factories
= NULL
;
1307 bundle
->_bundleLoadingLock
= CFSpinLockInit
;
1309 CFBundleGetInfoDictionary(bundle
);
1311 _CFBundleAddToTables(bundle
, alreadyLocked
);
1313 if (doFinalProcessing
) {
1314 _CFBundleCheckWorkarounds(bundle
);
1315 if (_CFBundleNeedsInitPlugIn(bundle
)) {
1316 if (alreadyLocked
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
1317 _CFBundleInitPlugIn(bundle
);
1318 if (alreadyLocked
) __CFSpinLock(&CFBundleGlobalDataLock
);
1325 CFBundleRef
CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
) {
1326 return _CFBundleCreate(allocator
, bundleURL
, false, true);
1329 CFArrayRef
CFBundleCreateBundlesFromDirectory(CFAllocatorRef alloc
, CFURLRef directoryURL
, CFStringRef bundleType
) {
1330 alloc
= _CFConvertAllocatorToNonGCRefZeroEquivalent(alloc
);
1331 CFMutableArrayRef bundles
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
);
1332 CFArrayRef URLs
= _CFContentsOfDirectory(alloc
, NULL
, NULL
, directoryURL
, bundleType
);
1334 CFIndex i
, c
= CFArrayGetCount(URLs
);
1336 CFBundleRef curBundle
;
1338 for (i
= 0; i
< c
; i
++) {
1339 curURL
= (CFURLRef
)CFArrayGetValueAtIndex(URLs
, i
);
1340 curBundle
= CFBundleCreate(alloc
, curURL
);
1341 if (curBundle
) CFArrayAppendValue(bundles
, curBundle
);
1349 CFURLRef
CFBundleCopyBundleURL(CFBundleRef bundle
) {
1350 if (bundle
->_url
) CFRetain(bundle
->_url
);
1351 return bundle
->_url
;
1354 void _CFBundleSetDefaultLocalization(CFStringRef localizationName
) {
1355 CFStringRef newLocalization
= localizationName
? (CFStringRef
)CFStringCreateCopy(kCFAllocatorSystemDefault
, localizationName
) : NULL
;
1356 if (_defaultLocalization
) CFRelease(_defaultLocalization
);
1357 _defaultLocalization
= newLocalization
;
1360 CFArrayRef
_CFBundleGetLanguageSearchList(CFBundleRef bundle
) {
1361 if (!bundle
->_searchLanguages
) {
1362 CFMutableArrayRef langs
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
1363 CFStringRef devLang
= CFBundleGetDevelopmentRegion(bundle
);
1365 #if DEPLOYMENT_TARGET_WINDOWS
1366 if (_defaultLocalization
) CFArrayAppendValue(langs
, _defaultLocalization
);
1368 _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
, bundle
->_infoDict
, langs
, devLang
);
1370 if (CFArrayGetCount(langs
) == 0) {
1371 // If the user does not prefer any of our languages, and devLang is not present, try English
1372 _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
, bundle
->_infoDict
, langs
, CFSTR("en_US"));
1374 if (CFArrayGetCount(langs
) == 0) {
1375 // if none of the preferred localizations are present, fall back on a random localization that is present
1376 CFArrayRef localizations
= CFBundleCopyBundleLocalizations(bundle
);
1377 if (localizations
) {
1378 if (CFArrayGetCount(localizations
) > 0) _CFBundleAddPreferredLprojNamesInDirectory(CFGetAllocator(bundle
), bundle
->_url
, bundle
->_version
, bundle
->_infoDict
, langs
, (CFStringRef
)CFArrayGetValueAtIndex(localizations
, 0));
1379 CFRelease(localizations
);
1383 if (devLang
&& !CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), devLang
)) {
1384 // Make sure that devLang is on the list as a fallback for individual resources that are not present
1385 CFArrayAppendValue(langs
, devLang
);
1386 } else if (!devLang
) {
1387 // Or if there is no devLang, try some variation of English that is present
1388 CFArrayRef localizations
= CFBundleCopyBundleLocalizations(bundle
);
1389 if (localizations
) {
1390 CFStringRef en_US
= CFSTR("en_US"), en
= CFSTR("en"), English
= CFSTR("English");
1391 CFRange range
= CFRangeMake(0, CFArrayGetCount(localizations
));
1392 if (CFArrayContainsValue(localizations
, range
, en
)) {
1393 if (!CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), en
)) CFArrayAppendValue(langs
, en
);
1394 } else if (CFArrayContainsValue(localizations
, range
, English
)) {
1395 if (!CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), English
)) CFArrayAppendValue(langs
, English
);
1396 } else if (CFArrayContainsValue(localizations
, range
, en_US
)) {
1397 if (!CFArrayContainsValue(langs
, CFRangeMake(0, CFArrayGetCount(langs
)), en_US
)) CFArrayAppendValue(langs
, en_US
);
1399 CFRelease(localizations
);
1402 if (CFArrayGetCount(langs
) == 0) {
1403 // Total backstop behavior to avoid having an empty array.
1404 if (_defaultLocalization
) {
1405 CFArrayAppendValue(langs
, _defaultLocalization
);
1407 CFArrayAppendValue(langs
, CFSTR("en"));
1410 if (!OSAtomicCompareAndSwapPtrBarrier(NULL
, (void *)langs
, (void * volatile *)&(bundle
->_searchLanguages
))) CFRelease(langs
);
1412 return bundle
->_searchLanguages
;
1415 CFDictionaryRef
CFBundleCopyInfoDictionaryInDirectory(CFURLRef url
) {
1416 CFDictionaryRef dict
= _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefaultGCRefZero
, url
, NULL
);
1417 if (dict
&& _CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRetain(dict
); // conditionally put on a retain for a Copy function
1421 CFDictionaryRef
CFBundleGetInfoDictionary(CFBundleRef bundle
) {
1422 if (!bundle
->_infoDict
) bundle
->_infoDict
= _CFBundleCopyInfoDictionaryInDirectoryWithVersion(kCFAllocatorSystemDefaultGCRefZero
, bundle
->_url
, bundle
->_version
);
1423 return bundle
->_infoDict
;
1426 CFDictionaryRef
_CFBundleGetLocalInfoDictionary(CFBundleRef bundle
) {
1427 return CFBundleGetLocalInfoDictionary(bundle
);
1430 CFDictionaryRef
CFBundleGetLocalInfoDictionary(CFBundleRef bundle
) {
1431 static CFSpinLock_t CFBundleLocalInfoLock
= CFSpinLockInit
;
1432 CFDictionaryRef localInfoDict
= bundle
->_localInfoDict
;
1433 if (!localInfoDict
) {
1434 CFURLRef url
= CFBundleCopyResourceURL(bundle
, _CFBundleLocalInfoName
, _CFBundleStringTableType
, NULL
);
1438 CFStringRef errStr
= NULL
;
1440 if (CFURLCreateDataAndPropertiesFromResource(kCFAllocatorSystemDefault
, url
, &data
, NULL
, NULL
, &errCode
)) {
1441 localInfoDict
= (CFDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefaultGCRefZero
, data
, kCFPropertyListMutableContainers
, &errStr
);
1442 if (errStr
) CFRelease(errStr
);
1443 if (localInfoDict
&& CFDictionaryGetTypeID() != CFGetTypeID(localInfoDict
)) {
1444 if (!_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(localInfoDict
);
1445 localInfoDict
= NULL
;
1451 if (localInfoDict
) _processInfoDictionary((CFMutableDictionaryRef
)localInfoDict
, _CFGetPlatformName(), _CFGetProductName());
1452 __CFSpinLock(&CFBundleLocalInfoLock
);
1453 if (!bundle
->_localInfoDict
) {
1454 bundle
->_localInfoDict
= localInfoDict
;
1456 if (localInfoDict
&& !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(localInfoDict
);
1457 localInfoDict
= bundle
->_localInfoDict
;
1459 __CFSpinUnlock(&CFBundleLocalInfoLock
);
1461 return localInfoDict
;
1464 CFPropertyListRef
_CFBundleGetValueForInfoKey(CFBundleRef bundle
, CFStringRef key
) {
1465 return (CFPropertyListRef
)CFBundleGetValueForInfoDictionaryKey(bundle
, key
);
1468 CFTypeRef
CFBundleGetValueForInfoDictionaryKey(CFBundleRef bundle
, CFStringRef key
) {
1469 // Look in InfoPlist.strings first. Then look in Info.plist
1470 CFTypeRef result
= NULL
;
1471 if (bundle
&& key
) {
1472 CFDictionaryRef dict
= CFBundleGetLocalInfoDictionary(bundle
);
1473 if (dict
) result
= CFDictionaryGetValue(dict
, key
);
1475 dict
= CFBundleGetInfoDictionary(bundle
);
1476 if (dict
) result
= CFDictionaryGetValue(dict
, key
);
1482 CFStringRef
CFBundleGetIdentifier(CFBundleRef bundle
) {
1483 CFStringRef bundleID
= NULL
;
1484 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1485 if (infoDict
) bundleID
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleIdentifierKey
);
1489 #define DEVELOPMENT_STAGE 0x20
1490 #define ALPHA_STAGE 0x40
1491 #define BETA_STAGE 0x60
1492 #define RELEASE_STAGE 0x80
1494 #define MAX_VERS_LEN 10
1496 CF_INLINE Boolean
_isDigit(UniChar aChar
) {return ((aChar
>= (UniChar
)'0' && aChar
<= (UniChar
)'9') ? true : false);}
1498 __private_extern__ CFStringRef
_CFCreateStringFromVersionNumber(CFAllocatorRef alloc
, UInt32 vers
) {
1499 CFStringRef result
= NULL
;
1500 uint8_t major1
, major2
, minor1
, minor2
, stage
, build
;
1502 major1
= (vers
& 0xF0000000) >> 28;
1503 major2
= (vers
& 0x0F000000) >> 24;
1504 minor1
= (vers
& 0x00F00000) >> 20;
1505 minor2
= (vers
& 0x000F0000) >> 16;
1506 stage
= (vers
& 0x0000FF00) >> 8;
1507 build
= (vers
& 0x000000FF);
1509 if (stage
== RELEASE_STAGE
) {
1511 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d%d.%d.%d"), major1
, major2
, minor1
, minor2
);
1513 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d.%d.%d"), major2
, minor1
, minor2
);
1517 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d%d.%d.%d%C%d"), major1
, major2
, minor1
, minor2
, ((stage
== DEVELOPMENT_STAGE
) ? 'd' : ((stage
== ALPHA_STAGE
) ? 'a' : 'b')), build
);
1519 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d.%d.%d%C%d"), major2
, minor1
, minor2
, ((stage
== DEVELOPMENT_STAGE
) ? 'd' : ((stage
== ALPHA_STAGE
) ? 'a' : 'b')), build
);
1525 __private_extern__ UInt32
_CFVersionNumberFromString(CFStringRef versStr
) {
1526 // Parse version number from string.
1527 // String can begin with "." for major version number 0. String can end at any point, but elements within the string cannot be skipped.
1528 UInt32 major1
= 0, major2
= 0, minor1
= 0, minor2
= 0, stage
= RELEASE_STAGE
, build
= 0;
1529 UniChar versChars
[MAX_VERS_LEN
];
1530 UniChar
*chars
= NULL
;
1533 Boolean digitsDone
= false;
1535 if (!versStr
) return 0;
1536 len
= CFStringGetLength(versStr
);
1537 if (len
<= 0 || len
> MAX_VERS_LEN
) return 0;
1539 CFStringGetCharacters(versStr
, CFRangeMake(0, len
), versChars
);
1542 // Get major version number.
1543 major1
= major2
= 0;
1544 if (_isDigit(*chars
)) {
1545 major2
= *chars
- (UniChar
)'0';
1549 if (_isDigit(*chars
)) {
1551 major2
= *chars
- (UniChar
)'0';
1555 if (*chars
== (UniChar
)'.') {
1562 } else if (*chars
== (UniChar
)'.') {
1569 } else if (*chars
== (UniChar
)'.') {
1576 // Now major1 and major2 contain first and second digit of the major version number as ints.
1577 // Now either len is 0 or chars points at the first char beyond the first decimal point.
1579 // Get the first minor version number.
1580 if (len
> 0 && !digitsDone
) {
1581 if (_isDigit(*chars
)) {
1582 minor1
= *chars
- (UniChar
)'0';
1586 if (*chars
== (UniChar
)'.') {
1598 // Now minor1 contains the first minor version number as an int.
1599 // Now either len is 0 or chars points at the first char beyond the second decimal point.
1601 // Get the second minor version number.
1602 if (len
> 0 && !digitsDone
) {
1603 if (_isDigit(*chars
)) {
1604 minor2
= *chars
- (UniChar
)'0';
1612 // Now minor2 contains the second minor version number as an int.
1613 // Now either len is 0 or chars points at the build stage letter.
1615 // Get the build stage letter. We must find 'd', 'a', 'b', or 'f' next, if there is anything next.
1617 if (*chars
== (UniChar
)'d') {
1618 stage
= DEVELOPMENT_STAGE
;
1619 } else if (*chars
== (UniChar
)'a') {
1620 stage
= ALPHA_STAGE
;
1621 } else if (*chars
== (UniChar
)'b') {
1623 } else if (*chars
== (UniChar
)'f') {
1624 stage
= RELEASE_STAGE
;
1632 // Now stage contains the release stage.
1633 // Now either len is 0 or chars points at the build number.
1635 // Get the first digit of the build number.
1637 if (_isDigit(*chars
)) {
1638 build
= *chars
- (UniChar
)'0';
1645 // Get the second digit of the build number.
1647 if (_isDigit(*chars
)) {
1649 build
+= *chars
- (UniChar
)'0';
1656 // Get the third digit of the build number.
1658 if (_isDigit(*chars
)) {
1660 build
+= *chars
- (UniChar
)'0';
1668 // Range check the build number and make sure we exhausted the string.
1669 if (build
> 0xFF || len
> 0) return 0;
1672 theVers
= major1
<< 28;
1673 theVers
+= major2
<< 24;
1674 theVers
+= minor1
<< 20;
1675 theVers
+= minor2
<< 16;
1676 theVers
+= stage
<< 8;
1682 UInt32
CFBundleGetVersionNumber(CFBundleRef bundle
) {
1683 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1684 CFTypeRef unknownVersionValue
= CFDictionaryGetValue(infoDict
, _kCFBundleNumericVersionKey
);
1685 CFNumberRef versNum
;
1688 if (!unknownVersionValue
) unknownVersionValue
= CFDictionaryGetValue(infoDict
, kCFBundleVersionKey
);
1689 if (unknownVersionValue
) {
1690 if (CFGetTypeID(unknownVersionValue
) == CFStringGetTypeID()) {
1691 // Convert a string version number into a numeric one.
1692 vers
= _CFVersionNumberFromString((CFStringRef
)unknownVersionValue
);
1694 versNum
= CFNumberCreate(CFGetAllocator(bundle
), kCFNumberSInt32Type
, &vers
);
1695 CFDictionarySetValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleNumericVersionKey
, versNum
);
1697 } else if (CFGetTypeID(unknownVersionValue
) == CFNumberGetTypeID()) {
1698 CFNumberGetValue((CFNumberRef
)unknownVersionValue
, kCFNumberSInt32Type
, &vers
);
1700 CFDictionaryRemoveValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleNumericVersionKey
);
1706 CFStringRef
CFBundleGetDevelopmentRegion(CFBundleRef bundle
) {
1707 CFStringRef devLang
= NULL
;
1708 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1710 devLang
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleDevelopmentRegionKey
);
1711 if (devLang
&& (CFGetTypeID(devLang
) != CFStringGetTypeID() || CFStringGetLength(devLang
) == 0)) {
1713 CFDictionaryRemoveValue((CFMutableDictionaryRef
)infoDict
, kCFBundleDevelopmentRegionKey
);
1720 Boolean
_CFBundleGetHasChanged(CFBundleRef bundle
) {
1722 Boolean result
= false;
1723 Boolean exists
= false;
1726 if (_CFGetFileProperties(CFGetAllocator(bundle
), bundle
->_url
, &exists
, &mode
, NULL
, &modDate
, NULL
, NULL
) == 0) {
1727 // If the bundle no longer exists or is not a folder, it must have "changed"
1728 if (!exists
|| ((mode
& S_IFMT
) != S_IFDIR
)) result
= true;
1730 // Something is wrong. The stat failed.
1733 if (bundle
->_modDate
&& !CFEqual(bundle
->_modDate
, modDate
)) {
1734 // mod date is different from when we created.
1741 void _CFBundleSetStringsFilesShared(CFBundleRef bundle
, Boolean flag
) {
1742 bundle
->_sharesStringsFiles
= flag
;
1745 Boolean
_CFBundleGetStringsFilesShared(CFBundleRef bundle
) {
1746 return bundle
->_sharesStringsFiles
;
1749 static Boolean
_urlExists(CFURLRef url
) {
1751 return url
&& (0 == _CFGetFileProperties(kCFAllocatorSystemDefault
, url
, &exists
, NULL
, NULL
, NULL
, NULL
, NULL
)) && exists
;
1754 // This is here because on iPhoneOS with the dyld shared cache, we remove binaries from their
1755 // original locations on disk, so checking whether a binary's path exists is no longer sufficient.
1756 // For performance reasons, we only call dlopen_preflight() after we've verified that the binary
1757 // does not exist at its original path with _urlExists().
1758 // See <rdar://problem/6956670>
1759 static Boolean
_binaryLoadable(CFURLRef url
) {
1760 Boolean loadable
= _urlExists(url
);
1761 #if DEPLOYMENT_TARGET_EMBEDDED
1763 uint8_t path
[PATH_MAX
];
1764 if (url
&& CFURLGetFileSystemRepresentation(url
, true, path
, sizeof(path
))) {
1765 loadable
= dlopen_preflight((char *)path
);
1772 __private_extern__ CFURLRef
_CFBundleCopySupportFilesDirectoryURLInDirectory(CFURLRef bundleURL
, uint8_t version
) {
1773 CFURLRef result
= NULL
;
1776 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleSupportFilesURLFromBase1
, bundleURL
);
1777 } else if (2 == version
) {
1778 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleSupportFilesURLFromBase2
, bundleURL
);
1780 result
= (CFURLRef
)CFRetain(bundleURL
);
1786 CF_EXPORT CFURLRef
CFBundleCopySupportFilesDirectoryURL(CFBundleRef bundle
) {
1787 return _CFBundleCopySupportFilesDirectoryURLInDirectory(bundle
->_url
, bundle
->_version
);
1790 __private_extern__ CFURLRef
_CFBundleCopyResourcesDirectoryURLInDirectory(CFURLRef bundleURL
, uint8_t version
) {
1791 CFURLRef result
= NULL
;
1794 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleResourcesURLFromBase0
, bundleURL
);
1795 } else if (1 == version
) {
1796 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleResourcesURLFromBase1
, bundleURL
);
1797 } else if (2 == version
) {
1798 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleResourcesURLFromBase2
, bundleURL
);
1800 result
= (CFURLRef
)CFRetain(bundleURL
);
1806 CFURLRef
CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle
) {
1807 return _CFBundleCopyResourcesDirectoryURLInDirectory(bundle
->_url
, bundle
->_version
);
1810 __private_extern__ CFURLRef
_CFBundleCopyAppStoreReceiptURLInDirectory(CFURLRef bundleURL
, uint8_t version
) {
1811 CFURLRef result
= NULL
;
1814 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleAppStoreReceiptURLFromBase0
, bundleURL
);
1815 } else if (1 == version
) {
1816 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleAppStoreReceiptURLFromBase1
, bundleURL
);
1817 } else if (2 == version
) {
1818 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleAppStoreReceiptURLFromBase2
, bundleURL
);
1824 CFURLRef
_CFBundleCopyAppStoreReceiptURL(CFBundleRef bundle
) {
1825 return _CFBundleCopyAppStoreReceiptURLInDirectory(bundle
->_url
, bundle
->_version
);
1828 static CFURLRef
_CFBundleCopyExecutableURLRaw(CFURLRef urlPath
, CFStringRef exeName
) {
1829 // 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.
1830 CFURLRef executableURL
= NULL
;
1831 if (!urlPath
|| !exeName
) return NULL
;
1833 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1834 const uint8_t *image_suffix
= (uint8_t *)__CFgetenv("DYLD_IMAGE_SUFFIX");
1836 CFStringRef newExeName
, imageSuffix
;
1837 imageSuffix
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, (char *)image_suffix
, kCFStringEncodingUTF8
);
1838 if (CFStringHasSuffix(exeName
, CFSTR(".dylib"))) {
1839 CFStringRef bareExeName
= CFStringCreateWithSubstring(kCFAllocatorSystemDefault
, exeName
, CFRangeMake(0, CFStringGetLength(exeName
)-6));
1840 newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@.dylib"), exeName
, imageSuffix
);
1841 CFRelease(bareExeName
);
1843 newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@"), exeName
, imageSuffix
);
1845 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, newExeName
, kCFURLPOSIXPathStyle
, false, urlPath
);
1846 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1847 CFRelease(executableURL
);
1848 executableURL
= NULL
;
1850 CFRelease(newExeName
);
1851 CFRelease(imageSuffix
);
1853 if (!executableURL
) {
1854 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, exeName
, kCFURLPOSIXPathStyle
, false, urlPath
);
1855 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1856 CFRelease(executableURL
);
1857 executableURL
= NULL
;
1860 #elif DEPLOYMENT_TARGET_WINDOWS
1861 if (!executableURL
) {
1862 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, exeName
, kCFURLWindowsPathStyle
, false, urlPath
);
1863 if (executableURL
&& !_urlExists(executableURL
)) {
1864 CFRelease(executableURL
);
1865 executableURL
= NULL
;
1868 if (!executableURL
) {
1869 if (!CFStringFindWithOptions(exeName
, CFSTR(".dll"), CFRangeMake(0, CFStringGetLength(exeName
)), kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
)) {
1871 CFStringRef extension
= CFSTR("_debug.dll");
1873 CFStringRef extension
= CFSTR(".dll");
1875 CFStringRef newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@"), exeName
, extension
);
1876 executableURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, newExeName
, urlPath
);
1877 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1878 CFRelease(executableURL
);
1879 executableURL
= NULL
;
1881 CFRelease(newExeName
);
1884 if (!executableURL
) {
1885 if (!CFStringFindWithOptions(exeName
, CFSTR(".exe"), CFRangeMake(0, CFStringGetLength(exeName
)), kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
)) {
1887 CFStringRef extension
= CFSTR("_debug.exe");
1889 CFStringRef extension
= CFSTR(".exe");
1891 CFStringRef newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@"), exeName
, extension
);
1892 executableURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, newExeName
, urlPath
);
1893 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1894 CFRelease(executableURL
);
1895 executableURL
= NULL
;
1897 CFRelease(newExeName
);
1901 #error Unknown or unspecified DEPLOYMENT_TARGET
1903 return executableURL
;
1906 static CFStringRef
_CFBundleCopyExecutableName(CFBundleRef bundle
, CFURLRef url
, CFDictionaryRef infoDict
) {
1907 CFStringRef executableName
= NULL
;
1909 if (!infoDict
&& bundle
) infoDict
= CFBundleGetInfoDictionary(bundle
);
1910 if (!url
&& bundle
) url
= bundle
->_url
;
1913 // Figure out the name of the executable.
1914 // First try for the new key in the plist.
1915 executableName
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleExecutableKey
);
1916 // Second try for the old key in the plist.
1917 if (!executableName
) executableName
= (CFStringRef
)CFDictionaryGetValue(infoDict
, _kCFBundleOldExecutableKey
);
1918 if (executableName
&& CFGetTypeID(executableName
) == CFStringGetTypeID() && CFStringGetLength(executableName
) > 0) {
1919 CFRetain(executableName
);
1921 executableName
= NULL
;
1924 if (!executableName
&& url
) {
1925 // Third, take the name of the bundle itself (with path extension stripped)
1926 CFURLRef absoluteURL
= CFURLCopyAbsoluteURL(url
);
1927 CFStringRef bundlePath
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
);
1928 CFRelease(absoluteURL
);
1930 UniChar buff
[CFMaxPathSize
];
1931 CFIndex len
= CFStringGetLength(bundlePath
);
1932 CFIndex startOfBundleName
, endOfBundleName
;
1934 if (len
> CFMaxPathSize
) len
= CFMaxPathSize
;
1935 CFStringGetCharacters(bundlePath
, CFRangeMake(0, len
), buff
);
1936 startOfBundleName
= _CFStartOfLastPathComponent(buff
, len
);
1937 endOfBundleName
= _CFLengthAfterDeletingPathExtension(buff
, len
);
1939 if (startOfBundleName
<= len
&& endOfBundleName
<= len
&& startOfBundleName
< endOfBundleName
) executableName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfBundleName
]), endOfBundleName
- startOfBundleName
);
1940 CFRelease(bundlePath
);
1944 return executableName
;
1947 __private_extern__ CFURLRef
_CFBundleCopyResourceForkURLMayBeLocal(CFBundleRef bundle
, Boolean mayBeLocal
) {
1948 CFStringRef executableName
= _CFBundleCopyExecutableName(bundle
, NULL
, NULL
);
1949 CFURLRef resourceForkURL
= NULL
;
1950 if (executableName
) {
1952 resourceForkURL
= CFBundleCopyResourceURL(bundle
, executableName
, CFSTR("rsrc"), NULL
);
1954 resourceForkURL
= CFBundleCopyResourceURLForLocalization(bundle
, executableName
, CFSTR("rsrc"), NULL
, NULL
);
1956 CFRelease(executableName
);
1959 return resourceForkURL
;
1962 CFURLRef
_CFBundleCopyResourceForkURL(CFBundleRef bundle
) {
1963 return _CFBundleCopyResourceForkURLMayBeLocal(bundle
, true);
1966 static CFURLRef
_CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle
, CFURLRef url
, CFStringRef executableName
, Boolean ignoreCache
, Boolean useOtherPlatform
) {
1967 uint8_t version
= 0;
1968 CFDictionaryRef infoDict
= NULL
;
1969 CFStringRef executablePath
= NULL
;
1970 CFURLRef executableURL
= NULL
;
1971 Boolean foundIt
= false;
1972 Boolean lookupMainExe
= (executableName
? false : true);
1973 static CFSpinLock_t CFBundleExecutablePathLock
= CFSpinLockInit
;
1976 infoDict
= CFBundleGetInfoDictionary(bundle
);
1977 version
= bundle
->_version
;
1979 infoDict
= _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefaultGCRefZero
, url
, &version
);
1982 // If we have a bundle instance and an info dict, see if we have already cached the path
1983 if (lookupMainExe
&& !ignoreCache
&& !useOtherPlatform
&& bundle
&& infoDict
) {
1984 __CFSpinLock(&CFBundleExecutablePathLock
);
1985 executablePath
= (CFStringRef
)CFDictionaryGetValue(infoDict
, _kCFBundleExecutablePathKey
);
1986 if (executablePath
) CFRetain(executablePath
);
1987 __CFSpinUnlock(&CFBundleExecutablePathLock
);
1988 if (executablePath
) {
1989 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
1990 executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, executablePath
, kCFURLPOSIXPathStyle
, false);
1991 #elif DEPLOYMENT_TARGET_WINDOWS
1992 executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, executablePath
, kCFURLWindowsPathStyle
, false);
1994 #error Unknown or unspecified DEPLOYMENT_TARGET
1996 if (executableURL
) {
1999 __CFSpinLock(&CFBundleExecutablePathLock
);
2000 CFDictionaryRemoveValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleExecutablePathKey
);
2001 __CFSpinUnlock(&CFBundleExecutablePathLock
);
2003 CFRelease(executablePath
);
2008 if (lookupMainExe
) executableName
= _CFBundleCopyExecutableName(bundle
, url
, infoDict
);
2009 if (executableName
) {
2010 #if DEPLOYMENT_TARGET_EMBEDDED
2011 Boolean doExecSearch
= false;
2013 Boolean doExecSearch
= true;
2015 // Now, look for the executable inside the bundle.
2016 if (doExecSearch
&& 0 != version
) {
2018 CFURLRef exeSubdirURL
;
2021 exeDirURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleExecutablesURLFromBase1
, url
);
2022 } else if (2 == version
) {
2023 exeDirURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleExecutablesURLFromBase2
, url
);
2025 #if DEPLOYMENT_TARGET_WINDOWS
2026 // On Windows, if the bundle URL is foo.resources, then the executable is at the same level as the .resources directory
2027 CFStringRef extension
= CFURLCopyPathExtension(url
);
2028 if (extension
&& CFEqual(extension
, _CFBundleWindowsResourceDirectoryExtension
)) {
2029 exeDirURL
= CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault
, url
);
2031 exeDirURL
= (CFURLRef
)CFRetain(url
);
2033 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
2034 exeDirURL
= (CFURLRef
)CFRetain(url
);
2036 #error Unknown or unspecified DEPLOYMENT_TARGET
2039 CFStringRef platformSubDir
= useOtherPlatform
? _CFBundleGetOtherPlatformExecutablesSubdirectoryName() : _CFBundleGetPlatformExecutablesSubdirectoryName();
2040 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
2041 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
2042 if (!executableURL
) {
2043 CFRelease(exeSubdirURL
);
2044 platformSubDir
= useOtherPlatform
? _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetAlternatePlatformExecutablesSubdirectoryName();
2045 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
2046 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
2048 if (!executableURL
) {
2049 CFRelease(exeSubdirURL
);
2050 platformSubDir
= useOtherPlatform
? _CFBundleGetPlatformExecutablesSubdirectoryName() : _CFBundleGetOtherPlatformExecutablesSubdirectoryName();
2051 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
2052 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
2054 if (!executableURL
) {
2055 CFRelease(exeSubdirURL
);
2056 platformSubDir
= useOtherPlatform
? _CFBundleGetAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName();
2057 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
2058 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
2060 if (!executableURL
) executableURL
= _CFBundleCopyExecutableURLRaw(exeDirURL
, executableName
);
2061 CFRelease(exeDirURL
);
2062 CFRelease(exeSubdirURL
);
2065 // If this was an old bundle, or we did not find the executable in the Executables subdirectory, look directly in the bundle wrapper.
2066 if (!executableURL
) executableURL
= _CFBundleCopyExecutableURLRaw(url
, executableName
);
2068 #if DEPLOYMENT_TARGET_WINDOWS
2069 // Windows only: If we still haven't found the exe, look in the Executables folder.
2070 // But only for the main bundle exe
2071 if (lookupMainExe
&& !executableURL
) {
2072 CFURLRef exeDirURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, CFSTR("../../Executables"), url
);
2073 executableURL
= _CFBundleCopyExecutableURLRaw(exeDirURL
, executableName
);
2074 CFRelease(exeDirURL
);
2076 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
2078 #error Unknown or unspecified DEPLOYMENT_TARGET
2081 if (lookupMainExe
&& !ignoreCache
&& !useOtherPlatform
&& bundle
&& infoDict
&& executableURL
) {
2082 // We found it. Cache the path.
2083 CFURLRef absURL
= CFURLCopyAbsoluteURL(executableURL
);
2084 #if DEPLOYMENT_TARGET_WINDOWS
2085 executablePath
= CFURLCopyFileSystemPath(absURL
, kCFURLWindowsPathStyle
);
2086 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
2087 executablePath
= CFURLCopyFileSystemPath(absURL
, kCFURLPOSIXPathStyle
);
2089 #error Unknown or unspecified DEPLOYMENT_TARGET
2092 __CFSpinLock(&CFBundleExecutablePathLock
);
2093 CFDictionarySetValue((CFMutableDictionaryRef
)infoDict
, _kCFBundleExecutablePathKey
, executablePath
);
2094 __CFSpinUnlock(&CFBundleExecutablePathLock
);
2095 CFRelease(executablePath
);
2097 if (lookupMainExe
&& !useOtherPlatform
&& bundle
&& !executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
2098 if (lookupMainExe
) CFRelease(executableName
);
2101 if (!bundle
&& infoDict
&& !_CFAllocatorIsGCRefZero(kCFAllocatorSystemDefaultGCRefZero
)) CFRelease(infoDict
);
2102 return executableURL
;
2105 CFURLRef
_CFBundleCopyExecutableURLInDirectory(CFURLRef url
) {
2106 return _CFBundleCopyExecutableURLInDirectory2(NULL
, url
, NULL
, true, false);
2109 CFURLRef
_CFBundleCopyOtherExecutableURLInDirectory(CFURLRef url
) {
2110 return _CFBundleCopyExecutableURLInDirectory2(NULL
, url
, NULL
, true, true);
2113 CFURLRef
CFBundleCopyExecutableURL(CFBundleRef bundle
) {
2114 return _CFBundleCopyExecutableURLInDirectory2(bundle
, bundle
->_url
, NULL
, false, false);
2117 static CFURLRef
_CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle
) {
2118 return _CFBundleCopyExecutableURLInDirectory2(bundle
, bundle
->_url
, NULL
, true, false);
2121 CFURLRef
CFBundleCopyAuxiliaryExecutableURL(CFBundleRef bundle
, CFStringRef executableName
) {
2122 return _CFBundleCopyExecutableURLInDirectory2(bundle
, bundle
->_url
, executableName
, true, false);
2125 Boolean
CFBundleIsExecutableLoaded(CFBundleRef bundle
) {
2126 return bundle
->_isLoaded
;
2129 CFBundleExecutableType
CFBundleGetExecutableType(CFBundleRef bundle
) {
2130 CFBundleExecutableType result
= kCFBundleOtherExecutableType
;
2131 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
2133 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
2134 #if defined(BINARY_SUPPORT_DYLD)
2135 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
2136 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
2137 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
2139 #endif /* BINARY_SUPPORT_DYLD */
2140 if (executableURL
) CFRelease(executableURL
);
2142 if (bundle
->_binaryType
== __CFBundleCFMBinary
) {
2143 result
= kCFBundlePEFExecutableType
;
2144 } else if (bundle
->_binaryType
== __CFBundleDYLDExecutableBinary
|| bundle
->_binaryType
== __CFBundleDYLDBundleBinary
|| bundle
->_binaryType
== __CFBundleDYLDFrameworkBinary
) {
2145 result
= kCFBundleMachOExecutableType
;
2146 } else if (bundle
->_binaryType
== __CFBundleDLLBinary
) {
2147 result
= kCFBundleDLLExecutableType
;
2148 } else if (bundle
->_binaryType
== __CFBundleELFBinary
) {
2149 result
= kCFBundleELFExecutableType
;
2154 static SInt32
_CFBundleCurrentArchitecture(void) {
2156 #if defined(__ppc__)
2157 arch
= kCFBundleExecutableArchitecturePPC
;
2158 #elif defined(__ppc64__)
2159 arch
= kCFBundleExecutableArchitecturePPC64
;
2160 #elif defined(__i386__)
2161 arch
= kCFBundleExecutableArchitectureI386
;
2162 #elif defined(__x86_64__)
2163 arch
= kCFBundleExecutableArchitectureX86_64
;
2164 #elif defined(BINARY_SUPPORT_DYLD)
2165 const NXArchInfo
*archInfo
= NXGetLocalArchInfo();
2166 if (archInfo
) arch
= archInfo
->cputype
;
2171 #define UNKNOWN_FILETYPE 0x0
2172 #define PEF_FILETYPE 0x1000
2173 #define PEF_MAGIC 0x4a6f7921
2174 #define PEF_CIGAM 0x21796f4a
2175 #define TEXT_SEGMENT "__TEXT"
2176 #define PLIST_SECTION "__info_plist"
2177 #define OBJC_SEGMENT "__OBJC"
2178 #define IMAGE_INFO_SECTION "__image_info"
2179 #define OBJC_SEGMENT_64 "__DATA"
2180 #define IMAGE_INFO_SECTION_64 "__objc_imageinfo"
2181 #define LIB_X11 "/usr/X11R6/lib/libX"
2183 #define XLS_NAME "Book"
2184 #define XLS_NAME2 "Workbook"
2185 #define DOC_NAME "WordDocument"
2186 #define PPT_NAME "PowerPoint Document"
2188 #define ustrncmp(x, y, z) strncmp((char *)(x), (char *)(y), (z))
2189 #define ustrncasecmp(x, y, z) strncasecmp_l((char *)(x), (char *)(y), (z), NULL)
2191 static const uint32_t __CFBundleMagicNumbersArray
[] = {
2192 0xcafebabe, 0xbebafeca, 0xfeedface, 0xcefaedfe, 0xfeedfacf, 0xcffaedfe, 0x4a6f7921, 0x21796f4a,
2193 0x7f454c46, 0xffd8ffe0, 0x4d4d002a, 0x49492a00, 0x47494638, 0x89504e47, 0x69636e73, 0x00000100,
2194 0x7b5c7274, 0x25504446, 0x2e7261fd, 0x2e524d46, 0x2e736e64, 0x2e736400, 0x464f524d, 0x52494646,
2195 0x38425053, 0x000001b3, 0x000001ba, 0x4d546864, 0x504b0304, 0x53495421, 0x53495432, 0x53495435,
2196 0x53495444, 0x53747566, 0x30373037, 0x3c212d2d, 0x25215053, 0xd0cf11e0, 0x62656769, 0x3d796265,
2197 0x6b6f6c79, 0x3026b275, 0x0000000c, 0xfe370023, 0x09020600, 0x09040600, 0x4f676753, 0x664c6143,
2198 0x00010000, 0x74727565, 0x4f54544f, 0x41433130, 0xc809fe02, 0x0809fe02, 0x2356524d, 0x67696d70,
2199 0x3c435058, 0x28445746, 0x424f4d53, 0x49544f4c, 0x72746664, 0x63616666, 0x802a5fd7, 0x762f3101
2202 // string, with groups of 5 characters being 1 element in the array
2203 static const char * __CFBundleExtensionsArray
=
2204 "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "pef\0\0" "pef\0\0"
2205 "elf\0\0" "jpeg\0" "tiff\0" "tiff\0" "gif\0\0" "png\0\0" "icns\0" "ico\0\0"
2206 "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"
2207 "psd\0\0" "mpeg\0" "mpeg\0" "mid\0\0" "zip\0\0" "sit\0\0" "sit\0\0" "sit\0\0"
2208 "sit\0\0" "sit\0\0" "cpio\0" "html\0" "ps\0\0\0""ole\0\0" "uu\0\0\0""ync\0\0"
2209 "dmg\0\0" "wmv\0\0" "jp2\0\0" "doc\0\0" "xls\0\0" "xls\0\0" "ogg\0\0" "flac\0"
2210 "ttf\0\0" "ttf\0\0" "otf\0\0" "dwg\0\0" "dgn\0\0" "dgn\0\0" "wrl\0\0" "xcf\0\0"
2211 "cpx\0\0" "dwf\0\0" "bom\0\0" "lit\0\0" "rtfd\0" "caf\0\0" "cin\0\0" "exr\0\0";
2213 static const char * __CFBundleOOExtensionsArray
= "sxc\0\0" "sxd\0\0" "sxg\0\0" "sxi\0\0" "sxm\0\0" "sxw\0\0";
2214 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";
2216 #define EXTENSION_LENGTH 5
2217 #define NUM_EXTENSIONS 64
2218 #define MAGIC_BYTES_TO_READ 512
2219 #define DMG_BYTES_TO_READ 512
2220 #define ZIP_BYTES_TO_READ 1024
2221 #define OLE_BYTES_TO_READ 512
2222 #define X11_BYTES_TO_READ 4096
2223 #define IMAGE_INFO_BYTES_TO_READ 4096
2225 #if defined(BINARY_SUPPORT_DYLD)
2227 CF_INLINE
uint32_t _CFBundleSwapInt32Conditional(uint32_t arg
, Boolean swap
) {return swap
? CFSwapInt32(arg
) : arg
;}
2228 CF_INLINE
uint32_t _CFBundleSwapInt64Conditional(uint64_t arg
, Boolean swap
) {return swap
? CFSwapInt64(arg
) : arg
;}
2230 // returns zero-ref dictionary under GC
2231 static CFMutableDictionaryRef
_CFBundleGrokInfoDictFromData(const char *bytes
, uint32_t length
) {
2232 CFMutableDictionaryRef result
= NULL
;
2233 CFDataRef infoData
= NULL
;
2234 if (bytes
&& 0 < length
) {
2235 infoData
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, (uint8_t *)bytes
, length
, kCFAllocatorNull
);
2237 result
= (CFMutableDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefaultGCRefZero
, infoData
, kCFPropertyListMutableContainers
, NULL
);
2238 if (result
&& CFDictionaryGetTypeID() != CFGetTypeID(result
)) {
2242 CFRelease(infoData
);
2244 if (!result
) result
= CFDictionaryCreateMutable(kCFAllocatorSystemDefaultGCRefZero
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
2246 if (result
) _processInfoDictionary((CFMutableDictionaryRef
)result
, _CFGetPlatformName(), _CFGetProductName());
2250 static char *_CFBundleGetSectData(const char *segname
, const char *sectname
, unsigned long *size
) {
2251 char *retval
= NULL
;
2252 unsigned long localSize
= 0;
2253 uint32_t i
, numImages
= _dyld_image_count();
2254 const void *mhp
= (const void *)_NSGetMachExecuteHeader();
2256 for (i
= 0; i
< numImages
; i
++) {
2257 if (mhp
== (void *)_dyld_get_image_header(i
)) {
2259 const struct section_64
*sp
= getsectbynamefromheader_64((const struct mach_header_64
*)mhp
, segname
, sectname
);
2261 retval
= (char *)(sp
->addr
+ _dyld_get_image_vmaddr_slide(i
));
2262 localSize
= (unsigned long)sp
->size
;
2264 #else /* __LP64__ */
2265 const struct section
*sp
= getsectbynamefromheader((const struct mach_header
*)mhp
, segname
, sectname
);
2267 retval
= (char *)(sp
->addr
+ _dyld_get_image_vmaddr_slide(i
));
2268 localSize
= (unsigned long)sp
->size
;
2270 #endif /* __LP64__ */
2274 if (size
) *size
= localSize
;
2278 // returns zero-ref dictionary under GC
2279 static CFMutableDictionaryRef
_CFBundleGrokInfoDictFromMainExecutable() {
2281 unsigned long length
= 0;
2282 if (getsegbyname(TEXT_SEGMENT
)) bytes
= _CFBundleGetSectData(TEXT_SEGMENT
, PLIST_SECTION
, &length
);
2283 return _CFBundleGrokInfoDictFromData(bytes
, length
);
2286 static Boolean
_CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion
, uint32_t *objcFlags
) {
2287 Boolean retval
= false;
2288 uint32_t localVersion
= 0, localFlags
= 0;
2290 unsigned long length
= 0;
2292 if (getsegbyname(OBJC_SEGMENT_64
)) bytes
= _CFBundleGetSectData(OBJC_SEGMENT_64
, IMAGE_INFO_SECTION_64
, &length
);
2293 #else /* __LP64__ */
2294 if (getsegbyname(OBJC_SEGMENT
)) bytes
= _CFBundleGetSectData(OBJC_SEGMENT
, IMAGE_INFO_SECTION
, &length
);
2295 #endif /* __LP64__ */
2296 if (bytes
&& length
>= 8) {
2297 localVersion
= *(uint32_t *)bytes
;
2298 localFlags
= *(uint32_t *)(bytes
+ 4);
2301 if (objcVersion
) *objcVersion
= localVersion
;
2302 if (objcFlags
) *objcFlags
= localFlags
;
2306 static Boolean
_CFBundleGrokX11FromFile(int fd
, const void *bytes
, CFIndex length
, uint32_t offset
, Boolean swapped
, Boolean sixtyFour
) {
2307 static const char libX11name
[] = LIB_X11
;
2308 char *buffer
= NULL
;
2309 const char *loc
= NULL
;
2311 Boolean result
= false;
2313 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
2314 buffer
= malloc(X11_BYTES_TO_READ
);
2315 if (buffer
&& read(fd
, buffer
, X11_BYTES_TO_READ
) >= X11_BYTES_TO_READ
) loc
= buffer
;
2316 } else if (bytes
&& length
>= offset
+ X11_BYTES_TO_READ
) {
2317 loc
= bytes
+ offset
;
2321 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->ncmds
, swapped
);
2322 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->sizeofcmds
, swapped
);
2323 const char *startofcmds
= loc
+ sizeof(struct mach_header_64
);
2324 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2325 struct dylib_command
*dlp
= (struct dylib_command
*)startofcmds
;
2326 if (endofcmds
> loc
+ X11_BYTES_TO_READ
) endofcmds
= loc
+ X11_BYTES_TO_READ
;
2327 for (i
= 0; !result
&& i
< ncmds
&& startofcmds
<= (char *)dlp
&& (char *)dlp
< endofcmds
; i
++) {
2328 if (LC_LOAD_DYLIB
== _CFBundleSwapInt32Conditional(dlp
->cmd
, swapped
)) {
2329 uint32_t nameoffset
= _CFBundleSwapInt32Conditional(dlp
->dylib
.name
.offset
, swapped
);
2330 const char *name
= (const char *)dlp
+ nameoffset
;
2331 if (startofcmds
<= name
&& name
+ sizeof(libX11name
) <= endofcmds
&& 0 == strncmp(name
, libX11name
, sizeof(libX11name
) - 1)) result
= true;
2333 dlp
= (struct dylib_command
*)((char *)dlp
+ _CFBundleSwapInt32Conditional(dlp
->cmdsize
, swapped
));
2336 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->ncmds
, swapped
);
2337 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->sizeofcmds
, swapped
);
2338 const char *startofcmds
= loc
+ sizeof(struct mach_header
);
2339 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2340 struct dylib_command
*dlp
= (struct dylib_command
*)startofcmds
;
2341 if (endofcmds
> loc
+ X11_BYTES_TO_READ
) endofcmds
= loc
+ X11_BYTES_TO_READ
;
2342 for (i
= 0; !result
&& i
< ncmds
&& startofcmds
<= (char *)dlp
&& (char *)dlp
< endofcmds
; i
++) {
2343 if (LC_LOAD_DYLIB
== _CFBundleSwapInt32Conditional(dlp
->cmd
, swapped
)) {
2344 uint32_t nameoffset
= _CFBundleSwapInt32Conditional(dlp
->dylib
.name
.offset
, swapped
);
2345 const char *name
= (const char *)dlp
+ nameoffset
;
2346 if (startofcmds
<= name
&& name
+ sizeof(libX11name
) <= endofcmds
&& 0 == strncmp(name
, libX11name
, sizeof(libX11name
) - 1)) result
= true;
2348 dlp
= (struct dylib_command
*)((char *)dlp
+ _CFBundleSwapInt32Conditional(dlp
->cmdsize
, swapped
));
2352 if (buffer
) free(buffer
);
2356 // returns zero-ref dictionary under GC
2357 static CFDictionaryRef
_CFBundleGrokInfoDictFromFile(int fd
, const void *bytes
, CFIndex length
, uint32_t offset
, Boolean swapped
, Boolean sixtyFour
) {
2358 struct stat statBuf
;
2359 off_t fileLength
= 0;
2360 char *maploc
= NULL
;
2363 CFDictionaryRef result
= NULL
;
2364 Boolean foundit
= false;
2365 if (fd
>= 0 && fstat(fd
, &statBuf
) == 0 && (maploc
= mmap(0, statBuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0)) != (void *)-1) {
2367 fileLength
= statBuf
.st_size
;
2370 fileLength
= length
;
2372 if (fileLength
> offset
+ sizeof(struct mach_header_64
)) {
2374 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)(loc
+ offset
))->ncmds
, swapped
);
2375 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)(loc
+ offset
))->sizeofcmds
, swapped
);
2376 const char *startofcmds
= loc
+ offset
+ sizeof(struct mach_header_64
);
2377 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2378 struct segment_command_64
*sgp
= (struct segment_command_64
*)startofcmds
;
2379 if (endofcmds
> loc
+ fileLength
) endofcmds
= loc
+ fileLength
;
2380 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2381 if (LC_SEGMENT_64
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2382 struct section_64
*sp
= (struct section_64
*)((char *)sgp
+ sizeof(struct segment_command_64
));
2383 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2384 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2385 if (0 == strncmp(sp
->sectname
, PLIST_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, TEXT_SEGMENT
, sizeof(sp
->segname
))) {
2386 uint64_t sectlength64
= _CFBundleSwapInt64Conditional(sp
->size
, swapped
);
2387 uint32_t sectlength
= (uint32_t)(sectlength64
& 0xffffffff);
2388 uint32_t sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2389 const char *sectbytes
= loc
+ offset
+ sectoffset
;
2390 // we don't support huge-sized plists
2391 if (sectlength64
<= 0xffffffff && loc
<= sectbytes
&& sectbytes
+ sectlength
<= loc
+ fileLength
) result
= (CFDictionaryRef
)_CFBundleGrokInfoDictFromData(sectbytes
, sectlength
);
2394 sp
= (struct section_64
*)((char *)sp
+ sizeof(struct section_64
));
2397 sgp
= (struct segment_command_64
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2400 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)(loc
+ offset
))->ncmds
, swapped
);
2401 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)(loc
+ offset
))->sizeofcmds
, swapped
);
2402 const char *startofcmds
= loc
+ offset
+ sizeof(struct mach_header
);
2403 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2404 struct segment_command
*sgp
= (struct segment_command
*)startofcmds
;
2405 if (endofcmds
> loc
+ fileLength
) endofcmds
= loc
+ fileLength
;
2406 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2407 if (LC_SEGMENT
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2408 struct section
*sp
= (struct section
*)((char *)sgp
+ sizeof(struct segment_command
));
2409 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2410 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2411 if (0 == strncmp(sp
->sectname
, PLIST_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, TEXT_SEGMENT
, sizeof(sp
->segname
))) {
2412 uint32_t sectlength
= _CFBundleSwapInt32Conditional(sp
->size
, swapped
);
2413 uint32_t sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2414 const char *sectbytes
= loc
+ offset
+ sectoffset
;
2415 if (loc
<= sectbytes
&& sectbytes
+ sectlength
<= loc
+ fileLength
) result
= (CFDictionaryRef
)_CFBundleGrokInfoDictFromData(sectbytes
, sectlength
);
2418 sp
= (struct section
*)((char *)sp
+ sizeof(struct section
));
2421 sgp
= (struct segment_command
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2425 if (maploc
) munmap(maploc
, statBuf
.st_size
);
2429 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
) {
2430 uint32_t sectlength
= 0, sectoffset
= 0, localVersion
= 0, localFlags
= 0;
2431 char *buffer
= NULL
;
2433 const char *loc
= NULL
;
2435 Boolean foundit
= false, localHasObjc
= false;
2437 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
2438 buffer
= malloc(IMAGE_INFO_BYTES_TO_READ
);
2439 if (buffer
&& read(fd
, buffer
, IMAGE_INFO_BYTES_TO_READ
) >= IMAGE_INFO_BYTES_TO_READ
) loc
= buffer
;
2440 } else if (bytes
&& length
>= offset
+ IMAGE_INFO_BYTES_TO_READ
) {
2441 loc
= bytes
+ offset
;
2445 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->ncmds
, swapped
);
2446 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->sizeofcmds
, swapped
);
2447 const char *startofcmds
= loc
+ sizeof(struct mach_header_64
);
2448 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2449 struct segment_command_64
*sgp
= (struct segment_command_64
*)startofcmds
;
2450 if (endofcmds
> loc
+ IMAGE_INFO_BYTES_TO_READ
) endofcmds
= loc
+ IMAGE_INFO_BYTES_TO_READ
;
2451 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2452 if (LC_SEGMENT_64
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2453 struct section_64
*sp
= (struct section_64
*)((char *)sgp
+ sizeof(struct segment_command_64
));
2454 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2455 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2456 if (0 == strncmp(sp
->segname
, OBJC_SEGMENT_64
, sizeof(sp
->segname
))) localHasObjc
= true;
2457 if (0 == strncmp(sp
->sectname
, IMAGE_INFO_SECTION_64
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, OBJC_SEGMENT_64
, sizeof(sp
->segname
))) {
2458 uint64_t sectlength64
= _CFBundleSwapInt64Conditional(sp
->size
, swapped
);
2459 sectlength
= (uint32_t)(sectlength64
& 0xffffffff);
2460 sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2463 sp
= (struct section_64
*)((char *)sp
+ sizeof(struct section_64
));
2466 sgp
= (struct segment_command_64
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2469 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->ncmds
, swapped
);
2470 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->sizeofcmds
, swapped
);
2471 const char *startofcmds
= loc
+ sizeof(struct mach_header
);
2472 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2473 struct segment_command
*sgp
= (struct segment_command
*)startofcmds
;
2474 if (endofcmds
> loc
+ IMAGE_INFO_BYTES_TO_READ
) endofcmds
= loc
+ IMAGE_INFO_BYTES_TO_READ
;
2475 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2476 if (LC_SEGMENT
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2477 struct section
*sp
= (struct section
*)((char *)sgp
+ sizeof(struct segment_command
));
2478 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2479 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2480 if (0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) localHasObjc
= true;
2481 if (0 == strncmp(sp
->sectname
, IMAGE_INFO_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) {
2482 sectlength
= _CFBundleSwapInt32Conditional(sp
->size
, swapped
);
2483 sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2486 sp
= (struct section
*)((char *)sp
+ sizeof(struct section
));
2489 sgp
= (struct segment_command
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2492 if (sectlength
>= 8) {
2493 if (fd
>= 0 && lseek(fd
, offset
+ sectoffset
, SEEK_SET
) == (off_t
)(offset
+ sectoffset
) && read(fd
, sectbuffer
, 8) >= 8) {
2494 localVersion
= _CFBundleSwapInt32Conditional(*(uint32_t *)sectbuffer
, swapped
);
2495 localFlags
= _CFBundleSwapInt32Conditional(*(uint32_t *)(sectbuffer
+ 4), swapped
);
2496 } else if (bytes
&& length
>= offset
+ sectoffset
+ 8) {
2497 localVersion
= _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes
+ offset
+ sectoffset
), swapped
);
2498 localFlags
= _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes
+ offset
+ sectoffset
+ 4), swapped
);
2502 if (buffer
) free(buffer
);
2503 if (hasObjc
) *hasObjc
= localHasObjc
;
2504 if (objcVersion
) *objcVersion
= localVersion
;
2505 if (objcFlags
) *objcFlags
= localFlags
;
2508 // returns zero-ref dictionary in *infodict under GC
2509 static UInt32
_CFBundleGrokMachTypeForFatFile(int fd
, const void *bytes
, CFIndex length
, Boolean swap
, Boolean
*isX11
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2510 CFIndex headerLength
= length
;
2511 unsigned char headerBuffer
[MAGIC_BYTES_TO_READ
];
2512 UInt32 machtype
= UNKNOWN_FILETYPE
, magic
, numFatHeaders
, maxFatHeaders
, i
;
2513 unsigned char buffer
[sizeof(struct mach_header_64
)];
2514 const unsigned char *moreBytes
= NULL
;
2515 const NXArchInfo
*archInfo
= NXGetLocalArchInfo();
2516 SInt32 curArch
= _CFBundleCurrentArchitecture();
2518 struct fat_arch
*fat
= NULL
;
2520 if (isX11
) *isX11
= false;
2521 if (architectures
) *architectures
= NULL
;
2522 if (infodict
) *infodict
= NULL
;
2523 if (hasObjc
) *hasObjc
= false;
2524 if (objcVersion
) *objcVersion
= 0;
2525 if (objcFlags
) *objcFlags
= 0;
2527 if (headerLength
> MAGIC_BYTES_TO_READ
) headerLength
= MAGIC_BYTES_TO_READ
;
2528 (void)memmove(headerBuffer
, bytes
, headerLength
);
2530 for (i
= 0; i
< headerLength
; i
+= 4) *(UInt32
*)(headerBuffer
+ i
) = CFSwapInt32(*(UInt32
*)(headerBuffer
+ i
));
2532 numFatHeaders
= ((struct fat_header
*)headerBuffer
)->nfat_arch
;
2533 maxFatHeaders
= (headerLength
- sizeof(struct fat_header
)) / sizeof(struct fat_arch
);
2534 if (numFatHeaders
> maxFatHeaders
) numFatHeaders
= maxFatHeaders
;
2535 if (numFatHeaders
> 0) {
2536 if (archInfo
) fat
= NXFindBestFatArch(archInfo
->cputype
, archInfo
->cpusubtype
, (struct fat_arch
*)(headerBuffer
+ sizeof(struct fat_header
)), numFatHeaders
);
2537 if (!fat
&& curArch
!= 0) fat
= NXFindBestFatArch((cpu_type_t
)curArch
, (cpu_subtype_t
)0, (struct fat_arch
*)(headerBuffer
+ sizeof(struct fat_header
)), numFatHeaders
);
2538 if (!fat
) fat
= (struct fat_arch
*)(headerBuffer
+ sizeof(struct fat_header
));
2539 if (architectures
) {
2540 CFMutableArrayRef mutableArchitectures
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
2541 for (i
= 0; i
< numFatHeaders
; i
++) {
2542 CFNumberRef architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, headerBuffer
+ sizeof(struct fat_header
) + i
* sizeof(struct fat_arch
));
2543 if (CFArrayGetFirstIndexOfValue(mutableArchitectures
, CFRangeMake(0, CFArrayGetCount(mutableArchitectures
)), architecture
) < 0) CFArrayAppendValue(mutableArchitectures
, architecture
);
2544 CFRelease(architecture
);
2546 *architectures
= (CFArrayRef
)mutableArchitectures
;
2550 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
)) {
2552 } else if (bytes
&& (uint32_t)length
>= fat
->offset
+ sizeof(struct mach_header_64
)) {
2553 moreBytes
= bytes
+ fat
->offset
;
2556 magic
= *((UInt32
*)moreBytes
);
2557 if (MH_MAGIC
== magic
) {
2558 machtype
= ((struct mach_header
*)moreBytes
)->filetype
;
2559 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, false, false);
2560 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, false, false);
2561 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, false, false, hasObjc
, objcVersion
, objcFlags
);
2562 } else if (MH_CIGAM
== magic
) {
2563 machtype
= CFSwapInt32(((struct mach_header
*)moreBytes
)->filetype
);
2564 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, true, false);
2565 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, true, false);
2566 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, true, false, hasObjc
, objcVersion
, objcFlags
);
2567 } else if (MH_MAGIC_64
== magic
) {
2568 machtype
= ((struct mach_header_64
*)moreBytes
)->filetype
;
2569 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, false, true);
2570 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, false, true);
2571 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, false, true, hasObjc
, objcVersion
, objcFlags
);
2572 } else if (MH_CIGAM_64
== magic
) {
2573 machtype
= CFSwapInt32(((struct mach_header_64
*)moreBytes
)->filetype
);
2574 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, true, true);
2575 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, true, true);
2576 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, true, true, hasObjc
, objcVersion
, objcFlags
);
2583 // returns zero-ref dictionary in *infodict under GC
2584 static UInt32
_CFBundleGrokMachType(int fd
, const void *bytes
, CFIndex length
, Boolean
*isX11
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2585 unsigned int magic
= *((UInt32
*)bytes
), machtype
= UNKNOWN_FILETYPE
, cputype
;
2586 CFNumberRef architecture
= NULL
;
2588 if (isX11
) *isX11
= false;
2589 if (architectures
) *architectures
= NULL
;
2590 if (infodict
) *infodict
= NULL
;
2591 if (hasObjc
) *hasObjc
= false;
2592 if (objcVersion
) *objcVersion
= 0;
2593 if (objcFlags
) *objcFlags
= 0;
2594 if (MH_MAGIC
== magic
) {
2595 machtype
= ((struct mach_header
*)bytes
)->filetype
;
2596 cputype
= ((struct mach_header
*)bytes
)->cputype
;
2597 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2598 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, false, false);
2599 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, false, false);
2600 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, false, false, hasObjc
, objcVersion
, objcFlags
);
2601 } else if (MH_CIGAM
== magic
) {
2602 machtype
= CFSwapInt32(((struct mach_header
*)bytes
)->filetype
);
2603 cputype
= CFSwapInt32(((struct mach_header
*)bytes
)->cputype
);
2604 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2605 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, true, false);
2606 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, true, false);
2607 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, true, false, hasObjc
, objcVersion
, objcFlags
);
2608 } else if (MH_MAGIC_64
== magic
) {
2609 machtype
= ((struct mach_header_64
*)bytes
)->filetype
;
2610 cputype
= ((struct mach_header_64
*)bytes
)->cputype
;
2611 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2612 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, false, true);
2613 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, false, true);
2614 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, false, true, hasObjc
, objcVersion
, objcFlags
);
2615 } else if (MH_CIGAM_64
== magic
) {
2616 machtype
= CFSwapInt32(((struct mach_header_64
*)bytes
)->filetype
);
2617 cputype
= CFSwapInt32(((struct mach_header_64
*)bytes
)->cputype
);
2618 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2619 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, true, true);
2620 if (infodict
) *infodict
= _CFBundleGrokInfoDictFromFile(fd
, bytes
, length
, 0, true, true);
2621 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, true, true, hasObjc
, objcVersion
, objcFlags
);
2622 } else if (FAT_MAGIC
== magic
) {
2623 machtype
= _CFBundleGrokMachTypeForFatFile(fd
, bytes
, length
, false, isX11
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2624 } else if (FAT_CIGAM
== magic
) {
2625 machtype
= _CFBundleGrokMachTypeForFatFile(fd
, bytes
, length
, true, isX11
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2626 } else if (PEF_MAGIC
== magic
|| PEF_CIGAM
== magic
) {
2627 machtype
= PEF_FILETYPE
;
2629 if (architectures
&& architecture
) *architectures
= CFArrayCreate(kCFAllocatorSystemDefault
, (const void **)&architecture
, 1, &kCFTypeArrayCallBacks
);
2630 if (architecture
) CFRelease(architecture
);
2634 #endif /* BINARY_SUPPORT_DYLD */
2636 static Boolean
_CFBundleGrokFileTypeForZipMimeType(const unsigned char *bytes
, CFIndex length
, const char **ext
) {
2637 unsigned namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 26))), extralength
= CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 28)));
2638 const unsigned char *data
= bytes
+ 30 + namelength
+ extralength
;
2640 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))) {
2641 data
+= ('.' == *(data
+ 15)) ? 16 : 18;
2642 if (0 == ustrncasecmp(data
, "sun.xml.", 8)) {
2644 if (0 == ustrncasecmp(data
, "calc", 4)) i
= 0;
2645 else if (0 == ustrncasecmp(data
, "draw", 4)) i
= 1;
2646 else if (0 == ustrncasecmp(data
, "writer.global", 13)) i
= 2;
2647 else if (0 == ustrncasecmp(data
, "impress", 7)) i
= 3;
2648 else if (0 == ustrncasecmp(data
, "math", 4)) i
= 4;
2649 else if (0 == ustrncasecmp(data
, "writer", 6)) i
= 5;
2650 if (i
>= 0 && ext
) *ext
= __CFBundleOOExtensionsArray
+ i
* EXTENSION_LENGTH
;
2651 } else if (0 == ustrncasecmp(data
, "oasis.opendocument.", 19)) {
2653 if (0 == ustrncasecmp(data
, "chart", 5)) i
= 0;
2654 else if (0 == ustrncasecmp(data
, "formula", 7)) i
= 1;
2655 else if (0 == ustrncasecmp(data
, "graphics", 8)) i
= 2;
2656 else if (0 == ustrncasecmp(data
, "text-web", 8)) i
= 3;
2657 else if (0 == ustrncasecmp(data
, "image", 5)) i
= 4;
2658 else if (0 == ustrncasecmp(data
, "text-master", 11)) i
= 5;
2659 else if (0 == ustrncasecmp(data
, "presentation", 12)) i
= 6;
2660 else if (0 == ustrncasecmp(data
, "spreadsheet", 11)) i
= 7;
2661 else if (0 == ustrncasecmp(data
, "text", 4)) i
= 8;
2662 if (i
>= 0 && ext
) *ext
= __CFBundleODExtensionsArray
+ i
* EXTENSION_LENGTH
;
2664 } else if (bytes
< data
&& data
+ 41 <= bytes
+ length
&& 8 == CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 8))) && 0x4b2c28c8 == CFSwapInt32HostToBig(*((UInt32
*)data
)) && 0xc94c4e2c == CFSwapInt32HostToBig(*((UInt32
*)(data
+ 4)))) {
2665 // AbiWord compressed mimetype odt
2666 if (ext
) *ext
= "odt";
2671 static const char *_CFBundleGrokFileTypeForZipFile(int fd
, const unsigned char *bytes
, CFIndex length
, off_t fileLength
) {
2672 const char *ext
= "zip";
2673 const unsigned char *moreBytes
= NULL
;
2674 unsigned char *buffer
= NULL
;
2676 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;
2679 for (i
= 0; !foundMimetype
&& i
+ 30 < length
; i
++) {
2680 if (0x50 == bytes
[i
] && 0x4b == bytes
[i
+ 1]) {
2681 unsigned namelength
= 0, offset
= 0;
2682 if (0x01 == bytes
[i
+ 2] && 0x02 == bytes
[i
+ 3]) {
2683 namelength
= (unsigned)CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ i
+ 28)));
2685 } else if (0x03 == bytes
[i
+ 2] && 0x04 == bytes
[i
+ 3]) {
2686 namelength
= (unsigned)CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ i
+ 26)));
2689 if (offset
> 0 && (CFIndex
)(i
+ offset
+ namelength
) <= length
) {
2690 //printf("%.*s\n", namelength, bytes + i + offset);
2691 if (8 == namelength
&& 30 == offset
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "mimetype", 8)) foundMimetype
= _CFBundleGrokFileTypeForZipMimeType(bytes
+ i
, length
- i
, &ext
);
2692 else if (9 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/", 9)) hasMetaInf
= true;
2693 else if (11 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "content.xml", 11)) hasContentXML
= true;
2694 else if (11 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "_rels/.rels", 11)) hasRels
= true;
2695 else if (19 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "[Content_Types].xml", 19)) hasContentTypes
= true;
2696 else if (20 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/MANIFEST.MF", 20)) hasManifestMF
= true;
2697 else if (21 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/manifest.xml", 21)) hasManifestXML
= true;
2698 else if (4 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".opf", 4)) hasOPF
= true;
2699 else if (4 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".sml", 4)) hasSMIL
= true;
2700 else if (5 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 5, ".smil", 5)) hasSMIL
= true;
2701 else if (7 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "xl/", 3) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2702 else if (8 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "ppt/", 4) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2703 else if (9 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "word/", 5) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasWordDocument
= true;
2704 else if (10 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "excel/", 6) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2705 else if (15 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "powerpoint/", 11) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2706 i
+= offset
+ namelength
- 1;
2711 if (!foundMimetype
) {
2712 if (fileLength
>= ZIP_BYTES_TO_READ
) {
2713 if (fd
>= 0 && lseek(fd
, fileLength
- ZIP_BYTES_TO_READ
, SEEK_SET
) == fileLength
- ZIP_BYTES_TO_READ
) {
2714 buffer
= (unsigned char *)malloc(ZIP_BYTES_TO_READ
);
2715 if (buffer
&& read(fd
, buffer
, ZIP_BYTES_TO_READ
) >= ZIP_BYTES_TO_READ
) moreBytes
= buffer
;
2716 } else if (bytes
&& length
>= ZIP_BYTES_TO_READ
) {
2717 moreBytes
= bytes
+ length
- ZIP_BYTES_TO_READ
;
2721 for (i
= 0; i
+ 30 < ZIP_BYTES_TO_READ
; i
++) {
2722 if (0x50 == moreBytes
[i
] && 0x4b == moreBytes
[i
+ 1]) {
2723 unsigned namelength
= 0, offset
= 0;
2724 if (0x01 == moreBytes
[i
+ 2] && 0x02 == moreBytes
[i
+ 3]) {
2725 namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(moreBytes
+ i
+ 28)));
2727 } else if (0x03 == moreBytes
[i
+ 2] && 0x04 == moreBytes
[i
+ 3]) {
2728 namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(moreBytes
+ i
+ 26)));
2731 if (offset
> 0 && i
+ offset
+ namelength
<= ZIP_BYTES_TO_READ
) {
2732 //printf("%.*s\n", namelength, moreBytes + i + offset);
2733 if (9 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/", 9)) hasMetaInf
= true;
2734 else if (11 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "content.xml", 11)) hasContentXML
= true;
2735 else if (11 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "_rels/.rels", 11)) hasRels
= true;
2736 else if (19 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "[Content_Types].xml", 19)) hasContentTypes
= true;
2737 else if (20 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/MANIFEST.MF", 20)) hasManifestMF
= true;
2738 else if (21 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/manifest.xml", 21)) hasManifestXML
= true;
2739 else if (4 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".opf", 4)) hasOPF
= true;
2740 else if (4 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".sml", 4)) hasSMIL
= true;
2741 else if (5 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 5, ".smil", 5)) hasSMIL
= true;
2742 else if (7 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "xl/", 3) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2743 else if (8 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "ppt/", 4) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2744 else if (9 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "word/", 5) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasWordDocument
= true;
2745 else if (10 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "excel/", 6) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2746 else if (15 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "powerpoint/", 11) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2747 i
+= offset
+ namelength
- 1;
2752 //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);
2753 if (hasManifestMF
) ext
= "jar";
2754 else if ((hasRels
|| hasContentTypes
) && hasWordDocument
) ext
= "docx";
2755 else if ((hasRels
|| hasContentTypes
) && hasExcelDocument
) ext
= "xlsx";
2756 else if ((hasRels
|| hasContentTypes
) && hasPowerPointDocument
) ext
= "pptx";
2757 else if (hasManifestXML
|| hasContentXML
) ext
= "odt";
2758 else if (hasMetaInf
) ext
= "jar";
2759 else if (hasOPF
&& hasSMIL
) ext
= "dtb";
2760 else if (hasOPF
) ext
= "oeb";
2762 if (buffer
) free(buffer
);
2767 static Boolean
_CFBundleCheckOLEName(const char *name
, const char *bytes
, unsigned length
) {
2768 Boolean retval
= true;
2770 for (j
= 0; retval
&& j
< length
; j
++) if (bytes
[2 * j
] != name
[j
]) retval
= false;
2774 static const char *_CFBundleGrokFileTypeForOLEFile(int fd
, const void *bytes
, CFIndex length
, off_t offset
) {
2775 const char *ext
= "ole", *moreBytes
= NULL
;
2776 char *buffer
= NULL
;
2778 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
2779 buffer
= (char *)malloc(OLE_BYTES_TO_READ
);
2780 if (buffer
&& read(fd
, buffer
, OLE_BYTES_TO_READ
) >= OLE_BYTES_TO_READ
) moreBytes
= buffer
;
2781 } else if (bytes
&& length
>= offset
+ OLE_BYTES_TO_READ
) {
2782 moreBytes
= (char *)bytes
+ offset
;
2785 Boolean foundit
= false;
2787 for (i
= 0; !foundit
&& i
< 4; i
++) {
2788 char namelength
= moreBytes
[128 * i
+ 64] / 2;
2790 if (sizeof(XLS_NAME
) == namelength
&& _CFBundleCheckOLEName(XLS_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "xls";
2791 else if (sizeof(XLS_NAME2
) == namelength
&& _CFBundleCheckOLEName(XLS_NAME2
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "xls";
2792 else if (sizeof(DOC_NAME
) == namelength
&& _CFBundleCheckOLEName(DOC_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "doc";
2793 else if (sizeof(PPT_NAME
) == namelength
&& _CFBundleCheckOLEName(PPT_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "ppt";
2794 else foundit
= false;
2797 if (buffer
) free(buffer
);
2801 #if DEPLOYMENT_TARGET_WINDOWS
2802 // Windows isspace implementation limits the input chars to < 256 in the ASCII range. It will
2803 // assert in debug builds. This is annoying. We merrily grok chars > 256.
2804 static inline BOOL
isspace(char c
) {
2805 return (c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r'|| c
== '\v' || c
== '\f');
2809 // returns zero-ref dictionary in *infodict under GC
2810 static Boolean
_CFBundleGrokFileType(CFURLRef url
, CFDataRef data
, CFStringRef
*extension
, UInt32
*machtype
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2812 const unsigned char *bytes
= NULL
;
2813 unsigned char buffer
[MAGIC_BYTES_TO_READ
];
2814 CFIndex i
, length
= 0;
2815 off_t fileLength
= 0;
2816 const char *ext
= NULL
;
2817 UInt32 mt
= UNKNOWN_FILETYPE
;
2818 #if defined(BINARY_SUPPORT_DYLD)
2819 Boolean isX11
= false;
2820 #endif /* BINARY_SUPPORT_DYLD */
2821 Boolean isFile
= false, isPlain
= true, isZero
= true, isSpace
= true, hasBOM
= false;
2822 // 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, caf, 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, m4v, 3gp, 3g2, 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, cin, exr
2823 // ??? we do not distinguish between different wm types, returning wmv for any of wmv, wma, or asf
2824 // ??? we do not distinguish between ordinary documents and template versions (often there is no difference in file contents)
2825 // ??? the distinctions between docx, xlsx, and pptx may not be entirely reliable
2826 if (architectures
) *architectures
= NULL
;
2827 if (infodict
) *infodict
= NULL
;
2828 if (hasObjc
) *hasObjc
= false;
2829 if (objcVersion
) *objcVersion
= 0;
2830 if (objcFlags
) *objcFlags
= 0;
2832 Boolean gotPath
= FALSE
;
2833 char path
[CFMaxPathSize
];
2834 gotPath
= CFURLGetFileSystemRepresentation(url
, true, (uint8_t *)path
, CFMaxPathSize
);
2835 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
2836 struct stat statBuf
;
2837 #elif DEPLOYMENT_TARGET_WINDOWS
2838 struct _stat statBuf
;
2840 #error Unknown or unspecified DEPLOYMENT_TARGET
2842 if (gotPath
&& stat(path
, &statBuf
) == 0 && (statBuf
.st_mode
& S_IFMT
) == S_IFREG
&& (fd
= open(path
, O_RDONLY
| CF_OPENFLGS
, 0777)) >= 0) {
2843 length
= read(fd
, buffer
, MAGIC_BYTES_TO_READ
);
2844 fileLength
= statBuf
.st_size
;
2849 if (!isFile
&& data
) {
2850 length
= CFDataGetLength(data
);
2851 fileLength
= (off_t
)length
;
2852 bytes
= CFDataGetBytePtr(data
);
2853 if (length
== 0) ext
= "txt";
2857 UInt32 magic
= CFSwapInt32HostToBig(*((UInt32
*)bytes
));
2858 for (i
= 0; !ext
&& i
< NUM_EXTENSIONS
; i
++) {
2859 if (__CFBundleMagicNumbersArray
[i
] == magic
) ext
= __CFBundleExtensionsArray
+ i
* EXTENSION_LENGTH
;
2862 if (0xcafebabe == magic
&& 8 <= length
&& 0 != *((UInt16
*)(bytes
+ 4))) ext
= "class";
2863 #if defined(BINARY_SUPPORT_DYLD)
2864 else if ((int)sizeof(struct mach_header_64
) <= length
) mt
= _CFBundleGrokMachType(fd
, bytes
, length
, extension
? &isX11
: NULL
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2866 if (MH_OBJECT
== mt
) ext
= "o";
2867 else if (MH_EXECUTE
== mt
) ext
= isX11
? "x11app" : "tool";
2868 else if (PEF_FILETYPE
== mt
) ext
= "pef";
2869 else if (MH_CORE
== mt
) ext
= "core";
2870 else if (MH_DYLIB
== mt
) ext
= "dylib";
2871 else if (MH_BUNDLE
== mt
) ext
= "bundle";
2872 #endif /* BINARY_SUPPORT_DYLD */
2873 else if (0x7b5c7274 == magic
&& (6 > length
|| 'f' != bytes
[4])) ext
= NULL
;
2874 else if (0x25504446 == magic
&& (6 > length
|| '-' != bytes
[4])) ext
= NULL
;
2875 else if (0x00010000 == magic
&& (6 > length
|| 0 != bytes
[4])) ext
= NULL
;
2876 else if (0x47494638 == magic
&& (6 > length
|| (0x3761 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))) && 0x3961 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4)))))) ext
= NULL
;
2877 else if (0x0000000c == magic
&& (6 > length
|| 0x6a50 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2878 else if (0x2356524d == magic
&& (6 > length
|| 0x4c20 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2879 else if (0x28445746 == magic
&& (6 > length
|| 0x2056 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2880 else if (0x30373037 == magic
&& (6 > length
|| 0x30 != bytes
[4] || !isdigit(bytes
[5]))) ext
= NULL
;
2881 else if (0x41433130 == magic
&& (6 > length
|| 0x31 != bytes
[4] || !isdigit(bytes
[5]))) ext
= NULL
;
2882 else if (0x89504e47 == magic
&& (8 > length
|| 0x0d0a1a0a != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2883 else if (0x53747566 == magic
&& (8 > length
|| 0x66497420 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2884 else if (0x3026b275 == magic
&& (8 > length
|| 0x8e66cf11 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2885 else if (0x67696d70 == magic
&& (8 > length
|| 0x20786366 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2886 else if (0x424f4d53 == magic
&& (8 > length
|| 0x746f7265 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2887 else if (0x49544f4c == magic
&& (8 > length
|| 0x49544c53 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2888 else if (0x72746664 == magic
&& (8 > length
|| 0x00000000 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2889 else if (0x3d796265 == magic
&& (12 > length
|| 0x67696e20 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || (0x6c696e65 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8))) && 0x70617274 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)))))) ext
= NULL
;
2890 else if (0x63616666 == magic
&& (12 > length
|| 0 != bytes
[4] || 0x64657363 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8))))) ext
= NULL
;
2891 else if (0x504b0304 == magic
) ext
= _CFBundleGrokFileTypeForZipFile(fd
, bytes
, length
, fileLength
);
2892 else if (0x25215053 == magic
) {
2893 if (11 <= length
&& 0 == ustrncmp(bytes
+ 4, "-Adobe-", 7)) ext
= "ps";
2894 else if (14 <= length
&& 0 == ustrncmp(bytes
+ 4, "-AdobeFont", 10)) ext
= "pfa";
2896 } else if (0x464f524d == magic
) {
2900 UInt32 iffMagic
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2901 if (0x41494646 == iffMagic
) ext
= "aiff";
2902 else if (0x414946 == iffMagic
) ext
= "aifc";
2904 } else if (0x52494646 == magic
) {
2908 UInt32 riffMagic
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2909 if (0x57415645 == riffMagic
) ext
= "wav";
2910 else if (0x41564920 == riffMagic
) ext
= "avi";
2912 } else if (0xd0cf11e0 == magic
) {
2914 if (52 <= length
) ext
= _CFBundleGrokFileTypeForOLEFile(fd
, bytes
, length
, 512 * (1 + CFSwapInt32HostToLittle(*((UInt32
*)(bytes
+ 48)))));
2915 } else if (0x62656769 == magic
) {
2918 if (76 <= length
&& 'n' == bytes
[4] && ' ' == bytes
[5] && isdigit(bytes
[6]) && isdigit(bytes
[7]) && isdigit(bytes
[8]) && ' ' == bytes
[9]) {
2919 CFIndex endOfLine
= 0;
2920 for (i
= 10; 0 == endOfLine
&& i
< length
; i
++) if ('\n' == bytes
[i
]) endOfLine
= i
;
2921 if (10 <= endOfLine
&& endOfLine
+ 62 < length
&& 'M' == bytes
[endOfLine
+ 1] && '\n' == bytes
[endOfLine
+ 62]) {
2923 for (i
= endOfLine
+ 1; ext
&& i
< endOfLine
+ 62; i
++) if (!isprint(bytes
[i
])) ext
= NULL
;
2928 if (extension
&& !ext
) {
2929 UInt16 shortMagic
= CFSwapInt16HostToBig(*((UInt16
*)bytes
));
2930 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";
2931 else if (8 <= length
&& (0x6d6f6f76 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x6d646174 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x77696465 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "mov";
2932 else if (8 <= length
&& (0x69647363 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x69646174 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "qtif";
2933 else if (8 <= length
&& 0x424f424f == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4)))) ext
= "cwk";
2934 else if (8 <= length
&& 0x62706c69 == magic
&& 0x7374 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))) && isdigit(bytes
[6]) && isdigit(bytes
[7])) {
2935 for (i
= 8; !ext
&& i
< 128 && i
+ 16 <= length
; i
++) {
2936 if (0 == ustrncmp(bytes
+ i
, "WebMainResource", 15)) ext
= "webarchive";
2938 if (!ext
) ext
= "plist";
2939 } else if (0 == shortMagic
&& 12 <= length
&& 0x66747970 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4)))) {
2940 // ??? may want more ftyp values
2941 UInt32 ftyp
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2942 if (0x6d703431 == ftyp
|| 0x6d703432 == ftyp
|| 0x69736f6d == ftyp
|| 0x69736f32 == ftyp
) ext
= "mp4";
2943 else if (0x4d344120 == ftyp
) ext
= "m4a";
2944 else if (0x4d344220 == ftyp
) ext
= "m4b";
2945 else if (0x4d345020 == ftyp
) ext
= "m4p";
2946 else if (0x4d345620 == ftyp
|| 0x4d345648 == ftyp
|| 0x4d345650 == ftyp
) ext
= "m4v";
2947 else if (0x3367 == (ftyp
>> 16)) {
2948 UInt16 remainder
= (ftyp
& 0xffff);
2949 if (0x6536 == remainder
|| 0x6537 == remainder
|| 0x6736 == remainder
|| 0x7034 == remainder
|| 0x7035 == remainder
|| 0x7036 == remainder
|| 0x7236 == remainder
|| 0x7336 == remainder
|| 0x7337 == remainder
) ext
= "3gp";
2950 else if (0x3261 == remainder
) ext
= "3g2";
2952 } else if (0x424d == shortMagic
&& 18 <= length
) {
2953 UInt32 btyp
= CFSwapInt32HostToLittle(*((UInt32
*)(bytes
+ 14)));
2954 if (40 == btyp
|| btyp
== 12 || btyp
== 64 || btyp
== 108 || btyp
== 124) ext
= "bmp";
2955 } else if (20 <= length
&& 0 == ustrncmp(bytes
+ 6, "%!PS-AdobeFont", 14)) ext
= "pfb";
2956 else if (40 <= length
&& 0x42696e48 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 34))) && 0x6578 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 38)))) ext
= "hqx";
2957 else if (128 <= length
&& 0x6d42494e == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 102)))) ext
= "bin";
2958 else if (128 <= length
&& 0 == bytes
[0] && 0 < bytes
[1] && bytes
[1] < 64 && 0 == bytes
[74] && 0 == bytes
[82] && 0 == (fileLength
% 128)) {
2959 UInt32 df
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 83))), rf
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 87))), blocks
= 1 + (df
+ 127) / 128 + (rf
+ 127) / 128;
2960 if (df
< 0x00800000 && rf
< 0x00800000 && 1 < blocks
&& (off_t
)(128 * blocks
) == fileLength
) ext
= "bin";
2961 } else if (265 <= length
&& 0x75737461 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 257))) && (0x72202000 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 261))) || 0x7200 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 261))))) ext
= "tar";
2962 else if (0xfeff == shortMagic
|| 0xfffe == shortMagic
) {
2964 if (12 <= length
&& ((0x3cfeff == *((UInt32
*)bytes
) && 0x740068 == *((UInt32
*)(bytes
+ 4)) && 0x6c006d == *((UInt32
*)(bytes
+ 8))) || (0xfffe3c00 == *((UInt32
*)bytes
) && 0x68007400 == *((UInt32
*)(bytes
+ 4)) && 0x6d006c00 == *((UInt32
*)(bytes
+ 8))))) ext
= "html";
2965 } else if (0x1f9d == shortMagic
) ext
= "Z";
2966 else if (0x1f8b == shortMagic
) ext
= "gz";
2967 else if (0x71c7 == shortMagic
|| 0xc771 == shortMagic
) ext
= "cpio";
2968 else if (0xf702 == shortMagic
) ext
= "dvi";
2969 else if (0x01da == shortMagic
&& (0 == bytes
[2] || 1 == bytes
[2]) && (0 < bytes
[3] && 16 > bytes
[3])) ext
= "sgi";
2970 else if (0x2321 == shortMagic
) {
2971 CFIndex endOfLine
= 0, lastSlash
= 0;
2972 for (i
= 2; 0 == endOfLine
&& i
< length
; i
++) if ('\n' == bytes
[i
]) endOfLine
= i
;
2973 if (endOfLine
> 3) {
2974 for (i
= endOfLine
- 1; 0 == lastSlash
&& i
> 1; i
--) if ('/' == bytes
[i
]) lastSlash
= i
;
2975 if (lastSlash
> 0) {
2976 if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "perl", 4)) ext
= "pl";
2977 else if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "python", 6)) ext
= "py";
2978 else if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "ruby", 4)) ext
= "rb";
2982 } else if (0xffd8 == shortMagic
&& 0xff == bytes
[2]) ext
= "jpeg";
2983 else if (0x4657 == shortMagic
&& 0x53 == bytes
[2]) ext
= "swf";
2984 else if (0x4357 == shortMagic
&& 0x53 == bytes
[2]) ext
= "swc";
2985 else if (0x4944 == shortMagic
&& '3' == bytes
[2] && 0x20 > bytes
[3]) ext
= "mp3";
2986 else if (0x425a == shortMagic
&& isdigit(bytes
[2]) && isdigit(bytes
[3])) ext
= "bz";
2987 else if (0x425a == shortMagic
&& 'h' == bytes
[2] && isdigit(bytes
[3]) && 8 <= length
&& (0x31415926 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x17724538 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "bz2";
2988 else if (0x0011 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 2))) || 0x0012 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 2)))) ext
= "tfm";
2991 if (extension
&& !ext
) {
2992 //??? what about MacOSRoman?
2993 if (0xef == bytes
[0] && 0xbb == bytes
[1] && 0xbf == bytes
[2]) { // UTF-8 BOM
2997 for (i
= (hasBOM
? 3 : 0); (isPlain
|| isZero
) && !ext
&& i
< length
&& i
< 512; i
++) {
2999 if (isPlain
&& '<' == c
&& i
+ 14 <= length
&& 0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype html", 13)) ext
= "html";
3000 if (isSpace
&& '<' == c
&& i
+ 14 <= length
) {
3001 if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype html", 13) || 0 == ustrncasecmp(bytes
+ i
+ 1, "head", 4) || 0 == ustrncasecmp(bytes
+ i
+ 1, "title", 5) || 0 == ustrncasecmp(bytes
+ i
+ 1, "script", 6) || 0 == ustrncasecmp(bytes
+ i
+ 1, "html", 4)) {
3003 } else if (0 == ustrncasecmp(bytes
+ i
+ 1, "?xml", 4)) {
3004 for (i
+= 4; !ext
&& i
< 128 && i
+ 20 <= length
; i
++) {
3005 if ('<' == bytes
[i
]) {
3006 if (0 == ustrncasecmp(bytes
+ i
+ 1, "abiword", 7)) ext
= "abw";
3007 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype svg", 12)) ext
= "svg";
3008 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype rdf", 12)) ext
= "rdf";
3009 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype x3d", 12)) ext
= "x3d";
3010 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype html", 13)) ext
= "html";
3011 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype posingfont", 19)) ext
= "sfont";
3012 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype plist", 14)) {
3013 for (i
+= 14; !ext
&& i
< 256 && i
+ 16 <= length
; i
++) {
3014 if (0 == ustrncmp(bytes
+ i
, "WebMainResource", 15)) ext
= "webarchive";
3016 if (!ext
) ext
= "plist";
3020 if (!ext
) ext
= "xml";
3023 if (0 != c
) isZero
= false;
3024 if (isZero
|| 0x7f <= c
|| (0x20 > c
&& !isspace(c
))) isPlain
= false;
3025 if (isZero
|| !isspace(c
)) isSpace
= false;
3029 if (16 <= length
&& 0 == ustrncmp(bytes
, "StartFontMetrics", 16)) ext
= "afm";
3031 } else if (isZero
&& length
>= MAGIC_BYTES_TO_READ
&& fileLength
>= 526) {
3033 if (lseek(fd
, 512, SEEK_SET
) == 512 && read(fd
, buffer
, MAGIC_BYTES_TO_READ
) >= 14) {
3034 if (0x001102ff == CFSwapInt32HostToBig(*((UInt32
*)(buffer
+ 10)))) ext
= "pict";
3037 if (526 <= length
&& 0x001102ff == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 522)))) ext
= "pict";
3042 if (extension
&& (!ext
|| 0 == strcmp(ext
, "bz2")) && length
>= MAGIC_BYTES_TO_READ
&& fileLength
>= DMG_BYTES_TO_READ
) {
3044 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
) {
3045 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";
3048 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";
3052 if (extension
) *extension
= ext
? CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault
, ext
, kCFStringEncodingUTF8
, kCFAllocatorNull
) : NULL
;
3053 if (machtype
) *machtype
= mt
;
3054 if (fd
>= 0) close(fd
);
3055 return (ext
? true : false);
3058 CFStringRef
_CFBundleCopyFileTypeForFileURL(CFURLRef url
) {
3059 CFStringRef extension
= NULL
;
3060 (void)_CFBundleGrokFileType(url
, NULL
, &extension
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3064 CFStringRef
_CFBundleCopyFileTypeForFileData(CFDataRef data
) {
3065 CFStringRef extension
= NULL
;
3066 (void)_CFBundleGrokFileType(NULL
, data
, &extension
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3070 // returns zero-ref dictionary under GC
3071 __private_extern__ CFDictionaryRef
_CFBundleCopyInfoDictionaryInExecutable(CFURLRef url
) {
3072 CFDictionaryRef result
= NULL
;
3073 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, NULL
, &result
, NULL
, NULL
, NULL
);
3077 __private_extern__ CFArrayRef
_CFBundleCopyArchitecturesForExecutable(CFURLRef url
) {
3078 CFArrayRef result
= NULL
;
3079 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, &result
, NULL
, NULL
, NULL
, NULL
);
3083 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
3084 static Boolean
_CFBundleGetObjCImageInfoForExecutable(CFURLRef url
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
3085 Boolean retval
= false;
3086 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, NULL
, NULL
, &retval
, objcVersion
, objcFlags
);
3091 #if defined(BINARY_SUPPORT_DYLD)
3093 __private_extern__ __CFPBinaryType
_CFBundleGrokBinaryType(CFURLRef executableURL
) {
3094 // 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.
3095 __CFPBinaryType result
= executableURL
? __CFBundleUnreadableBinary
: __CFBundleNoBinary
;
3096 UInt32 machtype
= UNKNOWN_FILETYPE
;
3097 if (_CFBundleGrokFileType(executableURL
, NULL
, NULL
, &machtype
, NULL
, NULL
, NULL
, NULL
, NULL
)) {
3100 result
= __CFBundleDYLDExecutableBinary
;
3103 result
= __CFBundleDYLDBundleBinary
;
3106 result
= __CFBundleDYLDFrameworkBinary
;
3109 result
= __CFBundleCFMBinary
;
3116 #endif /* BINARY_SUPPORT_DYLD */
3118 void _CFBundleSetCFMConnectionID(CFBundleRef bundle
, void *connectionID
) {
3119 bundle
->_connectionCookie
= connectionID
;
3120 bundle
->_isLoaded
= true;
3123 static CFStringRef
_CFBundleCopyLastPathComponent(CFBundleRef bundle
) {
3124 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
);
3125 CFStringRef str
= CFURLCopyFileSystemPath(bundleURL
, kCFURLPOSIXPathStyle
);
3126 UniChar buff
[CFMaxPathSize
];
3127 CFIndex buffLen
= CFStringGetLength(str
), startOfLastDir
= 0;
3129 CFRelease(bundleURL
);
3130 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
3131 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
3133 if (buffLen
> 0) startOfLastDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
3134 return CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfLastDir
]), buffLen
- startOfLastDir
);
3137 static CFErrorRef
_CFBundleCreateErrorDebug(CFAllocatorRef allocator
, CFBundleRef bundle
, CFIndex code
, CFStringRef debugString
) {
3138 const void *userInfoKeys
[6], *userInfoValues
[6];
3139 CFIndex numKeys
= 0;
3140 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
), absoluteURL
= CFURLCopyAbsoluteURL(bundleURL
), executableURL
= CFBundleCopyExecutableURL(bundle
);
3141 CFBundleRef bdl
= CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreFoundation"));
3142 CFStringRef bundlePath
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
), executablePath
= executableURL
? CFURLCopyFileSystemPath(executableURL
, PLATFORM_PATH_STYLE
) : NULL
, descFormat
= NULL
, desc
= NULL
, reason
= NULL
, suggestion
= NULL
;
3145 CFStringRef name
= (CFStringRef
)CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleNameKey
);
3146 name
= name
? (CFStringRef
)CFRetain(name
) : _CFBundleCopyLastPathComponent(bundle
);
3147 if (CFBundleExecutableNotFoundError
== code
) {
3148 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
3149 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl
, CFSTR("The bundle\\U2019s executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
3150 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSFileNoSuchFileError");
3151 } else if (CFBundleExecutableNotLoadableError
== code
) {
3152 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
3153 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl
, CFSTR("The bundle\\U2019s executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
3154 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableNotLoadableError");
3155 } else if (CFBundleExecutableArchitectureMismatchError
== code
) {
3156 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
3157 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl
, CFSTR("The bundle doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
3158 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-R"), CFSTR("Error"), bdl
, CFSTR("Try installing a universal version of the bundle."), "NSExecutableArchitectureMismatchError");
3159 } else if (CFBundleExecutableRuntimeMismatchError
== code
) {
3160 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it isn\\U2019t compatible with the current application."), "NSExecutableRuntimeMismatchError");
3161 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl
, CFSTR("The bundle isn\\U2019t compatible with this application."), "NSExecutableRuntimeMismatchError");
3162 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-R"), CFSTR("Error"), bdl
, CFSTR("Try installing a newer version of the bundle."), "NSExecutableRuntimeMismatchError");
3163 } else if (CFBundleExecutableLoadError
== code
) {
3164 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because it is damaged or missing necessary resources."), "NSExecutableLoadError");
3165 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-C"), CFSTR("Error"), bdl
, CFSTR("The bundle is damaged or missing necessary resources."), "NSExecutableLoadError");
3166 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableLoadError");
3167 } else if (CFBundleExecutableLinkError
== code
) {
3168 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded."), "NSExecutableLinkError");
3169 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl
, CFSTR("The bundle couldn\\U2019t be loaded."), "NSExecutableLinkError");
3170 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableLinkError");
3173 desc
= CFStringCreateWithFormat(allocator
, NULL
, descFormat
, name
);
3174 CFRelease(descFormat
);
3179 userInfoKeys
[numKeys
] = CFSTR("NSBundlePath");
3180 userInfoValues
[numKeys
] = bundlePath
;
3183 if (executablePath
) {
3184 userInfoKeys
[numKeys
] = CFSTR("NSFilePath");
3185 userInfoValues
[numKeys
] = executablePath
;
3189 userInfoKeys
[numKeys
] = kCFErrorLocalizedDescriptionKey
;
3190 userInfoValues
[numKeys
] = desc
;
3194 userInfoKeys
[numKeys
] = kCFErrorLocalizedFailureReasonKey
;
3195 userInfoValues
[numKeys
] = reason
;
3199 userInfoKeys
[numKeys
] = kCFErrorLocalizedRecoverySuggestionKey
;
3200 userInfoValues
[numKeys
] = suggestion
;
3204 userInfoKeys
[numKeys
] = CFSTR("NSDebugDescription");
3205 userInfoValues
[numKeys
] = debugString
;
3208 error
= CFErrorCreateWithUserInfoKeysAndValues(allocator
, kCFErrorDomainCocoa
, code
, userInfoKeys
, userInfoValues
, numKeys
);
3209 if (bundleURL
) CFRelease(bundleURL
);
3210 if (absoluteURL
) CFRelease(absoluteURL
);
3211 if (executableURL
) CFRelease(executableURL
);
3212 if (bundlePath
) CFRelease(bundlePath
);
3213 if (executablePath
) CFRelease(executablePath
);
3214 if (desc
) CFRelease(desc
);
3215 if (reason
) CFRelease(reason
);
3216 if (suggestion
) CFRelease(suggestion
);
3220 CFErrorRef
_CFBundleCreateError(CFAllocatorRef allocator
, CFBundleRef bundle
, CFIndex code
) {
3221 allocator
= _CFConvertAllocatorToNonGCRefZeroEquivalent(allocator
);
3222 return _CFBundleCreateErrorDebug(allocator
, bundle
, code
, NULL
);
3225 Boolean
_CFBundleLoadExecutableAndReturnError(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
3226 Boolean result
= false;
3227 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
3228 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3230 __CFSpinLock(&(bundle
->_bundleLoadingLock
));
3231 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
3232 // make sure we know whether bundle is already loaded or not
3233 #if defined(BINARY_SUPPORT_DLFCN)
3234 if (!bundle
->_isLoaded
) _CFBundleDlfcnCheckLoaded(bundle
);
3235 #elif defined(BINARY_SUPPORT_DYLD)
3236 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
3237 #endif /* BINARY_SUPPORT_DLFCN */
3238 #if defined(BINARY_SUPPORT_DYLD)
3239 // We might need to figure out what it is
3240 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
3241 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
3242 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
3244 #endif /* BINARY_SUPPORT_DYLD */
3245 if (executableURL
) CFRelease(executableURL
);
3247 if (bundle
->_isLoaded
) {
3248 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3249 // Remove from the scheduled unload set if we are there.
3250 __CFSpinLock(&CFBundleGlobalDataLock
);
3251 #if defined(AVOID_WEAK_COLLECTIONS)
3252 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
3253 #else /* AVOID_WEAK_COLLECTIONS */
3254 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
3255 #endif /* AVOID_WEAK_COLLECTIONS */
3256 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3260 // Unload bundles scheduled for unloading
3261 if (!_scheduledBundlesAreUnloading
) {
3262 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3263 _CFBundleUnloadScheduledBundles();
3264 __CFSpinLock(&(bundle
->_bundleLoadingLock
));
3267 if (bundle
->_isLoaded
) {
3268 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3269 // Remove from the scheduled unload set if we are there.
3270 __CFSpinLock(&CFBundleGlobalDataLock
);
3271 #if defined(AVOID_WEAK_COLLECTIONS)
3272 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
3273 #else /* AVOID_WEAK_COLLECTIONS */
3274 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
3275 #endif /* AVOID_WEAK_COLLECTIONS */
3276 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3279 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3281 switch (bundle
->_binaryType
) {
3282 #if defined(BINARY_SUPPORT_DLFCN)
3283 case __CFBundleUnreadableBinary
:
3284 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
3286 #endif /* BINARY_SUPPORT_DLFCN */
3287 #if defined(BINARY_SUPPORT_DYLD)
3288 case __CFBundleDYLDBundleBinary
:
3289 #if defined(BINARY_SUPPORT_DLFCN)
3290 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
3291 #else /* BINARY_SUPPORT_DLFCN */
3292 result
= _CFBundleDYLDLoadBundle(bundle
, forceGlobal
, subError
);
3293 #endif /* BINARY_SUPPORT_DLFCN */
3295 case __CFBundleDYLDFrameworkBinary
:
3296 #if defined(BINARY_SUPPORT_DLFCN)
3297 result
= _CFBundleDlfcnLoadFramework(bundle
, subError
);
3298 #else /* BINARY_SUPPORT_DLFCN */
3299 result
= _CFBundleDYLDLoadFramework(bundle
, subError
);
3300 #endif /* BINARY_SUPPORT_DLFCN */
3302 case __CFBundleDYLDExecutableBinary
:
3304 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3306 CFLog(__kCFLogBundle
, CFSTR("Attempt to load executable of a type that cannot be dynamically loaded for %@"), bundle
);
3309 #endif /* BINARY_SUPPORT_DYLD */
3310 #if defined(BINARY_SUPPORT_DLFCN)
3311 case __CFBundleUnknownBinary
:
3312 case __CFBundleELFBinary
:
3313 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
3315 #endif /* BINARY_SUPPORT_DLFCN */
3316 #if defined(BINARY_SUPPORT_DLL)
3317 case __CFBundleDLLBinary
:
3318 result
= _CFBundleDLLLoad(bundle
, subError
);
3320 #endif /* BINARY_SUPPORT_DLL */
3321 case __CFBundleNoBinary
:
3323 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3325 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for %@"), bundle
);
3330 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3332 CFLog(__kCFLogBundle
, CFSTR("Cannot recognize type of executable for %@"), bundle
);
3336 if (result
&& bundle
->_plugInData
._isPlugIn
) _CFBundlePlugInLoaded(bundle
);
3337 if (!result
&& error
) *error
= localError
;
3341 Boolean
CFBundleLoadExecutableAndReturnError(CFBundleRef bundle
, CFErrorRef
*error
) {
3342 return _CFBundleLoadExecutableAndReturnError(bundle
, false, error
);
3345 Boolean
CFBundleLoadExecutable(CFBundleRef bundle
) {
3346 return _CFBundleLoadExecutableAndReturnError(bundle
, false, NULL
);
3349 Boolean
CFBundlePreflightExecutable(CFBundleRef bundle
, CFErrorRef
*error
) {
3350 Boolean result
= false;
3351 CFErrorRef localError
= NULL
;
3352 #if defined(BINARY_SUPPORT_DLFCN)
3353 CFErrorRef
*subError
= (error
? &localError
: NULL
);
3355 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3357 __CFSpinLock(&(bundle
->_bundleLoadingLock
));
3358 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
3359 // make sure we know whether bundle is already loaded or not
3360 #if defined(BINARY_SUPPORT_DLFCN)
3361 if (!bundle
->_isLoaded
) _CFBundleDlfcnCheckLoaded(bundle
);
3362 #elif defined(BINARY_SUPPORT_DYLD)
3363 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
3364 #endif /* BINARY_SUPPORT_DLFCN */
3365 #if defined(BINARY_SUPPORT_DYLD)
3366 // We might need to figure out what it is
3367 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
3368 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
3369 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
3371 #endif /* BINARY_SUPPORT_DYLD */
3372 if (executableURL
) CFRelease(executableURL
);
3374 if (bundle
->_isLoaded
) {
3375 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3378 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3380 switch (bundle
->_binaryType
) {
3381 #if defined(BINARY_SUPPORT_DLFCN)
3382 case __CFBundleUnreadableBinary
:
3383 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3385 #endif /* BINARY_SUPPORT_DLFCN */
3386 #if defined(BINARY_SUPPORT_DYLD)
3387 case __CFBundleDYLDBundleBinary
:
3389 #if defined(BINARY_SUPPORT_DLFCN)
3390 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3391 #endif /* BINARY_SUPPORT_DLFCN */
3393 case __CFBundleDYLDFrameworkBinary
:
3395 #if defined(BINARY_SUPPORT_DLFCN)
3396 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3397 #endif /* BINARY_SUPPORT_DLFCN */
3399 case __CFBundleDYLDExecutableBinary
:
3400 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3402 #endif /* BINARY_SUPPORT_DYLD */
3403 #if defined(BINARY_SUPPORT_DLFCN)
3404 case __CFBundleUnknownBinary
:
3405 case __CFBundleELFBinary
:
3406 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3408 #endif /* BINARY_SUPPORT_DLFCN */
3409 #if defined(BINARY_SUPPORT_DLL)
3410 case __CFBundleDLLBinary
:
3413 #endif /* BINARY_SUPPORT_DLL */
3414 case __CFBundleNoBinary
:
3415 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3418 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3421 if (!result
&& error
) *error
= localError
;
3425 CFArrayRef
CFBundleCopyExecutableArchitectures(CFBundleRef bundle
) {
3426 CFArrayRef result
= NULL
;
3427 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3428 if (executableURL
) {
3429 result
= _CFBundleCopyArchitecturesForExecutable(executableURL
);
3430 CFRelease(executableURL
);
3435 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
3436 static Boolean
_CFBundleGetObjCImageInfo(CFBundleRef bundle
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
3437 Boolean retval
= false;
3438 uint32_t localVersion
= 0, localFlags
= 0;
3439 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3440 if (executableURL
) {
3441 retval
= _CFBundleGetObjCImageInfoForExecutable(executableURL
, &localVersion
, &localFlags
);
3442 CFRelease(executableURL
);
3444 if (objcVersion
) *objcVersion
= localVersion
;
3445 if (objcFlags
) *objcFlags
= localFlags
;
3450 void CFBundleUnloadExecutable(CFBundleRef bundle
) {
3451 // First unload bundles scheduled for unloading (if that's not what we are already doing.)
3452 if (!_scheduledBundlesAreUnloading
) _CFBundleUnloadScheduledBundles();
3454 if (!bundle
->_isLoaded
) return;
3456 // Remove from the scheduled unload set if we are there.
3457 if (!_scheduledBundlesAreUnloading
) __CFSpinLock(&CFBundleGlobalDataLock
);
3458 #if defined(AVOID_WEAK_COLLECTIONS)
3459 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
3460 #else /* AVOID_WEAK_COLLECTIONS */
3461 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
3462 #endif /* AVOID_WEAK_COLLECTIONS */
3463 if (!_scheduledBundlesAreUnloading
) __CFSpinUnlock(&CFBundleGlobalDataLock
);
3465 // Give the plugIn code a chance to realize this...
3466 _CFPlugInWillUnload(bundle
);
3468 __CFSpinLock(&(bundle
->_bundleLoadingLock
));
3469 if (!bundle
->_isLoaded
) {
3470 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3473 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3475 switch (bundle
->_binaryType
) {
3476 #if defined(BINARY_SUPPORT_DYLD)
3477 case __CFBundleDYLDBundleBinary
:
3478 #if defined(BINARY_SUPPORT_DLFCN)
3479 if (bundle
->_handleCookie
) _CFBundleDlfcnUnload(bundle
);
3480 #else /* BINARY_SUPPORT_DLFCN */
3481 _CFBundleDYLDUnloadBundle(bundle
);
3482 #endif /* BINARY_SUPPORT_DLFCN */
3484 case __CFBundleDYLDFrameworkBinary
:
3485 #if defined(BINARY_SUPPORT_DLFCN)
3486 if (bundle
->_handleCookie
&& _CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard
)) _CFBundleDlfcnUnload(bundle
);
3487 #endif /* BINARY_SUPPORT_DLFCN */
3489 #endif /* BINARY_SUPPORT_DYLD */
3490 #if defined(BINARY_SUPPORT_DLL)
3491 case __CFBundleDLLBinary
:
3492 _CFBundleDLLUnload(bundle
);
3494 #endif /* BINARY_SUPPORT_DLL */
3496 #if defined(BINARY_SUPPORT_DLFCN)
3497 if (bundle
->_handleCookie
) _CFBundleDlfcnUnload(bundle
);
3498 #endif /* BINARY_SUPPORT_DLFCN */
3501 if (!bundle
->_isLoaded
&& bundle
->_glueDict
) {
3502 CFDictionaryApplyFunction(bundle
->_glueDict
, _CFBundleDeallocateGlue
, (void *)CFGetAllocator(bundle
));
3503 CFRelease(bundle
->_glueDict
);
3504 bundle
->_glueDict
= NULL
;
3508 #if defined(AVOID_WEAK_COLLECTIONS)
3510 __private_extern__
void _CFBundleScheduleForUnloading(CFBundleRef bundle
) {
3511 __CFSpinLock(&CFBundleGlobalDataLock
);
3512 if (!_bundlesToUnload
) {
3513 CFSetCallBacks nonRetainingCallbacks
= kCFTypeSetCallBacks
;
3514 nonRetainingCallbacks
.retain
= NULL
;
3515 nonRetainingCallbacks
.release
= NULL
;
3516 _bundlesToUnload
= CFSetCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingCallbacks
);
3518 CFSetAddValue(_bundlesToUnload
, bundle
);
3519 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3522 __private_extern__
void _CFBundleUnscheduleForUnloading(CFBundleRef bundle
) {
3523 __CFSpinLock(&CFBundleGlobalDataLock
);
3524 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
3525 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3528 __private_extern__
void _CFBundleUnloadScheduledBundles(void) {
3529 __CFSpinLock(&CFBundleGlobalDataLock
);
3530 if (_bundlesToUnload
) {
3531 CFIndex i
, c
= CFSetGetCount(_bundlesToUnload
);
3533 CFBundleRef
*unloadThese
= (CFBundleRef
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(CFBundleRef
) * c
, 0);
3534 CFSetGetValues(_bundlesToUnload
, (const void **)unloadThese
);
3535 _scheduledBundlesAreUnloading
= true;
3536 for (i
= 0; i
< c
; i
++) {
3537 // This will cause them to be removed from the set. (Which is why we copied all the values out of the set up front.)
3538 CFBundleUnloadExecutable(unloadThese
[i
]);
3540 _scheduledBundlesAreUnloading
= false;
3541 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, unloadThese
);
3544 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3547 #else /* AVOID_WEAK_COLLECTIONS */
3549 __private_extern__
void _CFBundleScheduleForUnloading(CFBundleRef bundle
) {
3550 __CFSpinLock(&CFBundleGlobalDataLock
);
3551 if (!_bundlesToUnload
) _bundlesToUnload
= [[__CFHashTable alloc
] initWithOptions
:CFPointerFunctionsZeroingWeakMemory capacity
:0];
3552 [_bundlesToUnload addObject
:(id
)bundle
];
3553 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3556 __private_extern__
void _CFBundleUnscheduleForUnloading(CFBundleRef bundle
) {
3557 __CFSpinLock(&CFBundleGlobalDataLock
);
3558 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
3559 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3562 __private_extern__
void _CFBundleUnloadScheduledBundles(void) {
3563 __CFSpinLock(&CFBundleGlobalDataLock
);
3564 if (_bundlesToUnload
&& [_bundlesToUnload count
] > 0) {
3566 CFMutableArrayRef unloadThese
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3567 for (id value in _bundlesToUnload
) CFArrayAppendValue(unloadThese
, value
);
3568 c
= CFArrayGetCount(unloadThese
);
3570 _scheduledBundlesAreUnloading
= true;
3571 for (i
= 0; i
< c
; i
++) {
3572 // This will cause them to be removed from the set. (Which is why we copied all the values out of the set up front.)
3573 CFBundleUnloadExecutable((CFBundleRef
)CFArrayGetValueAtIndex(unloadThese
, i
));
3575 _scheduledBundlesAreUnloading
= false;
3577 CFRelease(unloadThese
);
3579 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3582 #endif /* AVOID_WEAK_COLLECTIONS */
3584 void *CFBundleGetFunctionPointerForName(CFBundleRef bundle
, CFStringRef funcName
) {
3586 // Load if necessary
3587 if (!bundle
->_isLoaded
) {
3588 if (!CFBundleLoadExecutable(bundle
)) return NULL
;
3591 switch (bundle
->_binaryType
) {
3592 #if defined(BINARY_SUPPORT_DYLD)
3593 case __CFBundleDYLDBundleBinary
:
3594 case __CFBundleDYLDFrameworkBinary
:
3595 case __CFBundleDYLDExecutableBinary
:
3596 #if defined(BINARY_SUPPORT_DLFCN)
3597 if (bundle
->_handleCookie
) return _CFBundleDlfcnGetSymbolByName(bundle
, funcName
);
3598 #else /* BINARY_SUPPORT_DLFCN */
3599 return _CFBundleDYLDGetSymbolByName(bundle
, funcName
);
3600 #endif /* BINARY_SUPPORT_DLFCN */
3602 #endif /* BINARY_SUPPORT_DYLD */
3603 #if defined(BINARY_SUPPORT_DLL)
3604 case __CFBundleDLLBinary
:
3605 tvp
= _CFBundleDLLGetSymbolByName(bundle
, funcName
);
3607 #endif /* BINARY_SUPPORT_DLL */
3609 #if defined(BINARY_SUPPORT_DLFCN)
3610 if (bundle
->_handleCookie
) return _CFBundleDlfcnGetSymbolByName(bundle
, funcName
);
3611 #endif /* BINARY_SUPPORT_DLFCN */
3617 void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle
, CFStringRef funcName
) {
3619 // Load if necessary
3620 if (!bundle
->_isLoaded
) {
3621 if (!CFBundleLoadExecutable(bundle
)) return NULL
;
3623 #if defined (BINARY_SUPPORT_DYLD) || defined (BINARY_SUPPORT_DLFCN)
3624 switch (bundle
->_binaryType
) {
3625 #if defined(BINARY_SUPPORT_DYLD)
3626 case __CFBundleDYLDBundleBinary
:
3627 case __CFBundleDYLDFrameworkBinary
:
3628 case __CFBundleDYLDExecutableBinary
:
3629 #if defined(BINARY_SUPPORT_DLFCN)
3630 if (bundle
->_handleCookie
) fp
= _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, funcName
, true);
3631 #else /* BINARY_SUPPORT_DLFCN */
3632 fp
= _CFBundleDYLDGetSymbolByNameWithSearch(bundle
, funcName
, true);
3633 #endif /* BINARY_SUPPORT_DLFCN */
3635 #endif /* BINARY_SUPPORT_DYLD */
3637 #if defined(BINARY_SUPPORT_DLFCN)
3638 if (bundle
->_handleCookie
) fp
= _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, funcName
, true);
3639 #endif /* BINARY_SUPPORT_DLFCN */
3642 #endif /* BINARY_SUPPORT_DYLD || BINARY_SUPPORT_DLFCN */
3646 void CFBundleGetFunctionPointersForNames(CFBundleRef bundle
, CFArrayRef functionNames
, void *ftbl
[]) {
3651 c
= CFArrayGetCount(functionNames
);
3652 for (i
= 0; i
< c
; i
++) ftbl
[i
] = CFBundleGetFunctionPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(functionNames
, i
));
3655 void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle
, CFArrayRef functionNames
, void *ftbl
[]) {
3660 c
= CFArrayGetCount(functionNames
);
3661 for (i
= 0; i
< c
; i
++) ftbl
[i
] = _CFBundleGetCFMFunctionPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(functionNames
, i
));
3664 void *CFBundleGetDataPointerForName(CFBundleRef bundle
, CFStringRef symbolName
) {
3666 // Load if necessary
3667 if (!bundle
->_isLoaded
&& !CFBundleLoadExecutable(bundle
)) return NULL
;
3669 switch (bundle
->_binaryType
) {
3670 #if defined(BINARY_SUPPORT_DYLD)
3671 case __CFBundleDYLDBundleBinary
:
3672 case __CFBundleDYLDFrameworkBinary
:
3673 case __CFBundleDYLDExecutableBinary
:
3674 #if defined(BINARY_SUPPORT_DLFCN)
3675 if (bundle
->_handleCookie
) dp
= _CFBundleDlfcnGetSymbolByName(bundle
, symbolName
);
3676 #else /* BINARY_SUPPORT_DLFCN */
3677 dp
= _CFBundleDYLDGetSymbolByName(bundle
, symbolName
);
3678 #endif /* BINARY_SUPPORT_DLFCN */
3680 #endif /* BINARY_SUPPORT_DYLD */
3681 #if defined(BINARY_SUPPORT_DLL)
3682 case __CFBundleDLLBinary
:
3683 /* MF:!!! Handle this someday */
3685 #endif /* BINARY_SUPPORT_DLL */
3687 #if defined(BINARY_SUPPORT_DLFCN)
3688 if (bundle
->_handleCookie
) dp
= _CFBundleDlfcnGetSymbolByName(bundle
, symbolName
);
3689 #endif /* BINARY_SUPPORT_DLFCN */
3695 void CFBundleGetDataPointersForNames(CFBundleRef bundle
, CFArrayRef symbolNames
, void *stbl
[]) {
3700 c
= CFArrayGetCount(symbolNames
);
3701 for (i
= 0; i
< c
; i
++) stbl
[i
] = CFBundleGetDataPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(symbolNames
, i
));
3704 __private_extern__ _CFResourceData
*__CFBundleGetResourceData(CFBundleRef bundle
) {
3705 return &(bundle
->_resourceData
);
3708 CFPlugInRef
CFBundleGetPlugIn(CFBundleRef bundle
) {
3709 return (bundle
->_plugInData
._isPlugIn
) ? (CFPlugInRef
)bundle
: NULL
;
3712 __private_extern__ _CFPlugInData
*__CFBundleGetPlugInData(CFBundleRef bundle
) {
3713 return &(bundle
->_plugInData
);
3716 __private_extern__ Boolean
_CFBundleCouldBeBundle(CFURLRef url
) {
3717 Boolean result
= false;
3720 if (_CFGetFileProperties(kCFAllocatorSystemDefault
, url
, &exists
, &mode
, NULL
, NULL
, NULL
, NULL
) == 0) result
= (exists
&& (mode
& S_IFMT
) == S_IFDIR
&& (mode
& 0444) != 0);
3724 #define LENGTH_OF(A) (sizeof(A) / sizeof(A[0]))
3726 //If 'permissive' is set, we will maintain the historical behavior of returning frameworks with names that don't match, and frameworks for executables in Resources/
3727 static CFURLRef
__CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath
, Boolean permissive
) {
3728 // 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.
3729 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
3730 #elif 0 && DEPLOYMENT_TARGET_WINDOWS
3731 UniChar executablesToFrameworksPathBuff
[] = {'.', '.', '\\', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
3732 UniChar executablesToPrivateFrameworksPathBuff
[] = {'.', '.', '\\', 'P', 'r', 'i', 'v', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
3733 UniChar executablesToSystemFrameworksPathBuff
[MAX_PATH
+1] = { 0 };
3734 SHGetFolderPathAndSubDirW(NULL
, CSIDL_PROGRAM_FILES_COMMON
, NULL
, 0 /* SHGFP_TYPE_CURRENT */, L
"Apple\\Mobile Device Support\\Frameworks", executablesToSystemFrameworksPathBuff
);
3735 UniChar frameworksExtension
[] = {'f', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k'};
3736 #elif DEPLOYMENT_TARGET_WINDOWS
3737 UniChar executablesToFrameworksPathBuff
[] = {'.', '.', '\\', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
3738 UniChar executablesToPrivateFrameworksPathBuff
[] = {'.', '.', '\\', 'P', 'r', 'i', 'v', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
3739 UniChar frameworksExtension
[] = {'f', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k'};
3741 #error Unknown or unspecified DEPLOYMENT_TARGET
3743 UniChar pathBuff
[CFMaxPathSize
] = {0};
3744 UniChar nameBuff
[CFMaxPathSize
] = {0};
3745 CFIndex length
, nameStart
, nameLength
, savedLength
;
3746 CFMutableStringRef cheapStr
= CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault
, NULL
, 0, 0, NULL
);
3747 CFURLRef bundleURL
= NULL
;
3749 length
= CFStringGetLength(executablePath
);
3750 if (length
> CFMaxPathSize
) length
= CFMaxPathSize
;
3751 CFStringGetCharacters(executablePath
, CFRangeMake(0, length
), pathBuff
);
3753 // Save the name in nameBuff
3754 length
= _CFLengthAfterDeletingPathExtension(pathBuff
, length
);
3755 nameStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3756 nameLength
= length
- nameStart
;
3757 memmove(nameBuff
, &(pathBuff
[nameStart
]), nameLength
* sizeof(UniChar
));
3759 // Strip the name from pathBuff
3760 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3761 savedLength
= length
;
3763 #if DEPLOYMENT_TARGET_WINDOWS
3764 // * (Windows-only) First check the "Executables" directory parallel to the "Frameworks" directory case.
3765 if (_CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, executablesToFrameworksPathBuff
, LENGTH_OF(executablesToFrameworksPathBuff
)) && _CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, nameBuff
, nameLength
) && _CFAppendPathExtension(pathBuff
, &length
, CFMaxPathSize
, frameworksExtension
, LENGTH_OF(frameworksExtension
))) {
3766 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3767 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3768 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3769 CFRelease(bundleURL
);
3773 // * (Windows-only) Next check the "Executables" directory parallel to the "PrivateFrameworks" directory case.
3775 length
= savedLength
;
3776 if (_CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, executablesToPrivateFrameworksPathBuff
, LENGTH_OF(executablesToPrivateFrameworksPathBuff
)) && _CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, nameBuff
, nameLength
) && _CFAppendPathExtension(pathBuff
, &length
, CFMaxPathSize
, frameworksExtension
, LENGTH_OF(frameworksExtension
))) {
3777 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3778 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3779 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3780 CFRelease(bundleURL
);
3786 #elif 0 && DEPLOYMENT_TARGET_WINDOWS
3787 // * (Windows-only) First check the "Executables" directory parallel to the "Frameworks" directory case.
3788 if (_CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, executablesToFrameworksPathBuff
, LENGTH_OF(executablesToFrameworksPathBuff
)) && _CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, nameBuff
, nameLength
) && _CFAppendPathExtension(pathBuff
, &length
, CFMaxPathSize
, frameworksExtension
, LENGTH_OF(frameworksExtension
))) {
3789 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3790 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3791 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3792 CFRelease(bundleURL
);
3796 // * (Windows-only) Next check the "Executables" directory parallel to the "PrivateFrameworks" directory case.
3798 length
= savedLength
;
3799 if (_CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, executablesToPrivateFrameworksPathBuff
, LENGTH_OF(executablesToPrivateFrameworksPathBuff
)) && _CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, nameBuff
, nameLength
) && _CFAppendPathExtension(pathBuff
, &length
, CFMaxPathSize
, frameworksExtension
, LENGTH_OF(frameworksExtension
))) {
3800 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3801 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3802 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3803 CFRelease(bundleURL
);
3808 // * (Windows-only) Next check the \Program Files\Apple\Mobile Device Support\Frameworks directory
3811 if (_CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, executablesToSystemFrameworksPathBuff
, wcslen(executablesToSystemFrameworksPathBuff
)) && _CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, nameBuff
, nameLength
) && _CFAppendPathExtension(pathBuff
, &length
, CFMaxPathSize
, frameworksExtension
, LENGTH_OF(frameworksExtension
))) {
3812 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3813 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3814 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3815 CFRelease(bundleURL
);
3820 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
3822 #error Unknown or unspecified DEPLOYMENT_TARGET
3824 // * Finally check the executable inside the framework case.
3826 length
= savedLength
;
3827 // To catch all the cases, we just peel off level looking for one ending in .framework or one called "Supporting Files".
3829 CFStringRef name
= permissive
? CFSTR("") : CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, (const char *)nameBuff
);
3831 while (length
> 0) {
3832 CFIndex curStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3833 if (curStart
>= length
) break;
3834 CFStringSetExternalCharactersNoCopy(cheapStr
, &(pathBuff
[curStart
]), length
- curStart
, CFMaxPathSize
- curStart
);
3835 if (!permissive
&& CFEqual(cheapStr
, _CFBundleResourcesDirectoryName
)) break;
3836 if (CFEqual(cheapStr
, _CFBundleSupportFilesDirectoryName1
) || CFEqual(cheapStr
, _CFBundleSupportFilesDirectoryName2
)) {
3838 CFIndex fmwkStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3839 CFStringSetExternalCharactersNoCopy(cheapStr
, &(pathBuff
[fmwkStart
]), length
- fmwkStart
, CFMaxPathSize
- fmwkStart
);
3841 if (permissive
|| CFStringHasPrefix(cheapStr
, name
)) {
3842 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3843 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3845 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3846 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3847 CFRelease(bundleURL
);
3852 } else if (CFStringHasSuffix(cheapStr
, CFSTR(".framework")) && (permissive
|| CFStringHasPrefix(cheapStr
, name
))) {
3853 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3854 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3855 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3856 CFRelease(bundleURL
);
3861 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3863 if (!permissive
) CFRelease(name
);
3865 CFStringSetExternalCharactersNoCopy(cheapStr
, NULL
, 0, 0);
3866 CFRelease(cheapStr
);
3871 //SPI version; separated out to minimize linkage changes
3872 CFURLRef
_CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath
) {
3873 return __CFBundleCopyFrameworkURLForExecutablePath(executablePath
, false);
3876 static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath
) {
3877 // This finds the bundle for the given path.
3878 // 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.
3880 CFURLRef curURL
= __CFBundleCopyFrameworkURLForExecutablePath(imagePath
, true);
3881 Boolean createdBundle
= false;
3884 bundle
= _CFBundleCopyBundleForURL(curURL
, true);
3886 // Ensure bundle exists by creating it if necessary
3887 // NB doFinalProcessing must be false here, see below
3888 bundle
= _CFBundleCreate(kCFAllocatorSystemDefault
, curURL
, true, false);
3889 createdBundle
= true;
3892 __CFSpinLock(&(bundle
->_bundleLoadingLock
));
3893 if (!bundle
->_isLoaded
) {
3894 // 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)
3895 #if defined(BINARY_SUPPORT_DLFCN)
3896 if (!bundle
->_isLoaded
) _CFBundleDlfcnCheckLoaded(bundle
);
3897 #elif defined(BINARY_SUPPORT_DYLD)
3898 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
3899 #endif /* BINARY_SUPPORT_DLFCN */
3900 #if defined(BINARY_SUPPORT_DYLD)
3901 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= __CFBundleDYLDFrameworkBinary
;
3902 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
3903 #endif /* BINARY_SUPPORT_DYLD */
3905 if (!bundle
->_isLoaded
) printf("ensure bundle %p set loaded fallback, handle %p image %p conn %p\n", bundle
, bundle
->_handleCookie
, bundle
->_imageCookie
, bundle
->_connectionCookie
);
3906 #endif /* LOG_BUNDLE_LOAD */
3907 bundle
->_isLoaded
= true;
3909 __CFSpinUnlock(&(bundle
->_bundleLoadingLock
));
3910 if (createdBundle
) {
3911 // Perform delayed final processing steps.
3912 // This must be done after _isLoaded has been set, for security reasons (3624341).
3913 _CFBundleCheckWorkarounds(bundle
);
3914 if (_CFBundleNeedsInitPlugIn(bundle
)) {
3915 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3916 _CFBundleInitPlugIn(bundle
);
3917 __CFSpinLock(&CFBundleGlobalDataLock
);
3920 // Release the bundle if we did not create it here
3928 static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths
) {
3929 // This finds the bundles for the given paths.
3930 // 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).
3931 CFIndex i
, imagePathCount
= CFArrayGetCount(imagePaths
);
3932 for (i
= 0; i
< imagePathCount
; i
++) _CFBundleEnsureBundleExistsForImagePath((CFStringRef
)CFArrayGetValueAtIndex(imagePaths
, i
));
3935 static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint
) {
3936 CFArrayRef imagePaths
= NULL
;
3937 // Tickle the main bundle into existence
3938 (void)_CFBundleGetMainBundleAlreadyLocked();
3939 #if defined(BINARY_SUPPORT_DYLD)
3940 imagePaths
= _CFBundleDYLDCopyLoadedImagePathsForHint(hint
);
3941 #endif /* BINARY_SUPPORT_DYLD */
3943 _CFBundleEnsureBundlesExistForImagePaths(imagePaths
);
3944 CFRelease(imagePaths
);
3948 static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void) {
3949 // 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.
3950 CFArrayRef imagePaths
= NULL
;
3951 // Tickle the main bundle into existence
3952 (void)_CFBundleGetMainBundleAlreadyLocked();
3954 #if defined(BINARY_SUPPORT_DLL)
3955 // Dont know how to find static bundles for DLLs
3956 #endif /* BINARY_SUPPORT_DLL */
3958 #if defined(BINARY_SUPPORT_DYLD)
3959 imagePaths
= _CFBundleDYLDCopyLoadedImagePathsIfChanged();
3960 #endif /* BINARY_SUPPORT_DYLD */
3962 _CFBundleEnsureBundlesExistForImagePaths(imagePaths
);
3963 CFRelease(imagePaths
);
3967 CFArrayRef
CFBundleGetAllBundles(void) {
3968 // To answer this properly, we have to have created the static bundles!
3969 #if !defined(AVOID_WEAK_COLLECTIONS)
3970 static CFMutableArrayRef externalAllBundles
= NULL
;
3971 #endif /* AVOID_WEAK_COLLECTIONS */
3973 __CFSpinLock(&CFBundleGlobalDataLock
);
3974 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
3975 #if defined(AVOID_WEAK_COLLECTIONS)
3976 bundles
= _allBundles
;
3977 #else /* AVOID_WEAK_COLLECTIONS */
3978 if (!externalAllBundles
) {
3979 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
3980 nonRetainingArrayCallbacks
.retain
= NULL
;
3981 nonRetainingArrayCallbacks
.release
= NULL
;
3982 externalAllBundles
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
3984 CFArrayRemoveAllValues(externalAllBundles
);
3985 for (id value in _allBundles
) CFArrayAppendValue(externalAllBundles
, value
);
3986 bundles
= externalAllBundles
;
3987 #endif /* AVOID_WEAK_COLLECTIONS */
3988 __CFSpinUnlock(&CFBundleGlobalDataLock
);
3992 CF_EXPORT CFArrayRef
_CFBundleCopyAllBundles(void) {
3993 // To answer this properly, we have to have created the static bundles!
3994 __CFSpinLock(&CFBundleGlobalDataLock
);
3995 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
3996 #if defined(AVOID_WEAK_COLLECTIONS)
3997 CFArrayRef bundles
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, _allBundles
);
3998 #else /* AVOID_WEAK_COLLECTIONS */
3999 CFMutableArrayRef bundles
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
4000 for (id value in _allBundles
) CFArrayAppendValue(bundles
, value
);
4001 #endif /* AVOID_WEAK_COLLECTIONS */
4002 __CFSpinUnlock(&CFBundleGlobalDataLock
);
4006 uint8_t _CFBundleLayoutVersion(CFBundleRef bundle
) {
4007 return bundle
->_version
;
4010 CF_EXPORT CFURLRef
_CFBundleCopyInfoPlistURL(CFBundleRef bundle
) {
4011 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
4012 CFURLRef url
= (CFURLRef
)CFDictionaryGetValue(infoDict
, _kCFBundleInfoPlistURLKey
);
4013 if (!url
) url
= (CFURLRef
)CFDictionaryGetValue(infoDict
, _kCFBundleRawInfoPlistURLKey
);
4014 return (url
? (CFURLRef
)CFRetain(url
) : NULL
);
4017 CF_EXPORT CFURLRef
_CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle
) {
4018 return CFBundleCopyPrivateFrameworksURL(bundle
);
4021 CF_EXPORT CFURLRef
CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle
) {
4022 CFURLRef result
= NULL
;
4024 if (1 == bundle
->_version
) {
4025 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase1
, bundle
->_url
);
4026 } else if (2 == bundle
->_version
) {
4027 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase2
, bundle
->_url
);
4029 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase0
, bundle
->_url
);
4034 CF_EXPORT CFURLRef
_CFBundleCopySharedFrameworksURL(CFBundleRef bundle
) {
4035 return CFBundleCopySharedFrameworksURL(bundle
);
4038 CF_EXPORT CFURLRef
CFBundleCopySharedFrameworksURL(CFBundleRef bundle
) {
4039 CFURLRef result
= NULL
;
4041 if (1 == bundle
->_version
) {
4042 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase1
, bundle
->_url
);
4043 } else if (2 == bundle
->_version
) {
4044 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase2
, bundle
->_url
);
4046 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase0
, bundle
->_url
);
4051 CF_EXPORT CFURLRef
_CFBundleCopySharedSupportURL(CFBundleRef bundle
) {
4052 return CFBundleCopySharedSupportURL(bundle
);
4055 CF_EXPORT CFURLRef
CFBundleCopySharedSupportURL(CFBundleRef bundle
) {
4056 CFURLRef result
= NULL
;
4058 if (1 == bundle
->_version
) {
4059 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase1
, bundle
->_url
);
4060 } else if (2 == bundle
->_version
) {
4061 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase2
, bundle
->_url
);
4063 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase0
, bundle
->_url
);
4068 __private_extern__ CFURLRef
_CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle
) {
4069 return CFBundleCopyBuiltInPlugInsURL(bundle
);
4072 CF_EXPORT CFURLRef
CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle
) {
4073 CFURLRef result
= NULL
, alternateResult
= NULL
;
4075 CFAllocatorRef alloc
= CFGetAllocator(bundle
);
4076 if (1 == bundle
->_version
) {
4077 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase1
, bundle
->_url
);
4078 } else if (2 == bundle
->_version
) {
4079 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase2
, bundle
->_url
);
4081 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase0
, bundle
->_url
);
4083 if (!result
|| !_urlExists(result
)) {
4084 if (1 == bundle
->_version
) {
4085 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase1
, bundle
->_url
);
4086 } else if (2 == bundle
->_version
) {
4087 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase2
, bundle
->_url
);
4089 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase0
, bundle
->_url
);
4091 if (alternateResult
&& _urlExists(alternateResult
)) {
4092 if (result
) CFRelease(result
);
4093 result
= alternateResult
;
4095 if (alternateResult
) CFRelease(alternateResult
);
4101 #if defined(BINARY_SUPPORT_DYLD)
4103 __private_extern__ CFArrayRef
_CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint
) {
4104 uint32_t i
, numImages
= _dyld_image_count();
4105 CFMutableArrayRef result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
4106 CFRange range
= CFRangeMake(0, CFStringGetLength(hint
)), altRange
= CFRangeMake(0, 0), testRange
= CFRangeMake(0, 0);
4107 const char *processPath
= _CFProcessPath();
4108 const void *mhp
= (const void *)_NSGetMachExecuteHeader();
4110 if (range
.length
> 14) {
4111 // handle some common variations on framework bundle identifiers
4112 if (CFStringFindWithOptions(hint
, CFSTR(".framework"), range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, &testRange
) && testRange
.location
> 0 && testRange
.length
> 0) {
4113 // identifier has .framework appended
4114 altRange
.length
= testRange
.location
;
4115 } else if (CFStringFindWithOptions(hint
, CFSTR("framework"), range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, &testRange
) && testRange
.location
> 0 && testRange
.length
> 0) {
4116 // identifier has Framework appended
4117 altRange
.length
= testRange
.location
;
4118 } else if (CFStringFindWithOptions(hint
, CFSTR("fw"), range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, &testRange
) && testRange
.location
> 0 && testRange
.length
> 0) {
4119 // identifier has FW appended
4120 altRange
.length
= testRange
.location
;
4123 for (i
= 0; i
< numImages
; i
++) {
4124 const char *curName
= _dyld_get_image_name(i
), *lastComponent
= NULL
;
4125 if (curName
&& (!processPath
|| 0 != strcmp(curName
, processPath
)) && mhp
!= (void *)_dyld_get_image_header(i
)) lastComponent
= strrchr(curName
, '/');
4126 if (lastComponent
) {
4127 CFStringRef str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, lastComponent
+ 1);
4129 if (CFStringFindWithOptions(hint
, str
, range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
) || (altRange
.length
> 0 && CFStringFindWithOptions(hint
, str
, altRange
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
))) {
4130 CFStringRef curStr
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, curName
);
4132 CFArrayAppendValue(result
, curStr
);
4143 static char *_cleanedPathForPath(const char *curName
) {
4144 char *thePath
= strdup(curName
);
4146 // We are going to process the buffer replacing all "/./" and "//" with "/"
4147 CFIndex srcIndex
= 0, dstIndex
= 0;
4148 CFIndex len
= strlen(thePath
);
4149 for (srcIndex
=0; srcIndex
<len
; srcIndex
++) {
4150 thePath
[dstIndex
] = thePath
[srcIndex
];
4152 while (srcIndex
< len
-1 && thePath
[srcIndex
] == '/' && (thePath
[srcIndex
+1] == '/' || (thePath
[srcIndex
+1] == '.' && srcIndex
< len
-2 && thePath
[srcIndex
+2] == '/'))) srcIndex
+= (thePath
[srcIndex
+1] == '/' ? 1 : 2);
4154 thePath
[dstIndex
] = 0;
4159 __private_extern__ CFArrayRef
_CFBundleDYLDCopyLoadedImagePathsIfChanged(void) {
4160 // 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.
4161 uint32_t i
, numImages
= _dyld_image_count();
4162 CFMutableArrayRef result
= NULL
;
4163 static uint32_t _cachedDYLDImageCount
= -1;
4165 if (numImages
!= _cachedDYLDImageCount
) {
4166 const char *curName
;
4167 char *cleanedCurName
= NULL
;
4169 const char *processPath
= _CFProcessPath();
4170 const void *mhp
= (const void *)_NSGetMachExecuteHeader();
4172 result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
4174 for (i
= 0; i
< numImages
; i
++) {
4175 curName
= _dyld_get_image_name(i
);
4176 if (curName
&& i
== 0) cleanedCurName
= _cleanedPathForPath(curName
);
4177 if (curName
&& (!processPath
|| 0 != strcmp(curName
, processPath
)) && (!processPath
|| !cleanedCurName
|| 0 != strcmp(cleanedCurName
, processPath
)) && mhp
!= (void *)_dyld_get_image_header(i
)) {
4178 curStr
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, curName
);
4180 CFArrayAppendValue(result
, curStr
);
4184 if (cleanedCurName
) {
4185 free(cleanedCurName
);
4186 cleanedCurName
= NULL
;
4189 _cachedDYLDImageCount
= numImages
;
4194 static CFStringRef
_CFBundleDYLDCopyLoadedImagePathForPointer(void *p
) {
4195 CFStringRef result
= NULL
;
4196 #if defined(USE_DYLD_PRIV)
4197 const char *name
= dyld_image_path_containing_address(p
);
4198 if (name
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, name
);
4199 #else /* USE_DYLD_PRIV */
4201 uint32_t i
, j
, n
= _dyld_image_count();
4202 Boolean foundit
= false;
4205 #define MACH_HEADER_TYPE struct mach_header_64
4206 #define MACH_SEGMENT_CMD_TYPE struct segment_command_64
4207 #define MACH_SEGMENT_FLAVOR LC_SEGMENT_64
4209 #define MACH_HEADER_TYPE struct mach_header
4210 #define MACH_SEGMENT_CMD_TYPE struct segment_command
4211 #define MACH_SEGMENT_FLAVOR LC_SEGMENT
4213 for (i
= 0; !foundit
&& i
< n
; i
++) {
4214 const MACH_HEADER_TYPE
*mh
= (const MACH_HEADER_TYPE
*)_dyld_get_image_header(i
);
4215 uintptr_t addr
= (uintptr_t)p
- _dyld_get_image_vmaddr_slide(i
);
4217 struct load_command
*lc
= (struct load_command
*)((char *)mh
+ sizeof(MACH_HEADER_TYPE
));
4218 for (j
= 0; !foundit
&& j
< mh
->ncmds
; j
++, lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
)) {
4219 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
) {
4221 name
= _dyld_get_image_name(i
);
4222 if (name
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, name
);
4227 #undef MACH_HEADER_TYPE
4228 #undef MACH_SEGMENT_CMD_TYPE
4229 #undef MACH_SEGMENT_FLAVOR
4231 #endif /* USE_DYLD_PRIV */
4233 printf("dyld image path for pointer %p is %p\n", p
, result
);
4234 #endif /* LOG_BUNDLE_LOAD */
4238 #if !defined(BINARY_SUPPORT_DLFCN)
4240 static const void *__CFBundleDYLDFindImage(char *buff
) {
4241 const void *header
= NULL
;
4242 uint32_t i
, numImages
= _dyld_image_count(), numMatches
= 0;
4243 const char *curName
, *p
, *q
;
4245 for (i
= 0; !header
&& i
< numImages
; i
++) {
4246 curName
= _dyld_get_image_name(i
);
4247 if (curName
&& 0 == strncmp(curName
, buff
, CFMaxPathSize
)) {
4248 header
= _dyld_get_image_header(i
);
4253 for (i
= 0; i
< numImages
; i
++) {
4254 curName
= _dyld_get_image_name(i
);
4256 for (p
= buff
, q
= curName
; *p
&& *q
&& (q
- curName
< CFMaxPathSize
); p
++, q
++) {
4257 if (*p
!= *q
&& (q
- curName
> 11) && 0 == strncmp(q
- 11, ".framework/Versions/", 20) && *(q
+ 9) && '/' == *(q
+ 10)) q
+= 11;
4258 else if (*p
!= *q
&& (q
- curName
> 12) && 0 == strncmp(q
- 12, ".framework/Versions/", 20) && *(q
+ 8) && '/' == *(q
+ 9)) q
+= 10;
4259 if (*p
!= *q
) break;
4262 header
= _dyld_get_image_header(i
);
4268 return (numMatches
== 1) ? header
: NULL
;
4271 __private_extern__ Boolean
_CFBundleDYLDCheckLoaded(CFBundleRef bundle
) {
4272 if (!bundle
->_isLoaded
) {
4273 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4274 char buff
[CFMaxPathSize
];
4276 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4277 const void *header
= __CFBundleDYLDFindImage(buff
);
4279 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= __CFBundleDYLDFrameworkBinary
;
4280 if (!bundle
->_imageCookie
) {
4281 bundle
->_imageCookie
= header
;
4283 printf("dyld check load bundle %p, find %s getting image %p\n", bundle
, buff
, bundle
->_imageCookie
);
4284 #endif /* LOG_BUNDLE_LOAD */
4286 bundle
->_isLoaded
= true;
4289 printf("dyld check load bundle %p, find %s no image\n", bundle
, buff
);
4290 #endif /* LOG_BUNDLE_LOAD */
4293 if (executableURL
) CFRelease(executableURL
);
4295 return bundle
->_isLoaded
;
4298 __private_extern__ Boolean
_CFBundleDYLDLoadBundle(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
4299 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4300 NSLinkEditErrors c
= NSLinkEditUndefinedError
;
4301 int errorNumber
= 0;
4302 const char *fileName
= NULL
;
4303 const char *errorString
= NULL
;
4305 if (!bundle
->_isLoaded
) {
4306 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4307 char buff
[CFMaxPathSize
];
4309 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4310 NSObjectFileImage image
;
4311 NSObjectFileImageReturnCode retCode
= NSCreateObjectFileImageFromFile(buff
, &image
);
4313 printf("dyld load bundle %p, create image of %s returns image %p retcode %d\n", bundle
, buff
, image
, retCode
);
4314 #endif /* LOG_BUNDLE_LOAD */
4315 if (retCode
== NSObjectFileImageSuccess
) {
4316 uint32_t options
= forceGlobal
? NSLINKMODULE_OPTION_RETURN_ON_ERROR
: (NSLINKMODULE_OPTION_BINDNOW
| NSLINKMODULE_OPTION_PRIVATE
| NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
4317 NSModule
module = NSLinkModule(image
, buff
, options
);
4319 printf("dyld load bundle %p, link module of %s options 0x%x returns module %p image %p\n", bundle
, buff
, options
, module, image
);
4320 #endif /* LOG_BUNDLE_LOAD */
4322 bundle
->_imageCookie
= image
;
4323 bundle
->_moduleCookie
= module;
4324 bundle
->_isLoaded
= true;
4326 NSLinkEditError(&c
, &errorNumber
, &fileName
, &errorString
);
4328 #if defined(BINARY_SUPPORT_DLFCN)
4329 _CFBundleDlfcnPreflight(bundle
, subError
);
4330 #endif /* BINARY_SUPPORT_DLFCN */
4332 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("error code %d, error number %d (%@)"), c
, errorNumber
, tempString
);
4333 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4334 if (tempString
) CFRelease(tempString
);
4335 if (debugString
) CFRelease(debugString
);
4338 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, fileName
);
4339 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString
, c
, errorNumber
, tempString
);
4340 if (tempString
) CFRelease(tempString
);
4341 if (executableString
) CFRelease(executableString
);
4343 (void)NSDestroyObjectFileImage(image
);
4347 if (retCode
== NSObjectFileImageArch
) {
4348 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableArchitectureMismatchError
);
4349 } else if (retCode
== NSObjectFileImageInappropriateFile
) {
4350 Boolean hasRuntimeMismatch
= false;
4351 uint32_t mainFlags
= 0, bundleFlags
= 0;
4352 if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL
, &mainFlags
) && (mainFlags
& 0x2) != 0) {
4353 if (_CFBundleGetObjCImageInfo(bundle
, NULL
, &bundleFlags
) && (bundleFlags
& 0x2) == 0) hasRuntimeMismatch
= true;
4355 if (hasRuntimeMismatch
) {
4356 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableRuntimeMismatchError
);
4358 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
4361 #if defined(BINARY_SUPPORT_DLFCN)
4362 _CFBundleDlfcnPreflight(bundle
, subError
);
4363 #endif /* BINARY_SUPPORT_DLFCN */
4365 CFStringRef debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("dyld returns %d"), retCode
);
4366 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4367 CFRelease(debugString
);
4371 CFLog(__kCFLogBundle
, CFSTR("dyld returns %d when trying to load %@"), retCode
, executableURL
);
4376 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4378 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4381 if (executableURL
) CFRelease(executableURL
);
4383 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4384 return bundle
->_isLoaded
;
4387 __private_extern__ Boolean
_CFBundleDYLDLoadFramework(CFBundleRef bundle
, CFErrorRef
*error
) {
4388 // !!! Framework loading should be better. Can't unload frameworks.
4389 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4390 NSLinkEditErrors c
= NSLinkEditUndefinedError
;
4391 int errorNumber
= 0;
4392 const char *fileName
= NULL
;
4393 const char *errorString
= NULL
;
4395 if (!bundle
->_isLoaded
) {
4396 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4397 char buff
[CFMaxPathSize
];
4399 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4400 void *image
= (void *)NSAddImage(buff
, NSADDIMAGE_OPTION_RETURN_ON_ERROR
);
4402 printf("dyld load framework %p, add image of %s returns image %p\n", bundle
, buff
, image
);
4403 #endif /* LOG_BUNDLE_LOAD */
4405 bundle
->_imageCookie
= image
;
4406 bundle
->_isLoaded
= true;
4408 NSLinkEditError(&c
, &errorNumber
, &fileName
, &errorString
);
4410 #if defined(BINARY_SUPPORT_DLFCN)
4411 _CFBundleDlfcnPreflight(bundle
, subError
);
4412 #endif /* BINARY_SUPPORT_DLFCN */
4414 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("error code %d, error number %d (%@)"), c
, errorNumber
, tempString
);
4415 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4416 if (tempString
) CFRelease(tempString
);
4417 if (debugString
) CFRelease(debugString
);
4420 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, fileName
);
4421 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString
, c
, errorNumber
, tempString
);
4422 if (tempString
) CFRelease(tempString
);
4423 if (executableString
) CFRelease(executableString
);
4428 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4430 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4433 if (executableURL
) CFRelease(executableURL
);
4435 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4436 return bundle
->_isLoaded
;
4439 __private_extern__
void _CFBundleDYLDUnloadBundle(CFBundleRef bundle
) {
4440 if (bundle
->_isLoaded
) {
4442 printf("dyld unload bundle %p, handle %p module %p image %p\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
);
4443 #endif /* LOG_BUNDLE_LOAD */
4444 if (bundle
->_moduleCookie
&& !NSUnLinkModule((NSModule
)(bundle
->_moduleCookie
), NSUNLINKMODULE_OPTION_NONE
)) {
4445 CFLog(__kCFLogBundle
, CFSTR("Internal error unloading bundle %@"), bundle
);
4447 if (bundle
->_moduleCookie
&& bundle
->_imageCookie
) (void)NSDestroyObjectFileImage((NSObjectFileImage
)(bundle
->_imageCookie
));
4448 bundle
->_connectionCookie
= bundle
->_handleCookie
= NULL
;
4449 bundle
->_imageCookie
= bundle
->_moduleCookie
= NULL
;
4450 bundle
->_isLoaded
= false;
4455 __private_extern__
void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {
4456 return _CFBundleDYLDGetSymbolByNameWithSearch(bundle
, symbolName
, false);
4459 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
) {
4460 void *result
= NULL
;
4462 NSSymbol symbol
= NULL
;
4465 if (CFStringGetCString(symbolName
, &(buff
[1]), 1024, kCFStringEncodingUTF8
)) {
4466 if (bundle
->_moduleCookie
) {
4467 symbol
= NSLookupSymbolInModule((NSModule
)(bundle
->_moduleCookie
), buff
);
4468 } else if (bundle
->_imageCookie
) {
4469 symbol
= NSLookupSymbolInImage(bundle
->_imageCookie
, buff
, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
|NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
);
4471 if (!symbol
&& !bundle
->_moduleCookie
&& (!bundle
->_imageCookie
|| globalSearch
)) {
4472 char hintBuff
[1026];
4473 CFStringRef executableName
= _CFBundleCopyExecutableName(bundle
, NULL
, NULL
);
4475 if (executableName
) {
4476 if (!CFStringGetCString(executableName
, hintBuff
, 1024, kCFStringEncodingUTF8
)) hintBuff
[0] = '\0';
4477 CFRelease(executableName
);
4479 // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint()
4480 // are identical, except the first just returns a bool, so checking with the
4481 // Is function first just causes a redundant lookup.
4482 // This returns NULL on failure.
4483 symbol
= NSLookupAndBindSymbolWithHint(buff
, hintBuff
);
4485 if (symbol
) result
= NSAddressOfSymbol(symbol
);
4487 if (!result
) CFLog(__kCFLogBundle
, CFSTR("dyld cannot find symbol %@ in %@"), symbolName
, bundle
);
4490 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);
4491 #endif /* LOG_BUNDLE_LOAD */
4496 #endif /* !BINARY_SUPPORT_DLFCN */
4497 #endif /* BINARY_SUPPORT_DYLD */
4499 #if defined(BINARY_SUPPORT_DLFCN)
4501 __private_extern__ Boolean
_CFBundleDlfcnCheckLoaded(CFBundleRef bundle
) {
4502 if (!bundle
->_isLoaded
) {
4503 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4504 char buff
[CFMaxPathSize
];
4506 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4507 int mode
= RTLD_LAZY
| RTLD_LOCAL
| RTLD_NOLOAD
| RTLD_FIRST
;
4508 void *handle
= dlopen(buff
, mode
);
4510 if (!bundle
->_handleCookie
) {
4511 bundle
->_handleCookie
= handle
;
4513 printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x getting handle %p\n", bundle
, buff
, mode
, bundle
->_handleCookie
);
4514 #endif /* LOG_BUNDLE_LOAD */
4516 bundle
->_isLoaded
= true;
4519 printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x no handle\n", bundle
, buff
, mode
);
4520 #endif /* LOG_BUNDLE_LOAD */
4523 if (executableURL
) CFRelease(executableURL
);
4525 return bundle
->_isLoaded
;
4528 CF_EXPORT Boolean
_CFBundleDlfcnPreflight(CFBundleRef bundle
, CFErrorRef
*error
) {
4529 Boolean retval
= true;
4530 CFErrorRef localError
= NULL
;
4531 if (!bundle
->_isLoaded
) {
4532 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4533 char buff
[CFMaxPathSize
];
4536 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4537 retval
= dlopen_preflight(buff
);
4538 if (!retval
&& error
) {
4539 CFArrayRef archs
= CFBundleCopyExecutableArchitectures(bundle
);
4540 CFStringRef debugString
= NULL
;
4541 const char *errorString
= dlerror();
4542 if (errorString
&& strlen(errorString
) > 0) debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
4544 Boolean hasSuitableArch
= false, hasRuntimeMismatch
= false;
4545 CFIndex i
, count
= CFArrayGetCount(archs
);
4546 SInt32 arch
, curArch
= _CFBundleCurrentArchitecture();
4547 for (i
= 0; !hasSuitableArch
&& i
< count
; i
++) {
4548 if (CFNumberGetValue((CFNumberRef
)CFArrayGetValueAtIndex(archs
, i
), kCFNumberSInt32Type
, (void *)&arch
) && arch
== curArch
) hasSuitableArch
= true;
4550 #if defined(BINARY_SUPPORT_DYLD)
4551 if (hasSuitableArch
) {
4552 uint32_t mainFlags
= 0, bundleFlags
= 0;
4553 if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL
, &mainFlags
) && (mainFlags
& 0x2) != 0) {
4554 if (_CFBundleGetObjCImageInfo(bundle
, NULL
, &bundleFlags
) && (bundleFlags
& 0x2) == 0) hasRuntimeMismatch
= true;
4557 #endif /* BINARY_SUPPORT_DYLD */
4558 if (hasRuntimeMismatch
) {
4559 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableRuntimeMismatchError
, debugString
);
4560 } else if (!hasSuitableArch
) {
4561 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableArchitectureMismatchError
, debugString
);
4563 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLoadError
, debugString
);
4567 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLoadError
, debugString
);
4569 if (debugString
) CFRelease(debugString
);
4572 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4574 if (executableURL
) CFRelease(executableURL
);
4576 if (!retval
&& error
) *error
= localError
;
4580 __private_extern__ Boolean
_CFBundleDlfcnLoadBundle(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
4581 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4582 if (!bundle
->_isLoaded
) {
4583 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4584 char buff
[CFMaxPathSize
];
4585 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4586 int mode
= forceGlobal
? (RTLD_LAZY
| RTLD_GLOBAL
| RTLD_FIRST
) : (RTLD_NOW
| RTLD_LOCAL
| RTLD_FIRST
);
4587 void *cookie
= dlopen(buff
, mode
);
4589 printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle
, buff
, mode
, cookie
);
4590 #endif /* LOG_BUNDLE_LOAD */
4591 if (cookie
&& cookie
== bundle
->_handleCookie
) {
4592 // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose
4594 printf("dlfcn load bundle %p closing existing reference to handle %p\n", bundle
, cookie
);
4595 #endif /* LOG_BUNDLE_LOAD */
4596 dlclose(bundle
->_handleCookie
);
4598 bundle
->_handleCookie
= cookie
;
4599 if (bundle
->_handleCookie
) {
4600 bundle
->_isLoaded
= true;
4602 const char *errorString
= dlerror();
4604 _CFBundleDlfcnPreflight(bundle
, subError
);
4606 CFStringRef debugString
= errorString
? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
) : NULL
;
4607 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4608 if (debugString
) CFRelease(debugString
);
4611 CFStringRef executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, buff
);
4613 CFStringRef debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
4614 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: %@"), executableString
, debugString
);
4615 if (debugString
) CFRelease(debugString
);
4617 CFLog(__kCFLogBundle
, CFSTR("Error loading %@"), executableString
);
4619 if (executableString
) CFRelease(executableString
);
4624 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4626 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4629 if (executableURL
) CFRelease(executableURL
);
4631 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4632 return bundle
->_isLoaded
;
4635 __private_extern__ Boolean
_CFBundleDlfcnLoadFramework(CFBundleRef bundle
, CFErrorRef
*error
) {
4636 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4637 if (!bundle
->_isLoaded
) {
4638 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4639 char buff
[CFMaxPathSize
];
4640 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4641 int mode
= RTLD_LAZY
| RTLD_GLOBAL
| RTLD_FIRST
;
4642 void *cookie
= dlopen(buff
, mode
);
4644 printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle
, buff
, mode
, cookie
);
4645 #endif /* LOG_BUNDLE_LOAD */
4646 if (cookie
&& cookie
== bundle
->_handleCookie
) {
4647 // during the call to dlopen, arbitrary init routines may have run and caused bundle->_handleCookie to be set, in which case proper reference counting requires that reference to be released with dlclose
4649 printf("dlfcn load framework %p closing existing reference to handle %p\n", bundle
, cookie
);
4650 #endif /* LOG_BUNDLE_LOAD */
4651 dlclose(bundle
->_handleCookie
);
4653 bundle
->_handleCookie
= cookie
;
4654 if (bundle
->_handleCookie
) {
4655 bundle
->_isLoaded
= true;
4657 const char *errorString
= dlerror();
4659 _CFBundleDlfcnPreflight(bundle
, subError
);
4661 CFStringRef debugString
= errorString
? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
) : NULL
;
4662 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4663 if (debugString
) CFRelease(debugString
);
4666 CFStringRef executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, buff
);
4668 CFStringRef debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
4669 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: %@"), executableString
, debugString
);
4670 if (debugString
) CFRelease(debugString
);
4672 CFLog(__kCFLogBundle
, CFSTR("Error loading %@"), executableString
);
4674 if (executableString
) CFRelease(executableString
);
4679 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4681 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4684 if (executableURL
) CFRelease(executableURL
);
4686 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4687 return bundle
->_isLoaded
;
4690 __private_extern__
void _CFBundleDlfcnUnload(CFBundleRef bundle
) {
4691 if (bundle
->_isLoaded
) {
4693 printf("dlfcn unload bundle %p, handle %p module %p image %p\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
);
4694 #endif /* LOG_BUNDLE_LOAD */
4695 if (0 != dlclose(bundle
->_handleCookie
)) {
4696 CFLog(__kCFLogBundle
, CFSTR("Internal error unloading bundle %@"), bundle
);
4698 bundle
->_connectionCookie
= bundle
->_handleCookie
= NULL
;
4699 bundle
->_imageCookie
= bundle
->_moduleCookie
= NULL
;
4700 bundle
->_isLoaded
= false;
4705 __private_extern__
void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {
4706 return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, symbolName
, false);
4709 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
) {
4710 void *result
= NULL
;
4713 if (CFStringGetCString(symbolName
, buff
, 1024, kCFStringEncodingUTF8
)) {
4714 result
= dlsym(bundle
->_handleCookie
, buff
);
4715 if (!result
&& globalSearch
) result
= dlsym(RTLD_DEFAULT
, buff
);
4717 if (!result
) CFLog(__kCFLogBundle
, CFSTR("dlsym cannot find symbol %@ in %@"), symbolName
, bundle
);
4720 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
);
4721 #endif /* LOG_BUNDLE_LOAD */
4726 #if !defined(BINARY_SUPPORT_DYLD)
4728 static CFStringRef
_CFBundleDlfcnCopyLoadedImagePathForPointer(void *p
) {
4729 CFStringRef result
= NULL
;
4731 if (0 != dladdr(p
, &info
) && info
.dli_fname
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, info
.dli_fname
);
4733 printf("dlfcn image path for pointer %p is %p\n", p
, result
);
4734 #endif /* LOG_BUNDLE_LOAD */
4738 #endif /* !BINARY_SUPPORT_DYLD */
4739 #endif /* BINARY_SUPPORT_DLFCN */
4741 #if defined(BINARY_SUPPORT_DLL)
4743 __private_extern__ Boolean
_CFBundleDLLLoad(CFBundleRef bundle
, CFErrorRef
*error
) {
4744 CFErrorRef localError
= NULL
;
4745 if (!bundle
->_isLoaded
) {
4746 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4747 wchar_t buff
[CFMaxPathSize
];
4749 if (executableURL
&& _CFURLGetWideFileSystemRepresentation(executableURL
, true, (wchar_t *)buff
, CFMaxPathSize
)) {
4750 bundle
->_hModule
= LoadLibraryW(buff
);
4751 if (bundle
->_hModule
) {
4752 bundle
->_isLoaded
= true;
4755 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
);
4757 CFLog(__kCFLogBundle
, CFSTR("Failed to load bundle %@"), bundle
);
4762 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4764 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4767 if (executableURL
) CFRelease(executableURL
);
4769 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4770 return bundle
->_isLoaded
;
4773 __private_extern__
void _CFBundleDLLUnload(CFBundleRef bundle
) {
4774 if (bundle
->_isLoaded
) {
4775 FreeLibrary(bundle
->_hModule
);
4776 bundle
->_hModule
= NULL
;
4777 bundle
->_isLoaded
= false;
4781 __private_extern__
void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {
4782 void *result
= NULL
;
4784 if (CFStringGetCString(symbolName
, buff
, 1024, kCFStringEncodingWindowsLatin1
)) result
= GetProcAddress(bundle
->_hModule
, buff
);
4788 #endif /* BINARY_SUPPORT_DLL */
4790 /* Workarounds to be applied in the presence of certain bundles can go here. This is called on every bundle creation.
4792 CF_EXPORT
void _CFStringSetCompatibility(CFOptionFlags
);
4794 static void _CFBundleCheckWorkarounds(CFBundleRef bundle
) {