2 * Copyright (c) 2013 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-2013, Apple Inc. All rights reserved.
26 Responsibility: Tony Parker
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"
44 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
46 #error Unknown deployment target
49 #define AVOID_WEAK_COLLECTIONS 1
51 #if !AVOID_WEAK_COLLECTIONS
52 #include "CFHashTable.h"
53 #include "CFMapTable.h"
54 #include "CFPointerArray.h"
55 #endif /* !AVOID_WEAK_COLLECTIONS */
57 #if defined(BINARY_SUPPORT_DYLD)
58 // Import the mach-o headers that define the macho magic numbers
59 #include <mach-o/loader.h>
60 #include <mach-o/fat.h>
61 #include <mach-o/arch.h>
62 #include <mach-o/dyld.h>
63 #include <mach-o/getsect.h>
67 #include <crt_externs.h>
68 #if defined(USE_DYLD_PRIV)
69 #include <mach-o/dyld_priv.h>
70 #endif /* USE_DYLD_PRIV */
71 #endif /* BINARY_SUPPORT_DYLD */
73 #if defined(BINARY_SUPPORT_DLFCN)
75 #endif /* BINARY_SUPPORT_DLFCN */
77 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
79 #elif DEPLOYMENT_TARGET_WINDOWS
84 #define stat(x,y) _NS_stat(x,y)
88 #if DEPLOYMENT_TARGET_WINDOWS
89 #define statinfo _stat
91 // Windows isspace implementation limits the input chars to < 256 in the ASCII range. It will
92 // assert in debug builds. This is annoying. We merrily grok chars > 256.
93 static inline BOOL
isspace(char c
) {
94 return (c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r'|| c
== '\v' || c
== '\f');
101 static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle
, Boolean alreadyLocked
);
103 #define LOG_BUNDLE_LOAD 0
105 // Public CFBundle Info plist keys
106 CONST_STRING_DECL(kCFBundleInfoDictionaryVersionKey
, "CFBundleInfoDictionaryVersion")
107 CONST_STRING_DECL(kCFBundleExecutableKey
, "CFBundleExecutable")
108 CONST_STRING_DECL(kCFBundleIdentifierKey
, "CFBundleIdentifier")
109 CONST_STRING_DECL(kCFBundleVersionKey
, "CFBundleVersion")
110 CONST_STRING_DECL(kCFBundleDevelopmentRegionKey
, "CFBundleDevelopmentRegion")
111 CONST_STRING_DECL(kCFBundleLocalizationsKey
, "CFBundleLocalizations")
113 // Private CFBundle Info plist keys, possible candidates for public constants
114 CONST_STRING_DECL(_kCFBundleAllowMixedLocalizationsKey
, "CFBundleAllowMixedLocalizations")
115 CONST_STRING_DECL(_kCFBundleSupportedPlatformsKey
, "CFBundleSupportedPlatforms")
116 CONST_STRING_DECL(_kCFBundleResourceSpecificationKey
, "CFBundleResourceSpecification")
119 CONST_STRING_DECL(_kCFBundlePackageTypeKey
, "CFBundlePackageType")
120 CONST_STRING_DECL(_kCFBundleSignatureKey
, "CFBundleSignature")
121 CONST_STRING_DECL(_kCFBundleIconFileKey
, "CFBundleIconFile")
122 CONST_STRING_DECL(_kCFBundleDocumentTypesKey
, "CFBundleDocumentTypes")
123 CONST_STRING_DECL(_kCFBundleURLTypesKey
, "CFBundleURLTypes")
125 // Keys that are usually localized in InfoPlist.strings
126 CONST_STRING_DECL(kCFBundleNameKey
, "CFBundleName")
127 CONST_STRING_DECL(_kCFBundleDisplayNameKey
, "CFBundleDisplayName")
128 CONST_STRING_DECL(_kCFBundleShortVersionStringKey
, "CFBundleShortVersionString")
129 CONST_STRING_DECL(_kCFBundleGetInfoStringKey
, "CFBundleGetInfoString")
130 CONST_STRING_DECL(_kCFBundleGetInfoHTMLKey
, "CFBundleGetInfoHTML")
132 // Sub-keys for CFBundleDocumentTypes dictionaries
133 CONST_STRING_DECL(_kCFBundleTypeNameKey
, "CFBundleTypeName")
134 CONST_STRING_DECL(_kCFBundleTypeRoleKey
, "CFBundleTypeRole")
135 CONST_STRING_DECL(_kCFBundleTypeIconFileKey
, "CFBundleTypeIconFile")
136 CONST_STRING_DECL(_kCFBundleTypeOSTypesKey
, "CFBundleTypeOSTypes")
137 CONST_STRING_DECL(_kCFBundleTypeExtensionsKey
, "CFBundleTypeExtensions")
138 CONST_STRING_DECL(_kCFBundleTypeMIMETypesKey
, "CFBundleTypeMIMETypes")
140 // Sub-keys for CFBundleURLTypes dictionaries
141 CONST_STRING_DECL(_kCFBundleURLNameKey
, "CFBundleURLName")
142 CONST_STRING_DECL(_kCFBundleURLIconFileKey
, "CFBundleURLIconFile")
143 CONST_STRING_DECL(_kCFBundleURLSchemesKey
, "CFBundleURLSchemes")
145 // Compatibility key names
146 CONST_STRING_DECL(_kCFBundleOldExecutableKey
, "NSExecutable")
147 CONST_STRING_DECL(_kCFBundleOldInfoDictionaryVersionKey
, "NSInfoPlistVersion")
148 CONST_STRING_DECL(_kCFBundleOldNameKey
, "NSHumanReadableName")
149 CONST_STRING_DECL(_kCFBundleOldIconFileKey
, "NSIcon")
150 CONST_STRING_DECL(_kCFBundleOldDocumentTypesKey
, "NSTypes")
151 CONST_STRING_DECL(_kCFBundleOldShortVersionStringKey
, "NSAppVersion")
153 // Compatibility CFBundleDocumentTypes key names
154 CONST_STRING_DECL(_kCFBundleOldTypeNameKey
, "NSName")
155 CONST_STRING_DECL(_kCFBundleOldTypeRoleKey
, "NSRole")
156 CONST_STRING_DECL(_kCFBundleOldTypeIconFileKey
, "NSIcon")
157 CONST_STRING_DECL(_kCFBundleOldTypeExtensions1Key
, "NSUnixExtensions")
158 CONST_STRING_DECL(_kCFBundleOldTypeExtensions2Key
, "NSDOSExtensions")
159 CONST_STRING_DECL(_kCFBundleOldTypeOSTypesKey
, "NSMacOSType")
161 // Internally used keys for loaded Info plists.
162 CONST_STRING_DECL(_kCFBundleInfoPlistURLKey
, "CFBundleInfoPlistURL")
163 CONST_STRING_DECL(_kCFBundleRawInfoPlistURLKey
, "CFBundleRawInfoPlistURL")
164 CONST_STRING_DECL(_kCFBundleNumericVersionKey
, "CFBundleNumericVersion")
165 CONST_STRING_DECL(_kCFBundleExecutablePathKey
, "CFBundleExecutablePath")
166 CONST_STRING_DECL(_kCFBundleResourcesFileMappedKey
, "CSResourcesFileMapped")
167 CONST_STRING_DECL(_kCFBundleCFMLoadAsBundleKey
, "CFBundleCFMLoadAsBundle")
169 // Keys used by NSBundle for loaded Info plists.
170 CONST_STRING_DECL(_kCFBundlePrincipalClassKey
, "NSPrincipalClass")
172 static char __CFBundleMainID__
[1026] = {0};
173 CF_PRIVATE
char *__CFBundleMainID
= __CFBundleMainID__
;
175 static CFTypeID __kCFBundleTypeID
= _kCFRuntimeNotATypeID
;
177 static pthread_mutex_t CFBundleGlobalDataLock
= PTHREAD_MUTEX_INITIALIZER
;
179 static CFMutableDictionaryRef _bundlesByIdentifier
= NULL
;
180 #if AVOID_WEAK_COLLECTIONS
181 static CFMutableDictionaryRef _bundlesByURL
= NULL
;
182 static CFMutableArrayRef _allBundles
= NULL
;
183 static CFMutableSetRef _bundlesToUnload
= NULL
;
184 #else /* AVOID_WEAK_COLLECTIONS */
185 static __CFHashTable
*_allBundles
= nil
;
186 static __CFHashTable
*_bundlesToUnload
= nil
;
187 #endif /* AVOID_WEAK_COLLECTIONS */
188 static Boolean _scheduledBundlesAreUnloading
= false;
190 static Boolean _initedMainBundle
= false;
191 static CFBundleRef _mainBundle
= NULL
;
193 // Forward declares functions.
194 static CFBundleRef
_CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
, Boolean alreadyLocked
, Boolean doFinalProcessing
);
195 static CFURLRef
_CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle
);
196 static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint
);
197 static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void);
198 static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath
);
199 static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths
);
200 #if defined(BINARY_SUPPORT_DYLD)
201 static CFMutableDictionaryRef
_CFBundleCreateInfoDictFromMainExecutable(void);
202 static Boolean
_CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion
, uint32_t *objcFlags
);
203 static CFStringRef
_CFBundleDYLDCopyLoadedImagePathForPointer(void *p
);
204 #if !defined(BINARY_SUPPORT_DLFCN)
205 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
);
206 #endif /* !BINARY_SUPPORT_DLFCN */
207 #endif /* BINARY_SUPPORT_DYLD */
208 #if defined(BINARY_SUPPORT_DLFCN)
209 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
);
210 #if !defined(BINARY_SUPPORT_DYLD)
211 static CFStringRef
_CFBundleDlfcnCopyLoadedImagePathForPointer(void *p
);
212 #endif /* !BINARY_SUPPORT_DYLD */
213 #endif /* BINARY_SUPPORT_DLFCN */
216 #if AVOID_WEAK_COLLECTIONS
218 static void _CFBundleAddToTables(CFBundleRef bundle
, Boolean alreadyLocked
) {
219 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
221 if (!alreadyLocked
) pthread_mutex_lock(&CFBundleGlobalDataLock
);
223 // Add to the _allBundles list
225 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
226 nonRetainingArrayCallbacks
.retain
= NULL
;
227 nonRetainingArrayCallbacks
.release
= NULL
;
228 _allBundles
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
230 CFArrayAppendValue(_allBundles
, bundle
);
232 // Add to the table that maps urls to bundles
233 if (!_bundlesByURL
) {
234 CFDictionaryValueCallBacks nonRetainingDictionaryValueCallbacks
= kCFTypeDictionaryValueCallBacks
;
235 nonRetainingDictionaryValueCallbacks
.retain
= NULL
;
236 nonRetainingDictionaryValueCallbacks
.release
= NULL
;
237 _bundlesByURL
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &nonRetainingDictionaryValueCallbacks
);
239 CFDictionarySetValue(_bundlesByURL
, bundle
->_url
, bundle
);
241 // Add to the table that maps identifiers to bundles
243 CFMutableArrayRef bundlesWithThisID
= NULL
;
244 CFBundleRef existingBundle
= NULL
;
245 if (!_bundlesByIdentifier
) {
246 _bundlesByIdentifier
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
248 bundlesWithThisID
= (CFMutableArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
249 if (bundlesWithThisID
) {
250 CFIndex i
, count
= CFArrayGetCount(bundlesWithThisID
);
251 UInt32 existingVersion
, newVersion
= CFBundleGetVersionNumber(bundle
);
252 for (i
= 0; i
< count
; i
++) {
253 existingBundle
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, i
);
254 existingVersion
= CFBundleGetVersionNumber(existingBundle
);
255 // If you load two bundles with the same identifier and the same version, the last one wins.
256 if (newVersion
>= existingVersion
) break;
258 CFArrayInsertValueAtIndex(bundlesWithThisID
, i
, bundle
);
260 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
261 nonRetainingArrayCallbacks
.retain
= NULL
;
262 nonRetainingArrayCallbacks
.release
= NULL
;
263 bundlesWithThisID
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
264 CFArrayAppendValue(bundlesWithThisID
, bundle
);
265 CFDictionarySetValue(_bundlesByIdentifier
, bundleID
, bundlesWithThisID
);
266 CFRelease(bundlesWithThisID
);
269 if (!alreadyLocked
) pthread_mutex_unlock(&CFBundleGlobalDataLock
);
272 static void _CFBundleRemoveFromTables(CFBundleRef bundle
, CFURLRef bundleURL
, CFStringRef bundleID
) {
273 pthread_mutex_lock(&CFBundleGlobalDataLock
);
274 // Remove from the various lists
276 CFIndex i
= CFArrayGetFirstIndexOfValue(_allBundles
, CFRangeMake(0, CFArrayGetCount(_allBundles
)), bundle
);
277 if (i
>= 0) CFArrayRemoveValueAtIndex(_allBundles
, i
);
280 // Remove from the table that maps urls to bundles
281 if (bundleURL
&& _bundlesByURL
) {
282 CFBundleRef bundleForURL
= (CFBundleRef
)CFDictionaryGetValue(_bundlesByURL
, bundleURL
);
283 if (bundleForURL
== bundle
) CFDictionaryRemoveValue(_bundlesByURL
, bundleURL
);
286 // Remove from the table that maps identifiers to bundles
287 if (bundleID
&& _bundlesByIdentifier
) {
288 CFMutableArrayRef bundlesWithThisID
= (CFMutableArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
289 if (bundlesWithThisID
) {
290 CFIndex count
= CFArrayGetCount(bundlesWithThisID
);
291 while (count
-- > 0) if (bundle
== (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, count
)) CFArrayRemoveValueAtIndex(bundlesWithThisID
, count
);
292 if (0 == CFArrayGetCount(bundlesWithThisID
)) CFDictionaryRemoveValue(_bundlesByIdentifier
, bundleID
);
295 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
298 static CFBundleRef
_CFBundleCopyBundleForURL(CFURLRef url
, Boolean alreadyLocked
) {
299 CFBundleRef result
= NULL
;
300 if (!alreadyLocked
) pthread_mutex_lock(&CFBundleGlobalDataLock
);
301 if (_bundlesByURL
) result
= (CFBundleRef
)CFDictionaryGetValue(_bundlesByURL
, url
);
302 if (result
&& !result
->_url
) {
304 CFDictionaryRemoveValue(_bundlesByURL
, url
);
306 if (result
) CFRetain(result
);
307 if (!alreadyLocked
) pthread_mutex_unlock(&CFBundleGlobalDataLock
);
311 static CFBundleRef
_CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID
) {
312 CFBundleRef result
= NULL
, bundle
;
313 if (_bundlesByIdentifier
&& bundleID
) {
314 // Note that this array is maintained in descending order by version number
315 CFArrayRef bundlesWithThisID
= (CFArrayRef
)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
316 if (bundlesWithThisID
) {
317 CFIndex i
, count
= CFArrayGetCount(bundlesWithThisID
);
319 // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
320 for (i
= 0; !result
&& i
< count
; i
++) {
321 bundle
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, i
);
322 if (CFBundleIsExecutableLoaded(bundle
)) result
= bundle
;
324 // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
325 if (!result
) result
= (CFBundleRef
)CFArrayGetValueAtIndex(bundlesWithThisID
, 0);
332 #else /* AVOID_WEAK_COLLECTIONS */
335 An explanation of what I'm doing here is probably in order.
336 8029300 has cast suspicion on the correctness of __CFMapTable with strong keys and weak values, at least under non-GC.
337 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
338 This indicates that it's not an overrelease in securityd, since AVOID_WEAK_COLLECTIONS wouldn't help in that case.
339 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.
341 static inline id
_getBundlesByURL() {
342 static id _bundles
= nil
;
343 static dispatch_once_t onceToken
;
344 dispatch_once(&onceToken
, ^{
345 if (CF_USING_COLLECTABLE_MEMORY
) {
346 _bundles
= [[__CFMapTable alloc
] initWithKeyOptions
:CFPointerFunctionsStrongMemory valueOptions
:CFPointerFunctionsZeroingWeakMemory capacity
:0];
348 CFDictionaryValueCallBacks nonRetainingDictionaryValueCallbacks
= kCFTypeDictionaryValueCallBacks
;
349 nonRetainingDictionaryValueCallbacks
.retain
= NULL
;
350 nonRetainingDictionaryValueCallbacks
.release
= NULL
;
351 _bundles
= (id
)CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &nonRetainingDictionaryValueCallbacks
);
357 #define _bundlesByURL _getBundlesByURL()
359 static void _setInBundlesByURL(CFURLRef key
, CFBundleRef bundle
) {
360 if (CF_USING_COLLECTABLE_MEMORY
) {
361 [(__CFMapTable
*)_bundlesByURL setObject
:(id
)bundle forKey
:(id
)key
];
363 CFDictionarySetValue((CFMutableDictionaryRef
)_bundlesByURL
, key
, bundle
);
367 static void _removeFromBundlesByURL(CFURLRef key
) {
368 if (CF_USING_COLLECTABLE_MEMORY
) {
369 [(__CFMapTable
*)_bundlesByURL removeObjectForKey
:(id
)key
];
371 CFDictionaryRemoveValue((CFMutableDictionaryRef
)_bundlesByURL
, key
);
375 static CFBundleRef
_getFromBundlesByURL(CFURLRef key
) {
376 if (CF_USING_COLLECTABLE_MEMORY
) {
377 return (CFBundleRef
)[(__CFMapTable
*)_bundlesByURL objectForKey
:(id
)key
];
379 return (CFBundleRef
)CFDictionaryGetValue((CFMutableDictionaryRef
)_bundlesByURL
, key
);
383 static void _CFBundleAddToTables(CFBundleRef bundle
, Boolean alreadyLocked
) {
384 CFStringRef bundleID
= CFBundleGetIdentifier(bundle
);
386 if (!alreadyLocked
) pthread_mutex_lock(&CFBundleGlobalDataLock
);
388 // Add to the _allBundles list
389 if (!_allBundles
) _allBundles
= [[__CFHashTable alloc
] initWithOptions
:CFPointerFunctionsZeroingWeakMemory capacity
:0];
390 [_allBundles addObject
:(id
)bundle
];
392 // Add to the table that maps urls to bundles
393 _setInBundlesByURL(bundle
->_url
, bundle
);
395 // Add to the table that maps identifiers to bundles
397 __CFPointerArray
*bundlesWithThisID
= nil
;
398 CFBundleRef existingBundle
= NULL
;
399 if (!_bundlesByIdentifier
) {
400 _bundlesByIdentifier
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
402 bundlesWithThisID
= (__CFPointerArray
*)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
403 if (bundlesWithThisID
) {
404 CFIndex i
, count
= (CFIndex
)[bundlesWithThisID count
];
405 UInt32 existingVersion
, newVersion
= CFBundleGetVersionNumber(bundle
);
406 for (i
= 0; i
< count
; i
++) {
407 existingBundle
= (CFBundleRef
)[bundlesWithThisID pointerAtIndex
:i
];
408 if (!existingBundle
) continue;
409 existingVersion
= CFBundleGetVersionNumber(existingBundle
);
410 // If you load two bundles with the same identifier and the same version, the last one wins.
411 if (newVersion
>= existingVersion
) break;
414 [bundlesWithThisID insertPointer
:bundle atIndex
:i
];
416 [bundlesWithThisID addPointer
:bundle
];
419 bundlesWithThisID
= [[__CFPointerArray alloc
] initWithOptions
:CFPointerFunctionsZeroingWeakMemory
];
420 [bundlesWithThisID addPointer
:bundle
];
421 CFDictionarySetValue(_bundlesByIdentifier
, bundleID
, bundlesWithThisID
);
422 [bundlesWithThisID release
];
425 if (!alreadyLocked
) pthread_mutex_unlock(&CFBundleGlobalDataLock
);
428 static void _CFBundleRemoveFromTables(CFBundleRef bundle
, CFURLRef bundleURL
, CFStringRef bundleID
) {
429 pthread_mutex_lock(&CFBundleGlobalDataLock
);
430 // Remove from the various lists
431 if (_allBundles
&& [_allBundles member
:(id
)bundle
]) [_allBundles removeObject
:(id
)bundle
];
433 // Remove from the table that maps urls to bundles
435 _removeFromBundlesByURL(bundleURL
);
438 // Remove from the table that maps identifiers to bundles
439 if (bundleID
&& _bundlesByIdentifier
) {
440 __CFPointerArray
*bundlesWithThisID
= (__CFPointerArray
*)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
441 if (bundlesWithThisID
) {
442 CFIndex count
= (CFIndex
)[bundlesWithThisID count
];
443 while (count
-- > 0) if (bundle
== (CFBundleRef
)[bundlesWithThisID pointerAtIndex
:count
]) [bundlesWithThisID removePointerAtIndex
:count
];
444 [bundlesWithThisID compact
];
445 if (0 == [bundlesWithThisID count
]) CFDictionaryRemoveValue(_bundlesByIdentifier
, bundleID
);
448 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
451 static CFBundleRef
_CFBundleCopyBundleForURL(CFURLRef url
, Boolean alreadyLocked
) {
452 CFBundleRef result
= NULL
;
453 if (!alreadyLocked
) pthread_mutex_lock(&CFBundleGlobalDataLock
);
454 result
= _getFromBundlesByURL(url
);
455 if (result
&& !result
->_url
) {
457 _removeFromBundlesByURL(url
);
459 if (result
) CFRetain(result
);
460 if (!alreadyLocked
) pthread_mutex_unlock(&CFBundleGlobalDataLock
);
464 static CFBundleRef
_CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID
) {
465 CFBundleRef result
= NULL
;
466 if (_bundlesByIdentifier
&& bundleID
) {
467 // Note that this array is maintained in descending order by version number
468 __CFPointerArray
*bundlesWithThisID
= (__CFPointerArray
*)CFDictionaryGetValue(_bundlesByIdentifier
, bundleID
);
469 if (bundlesWithThisID
&& [bundlesWithThisID count
] > 0) {
470 // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
471 for (id bundle in bundlesWithThisID
) {
472 if (bundle
&& CFBundleIsExecutableLoaded((CFBundleRef
)bundle
)) {
473 result
= (CFBundleRef
)bundle
;
477 // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
479 for (id bundle in bundlesWithThisID
) {
481 result
= (CFBundleRef
)bundle
;
491 #endif /* AVOID_WEAK_COLLECTIONS */
493 static CFURLRef
_CFBundleCopyBundleURLForExecutablePath(CFStringRef str
) {
494 //!!! need to handle frameworks, NT; need to integrate with NSBundle - drd
495 UniChar buff
[CFMaxPathSize
];
500 buffLen
= CFStringGetLength(str
);
501 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
502 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
504 #if DEPLOYMENT_TARGET_WINDOWS
505 // Is this a .dll or .exe?
506 if (buffLen
>= 5 && (_wcsnicmp((wchar_t *)&(buff
[buffLen
-4]), L
".dll", 4) == 0 || _wcsnicmp((wchar_t *)&(buff
[buffLen
-4]), L
".exe", 4) == 0)) {
507 CFIndex extensionLength
= CFStringGetLength(_CFBundleWindowsResourceDirectoryExtension
);
509 // If this is an _debug, we should strip that before looking for the bundle
510 if (buffLen
>= 7 && (_wcsnicmp((wchar_t *)&buff
[buffLen
-6], L
"_debug", 6) == 0)) buffLen
-= 6;
512 if (buffLen
+ 1 + extensionLength
< CFMaxPathSize
) {
515 CFStringGetCharacters(_CFBundleWindowsResourceDirectoryExtension
, CFRangeMake(0, extensionLength
), buff
+ buffLen
);
516 buffLen
+= extensionLength
;
517 outstr
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, buff
, buffLen
, kCFAllocatorNull
);
518 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, outstr
, PLATFORM_PATH_STYLE
, true);
525 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
); // Remove exe name
528 // See if this is a new bundle. If it is, we have to remove more path components.
529 CFIndex startOfLastDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
530 if (startOfLastDir
> 0 && startOfLastDir
< buffLen
) {
531 CFStringRef lastDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfLastDir
]), buffLen
- startOfLastDir
);
533 if (CFEqual(lastDirName
, _CFBundleGetPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetAlternatePlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName
, _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName())) {
534 // This is a new bundle. Back off a few more levels
536 // Remove platform folder
537 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
540 // Remove executables folder (if present)
541 CFIndex startOfNextDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
542 if (startOfNextDir
> 0 && startOfNextDir
< buffLen
) {
543 CFStringRef nextDirName
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfNextDir
]), buffLen
- startOfNextDir
);
544 if (CFEqual(nextDirName
, _CFBundleExecutablesDirectoryName
)) buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
545 CFRelease(nextDirName
);
549 // Remove support files folder
550 buffLen
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
553 CFRelease(lastDirName
);
558 outstr
= CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault
, buff
, buffLen
, kCFAllocatorNull
);
559 url
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, outstr
, PLATFORM_PATH_STYLE
, true);
566 static CFURLRef
_CFBundleCopyResolvedURLForExecutableURL(CFURLRef url
) {
567 // this is necessary so that we match any sanitization CFURL may perform on the result of _CFBundleCopyBundleURLForExecutableURL()
568 CFURLRef absoluteURL
, url1
, url2
, outURL
= NULL
;
569 CFStringRef str
, str1
, str2
;
570 absoluteURL
= CFURLCopyAbsoluteURL(url
);
571 str
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
);
573 UniChar buff
[CFMaxPathSize
];
574 CFIndex buffLen
= CFStringGetLength(str
), len1
;
575 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
576 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
577 len1
= _CFLengthAfterDeletingLastPathComponent(buff
, buffLen
);
578 if (len1
> 0 && len1
+ 1 < buffLen
) {
579 str1
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, buff
, len1
);
580 CFIndex skipSlashCount
= 1;
581 #if DEPLOYMENT_TARGET_WINDOWS
582 // 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
583 if (len1
== 3 && buff
[1] == ':' && buff
[2] == '\\') {
587 str2
= CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, buff
+ len1
+ skipSlashCount
, buffLen
- len1
- skipSlashCount
);
589 url1
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str1
, PLATFORM_PATH_STYLE
, true);
591 url2
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, str2
, PLATFORM_PATH_STYLE
, false, url1
);
593 outURL
= CFURLCopyAbsoluteURL(url2
);
599 if (str1
) CFRelease(str1
);
600 if (str2
) CFRelease(str2
);
605 outURL
= absoluteURL
;
607 CFRelease(absoluteURL
);
612 CFURLRef
_CFBundleCopyBundleURLForExecutableURL(CFURLRef url
) {
613 CFURLRef resolvedURL
, outurl
= NULL
;
615 resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
616 str
= CFURLCopyFileSystemPath(resolvedURL
, PLATFORM_PATH_STYLE
);
618 outurl
= _CFBundleCopyBundleURLForExecutablePath(str
);
621 CFRelease(resolvedURL
);
625 static uint8_t _CFBundleEffectiveLayoutVersion(CFBundleRef bundle
) {
626 uint8_t localVersion
= bundle
->_version
;
627 // exclude type 0 bundles with no binary (or CFM binary) and no Info.plist, since they give too many false positives
628 if (0 == localVersion
) {
629 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
630 if (!infoDict
|| 0 == CFDictionaryGetCount(infoDict
)) {
631 #if defined(BINARY_SUPPORT_DYLD)
632 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
634 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
635 if (bundle
->_binaryType
== __CFBundleCFMBinary
|| bundle
->_binaryType
== __CFBundleUnreadableBinary
) {
638 bundle
->_resourceData
._executableLacksResourceFork
= true;
640 CFRelease(executableURL
);
645 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
647 CFRelease(executableURL
);
651 #endif /* BINARY_SUPPORT_DYLD */
657 CFBundleRef
_CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
658 CFBundleRef bundle
= CFBundleCreate(allocator
, url
);
660 uint8_t localVersion
= _CFBundleEffectiveLayoutVersion(bundle
);
661 if (3 == localVersion
|| 4 == localVersion
) {
669 CFBundleRef
_CFBundleGetMainBundleIfLooksLikeBundle(void) {
670 CFBundleRef mainBundle
= CFBundleGetMainBundle();
671 if (mainBundle
&& (3 == mainBundle
->_version
|| 4 == mainBundle
->_version
)) mainBundle
= NULL
;
675 Boolean
_CFBundleMainBundleInfoDictionaryComesFromResourceFork(void) {
676 CFBundleRef mainBundle
= CFBundleGetMainBundle();
677 return (mainBundle
&& mainBundle
->_resourceData
._infoDictionaryFromResourceFork
);
680 CFBundleRef
_CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
681 CFBundleRef bundle
= NULL
;
682 CFURLRef bundleURL
= _CFBundleCopyBundleURLForExecutableURL(url
), resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
683 if (bundleURL
&& resolvedURL
) {
684 bundle
= _CFBundleCreateIfLooksLikeBundle(allocator
, bundleURL
);
686 CFURLRef executableURL
= _CFBundleCopyExecutableURLIgnoringCache(bundle
);
687 char buff1
[CFMaxPathSize
], buff2
[CFMaxPathSize
];
688 if (!executableURL
|| !CFURLGetFileSystemRepresentation(resolvedURL
, true, (uint8_t *)buff1
, CFMaxPathSize
) || !CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff2
, CFMaxPathSize
) || 0 != strcmp(buff1
, buff2
)) {
692 if (executableURL
) CFRelease(executableURL
);
695 if (bundleURL
) CFRelease(bundleURL
);
696 if (resolvedURL
) CFRelease(resolvedURL
);
700 CFBundleRef
_CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
701 CFBundleRef bundle
= CFBundleCreate(allocator
, url
);
703 Boolean mightBeBundle
= true, isDir
= false;
704 uint8_t localVersion
= _CFBundleEffectiveLayoutVersion(bundle
);
705 if (3 == localVersion
) {
706 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
707 CFURLRef executableURL
, supportFilesURL
, resourceSpecificationFileURL
;
708 CFArrayRef supportedPlatforms
;
709 CFStringRef resourceSpecificationFile
;
711 mightBeBundle
= false;
712 if (infoDict
&& CFDictionaryGetValue(infoDict
, kCFBundleExecutableKey
) && (executableURL
= _CFBundleCopyExecutableURLIgnoringCache(bundle
))) {
713 supportedPlatforms
= _CFBundleGetSupportedPlatforms(bundle
);
714 resourceSpecificationFile
= (CFStringRef
)CFDictionaryGetValue(infoDict
, _kCFBundleResourceSpecificationKey
);
715 if (supportedPlatforms
&& CFArrayGetCount(supportedPlatforms
) > 0 && CFArrayGetFirstIndexOfValue(supportedPlatforms
, CFRangeMake(0, CFArrayGetCount(supportedPlatforms
)), CFSTR("iPhoneOS")) >= 0) {
716 mightBeBundle
= true;
717 } else if (resourceSpecificationFile
&& CFGetTypeID(resourceSpecificationFile
) == CFStringGetTypeID() && (supportFilesURL
= CFBundleCopySupportFilesDirectoryURL(bundle
))) {
718 resourceSpecificationFileURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, resourceSpecificationFile
, kCFURLPOSIXPathStyle
, false, supportFilesURL
);
719 if (resourceSpecificationFileURL
) {
720 if (_CFIsResourceAtURL(resourceSpecificationFileURL
, &isDir
) && !isDir
) mightBeBundle
= true;
721 CFRelease(resourceSpecificationFileURL
);
723 CFRelease(supportFilesURL
);
725 CFRelease(executableURL
);
727 } else if (4 == localVersion
) {
728 mightBeBundle
= false;
730 if (!mightBeBundle
) {
738 CFBundleRef
_CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef allocator
, CFURLRef url
) {
739 CFBundleRef bundle
= NULL
;
740 CFURLRef bundleURL
= _CFBundleCopyBundleURLForExecutableURL(url
), resolvedURL
= _CFBundleCopyResolvedURLForExecutableURL(url
);
741 if (bundleURL
&& resolvedURL
) {
742 bundle
= _CFBundleCreateIfMightBeBundle(allocator
, bundleURL
);
744 CFURLRef executableURL
= _CFBundleCopyExecutableURLIgnoringCache(bundle
);
745 char buff1
[CFMaxPathSize
], buff2
[CFMaxPathSize
];
746 if (!executableURL
|| !CFURLGetFileSystemRepresentation(resolvedURL
, true, (uint8_t *)buff1
, CFMaxPathSize
) || !CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff2
, CFMaxPathSize
) || 0 != strcmp(buff1
, buff2
)) {
750 if (executableURL
) CFRelease(executableURL
);
753 if (bundleURL
) CFRelease(bundleURL
);
754 if (resolvedURL
) CFRelease(resolvedURL
);
758 CFURLRef
_CFBundleCopyMainBundleExecutableURL(Boolean
*looksLikeBundle
) {
759 // This function is for internal use only; _mainBundle is deliberately accessed outside of the lock to get around a reentrancy issue
760 const char *processPath
;
761 CFStringRef str
= NULL
;
762 CFURLRef executableURL
= NULL
;
763 processPath
= _CFProcessPath();
765 str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, processPath
);
767 executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str
, PLATFORM_PATH_STYLE
, false);
771 if (looksLikeBundle
) {
772 CFBundleRef mainBundle
= _mainBundle
;
773 if (mainBundle
&& (3 == mainBundle
->_version
|| 4 == mainBundle
->_version
)) mainBundle
= NULL
;
774 *looksLikeBundle
= (mainBundle
? true : false);
776 return executableURL
;
779 static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef executablePath
) {
780 CFBundleGetInfoDictionary(_mainBundle
);
781 if (!_mainBundle
->_infoDict
|| CFDictionaryGetCount(_mainBundle
->_infoDict
) == 0) {
782 // if type 3 bundle and no Info.plist, treat as unbundled, since this gives too many false positives
783 if (_mainBundle
->_version
== 3) _mainBundle
->_version
= 4;
784 if (_mainBundle
->_version
== 0) {
785 // if type 0 bundle and no Info.plist and not main executable for bundle, treat as unbundled, since this gives too many false positives
786 CFStringRef executableName
= _CFBundleCopyExecutableName(_mainBundle
, NULL
, NULL
);
787 if (!executableName
|| !executablePath
|| !CFStringHasSuffix(executablePath
, executableName
)) _mainBundle
->_version
= 4;
788 if (executableName
) CFRelease(executableName
);
790 #if defined(BINARY_SUPPORT_DYLD)
791 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
) {
792 if (_mainBundle
->_infoDict
&& !(0)) CFRelease(_mainBundle
->_infoDict
);
793 _mainBundle
->_infoDict
= (CFDictionaryRef
)_CFBundleCreateInfoDictFromMainExecutable();
795 #endif /* BINARY_SUPPORT_DYLD */
797 #if defined(BINARY_SUPPORT_DYLD)
798 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
) {
799 // if dyld and not main executable for bundle, prefer info dictionary from executable
800 CFStringRef executableName
= _CFBundleCopyExecutableName(_mainBundle
, NULL
, NULL
);
801 if (!executableName
|| !executablePath
|| !CFStringHasSuffix(executablePath
, executableName
)) {
802 CFDictionaryRef infoDictFromExecutable
= (CFDictionaryRef
)_CFBundleCreateInfoDictFromMainExecutable();
803 if (infoDictFromExecutable
&& CFDictionaryGetCount(infoDictFromExecutable
) > 0) {
804 if (_mainBundle
->_infoDict
) CFRelease(_mainBundle
->_infoDict
);
805 _mainBundle
->_infoDict
= infoDictFromExecutable
;
806 } else if (infoDictFromExecutable
) {
807 CFRelease(infoDictFromExecutable
);
810 if (executableName
) CFRelease(executableName
);
812 #endif /* BINARY_SUPPORT_DYLD */
814 if (!_mainBundle
->_infoDict
) _mainBundle
->_infoDict
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
815 if (!_mainBundle
->_executablePath
&& executablePath
) _mainBundle
->_executablePath
= (CFStringRef
)CFRetain(executablePath
);
816 CFStringRef bundleID
= (CFStringRef
)CFDictionaryGetValue(_mainBundle
->_infoDict
, kCFBundleIdentifierKey
);
818 if (!CFStringGetCString(bundleID
, __CFBundleMainID__
, sizeof(__CFBundleMainID__
) - 2, kCFStringEncodingUTF8
)) {
819 __CFBundleMainID__
[0] = '\0';
824 static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle
, Boolean alreadyLocked
) {
825 CFDictionaryRef oldInfoDict
= bundle
->_infoDict
;
828 bundle
->_infoDict
= NULL
;
829 if (bundle
->_localInfoDict
) {
830 CFRelease(bundle
->_localInfoDict
);
831 bundle
->_localInfoDict
= NULL
;
833 if (bundle
->_developmentRegion
) {
834 CFRelease(bundle
->_developmentRegion
);
835 bundle
->_developmentRegion
= NULL
;
837 if (bundle
->_executablePath
) {
838 CFRelease(bundle
->_executablePath
);
839 bundle
->_executablePath
= NULL
;
841 if (bundle
->_searchLanguages
) {
842 CFRelease(bundle
->_searchLanguages
);
843 bundle
->_searchLanguages
= NULL
;
845 if (bundle
->_resourceData
._stringTableCache
) {
846 CFRelease(bundle
->_resourceData
._stringTableCache
);
847 bundle
->_resourceData
._stringTableCache
= NULL
;
849 if (bundle
== _mainBundle
) {
850 CFStringRef executablePath
= bundle
->_executablePath
;
851 if (!alreadyLocked
) pthread_mutex_lock(&CFBundleGlobalDataLock
);
852 _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(executablePath
);
853 if (!alreadyLocked
) pthread_mutex_unlock(&CFBundleGlobalDataLock
);
855 CFBundleGetInfoDictionary(bundle
);
858 if (!bundle
->_infoDict
) bundle
->_infoDict
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
859 val
= CFDictionaryGetValue(oldInfoDict
, _kCFBundlePrincipalClassKey
);
860 if (val
) CFDictionarySetValue((CFMutableDictionaryRef
)bundle
->_infoDict
, _kCFBundlePrincipalClassKey
, val
);
861 CFRelease(oldInfoDict
);
863 __CFSpinLock(&bundle
->_queryLock
);
864 if (bundle
->_queryTable
) {
865 CFDictionaryRemoveAllValues(bundle
->_queryTable
);
867 __CFSpinUnlock(&bundle
->_queryLock
);
870 CF_EXPORT
void _CFBundleFlushBundleCaches(CFBundleRef bundle
) {
871 _CFBundleFlushBundleCachesAlreadyLocked(bundle
, false);
874 static CFBundleRef
_CFBundleGetMainBundleAlreadyLocked(void) {
875 if (!_initedMainBundle
) {
876 const char *processPath
;
877 CFStringRef str
= NULL
;
878 CFURLRef executableURL
= NULL
, bundleURL
= NULL
;
879 _initedMainBundle
= true;
880 processPath
= _CFProcessPath();
882 str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, processPath
);
883 if (!executableURL
) executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, str
, PLATFORM_PATH_STYLE
, false);
885 if (executableURL
) bundleURL
= _CFBundleCopyBundleURLForExecutableURL(executableURL
);
887 // make sure that main bundle has executable path
888 //??? what if we are not the main executable in the bundle?
889 // NB doFinalProcessing must be false here, see below
890 _mainBundle
= _CFBundleCreate(kCFAllocatorSystemDefault
, bundleURL
, true, false);
892 // make sure that the main bundle is listed as loaded, and mark it as executable
893 _mainBundle
->_isLoaded
= true;
894 #if defined(BINARY_SUPPORT_DYLD)
895 if (_mainBundle
->_binaryType
== __CFBundleUnknownBinary
) {
896 if (!executableURL
) {
897 _mainBundle
->_binaryType
= __CFBundleNoBinary
;
899 _mainBundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
900 if (_mainBundle
->_binaryType
!= __CFBundleCFMBinary
&& _mainBundle
->_binaryType
!= __CFBundleUnreadableBinary
) _mainBundle
->_resourceData
._executableLacksResourceFork
= true;
903 #endif /* BINARY_SUPPORT_DYLD */
904 // get cookie for already-loaded main bundle
905 #if defined(BINARY_SUPPORT_DLFCN)
906 if (!_mainBundle
->_handleCookie
) {
907 _mainBundle
->_handleCookie
= dlopen(NULL
, RTLD_NOLOAD
| RTLD_FIRST
);
909 printf("main bundle %p getting handle %p\n", _mainBundle
, _mainBundle
->_handleCookie
);
910 #endif /* LOG_BUNDLE_LOAD */
912 #elif defined(BINARY_SUPPORT_DYLD)
913 if (_mainBundle
->_binaryType
== __CFBundleDYLDExecutableBinary
&& !_mainBundle
->_imageCookie
) {
914 _mainBundle
->_imageCookie
= (void *)_dyld_get_image_header(0);
916 printf("main bundle %p getting image %p\n", _mainBundle
, _mainBundle
->_imageCookie
);
917 #endif /* LOG_BUNDLE_LOAD */
919 #endif /* BINARY_SUPPORT_DLFCN */
920 _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(str
);
921 // Perform delayed final processing steps.
922 // This must be done after _isLoaded has been set, for security reasons (3624341).
923 if (_CFBundleNeedsInitPlugIn(_mainBundle
)) {
924 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
925 _CFBundleInitPlugIn(_mainBundle
);
926 pthread_mutex_lock(&CFBundleGlobalDataLock
);
930 if (bundleURL
) CFRelease(bundleURL
);
931 if (str
) CFRelease(str
);
932 if (executableURL
) CFRelease(executableURL
);
937 CFBundleRef
CFBundleGetMainBundle(void) {
938 CFBundleRef mainBundle
;
939 pthread_mutex_lock(&CFBundleGlobalDataLock
);
940 mainBundle
= _CFBundleGetMainBundleAlreadyLocked();
941 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
945 CFBundleRef
CFBundleGetBundleWithIdentifier(CFStringRef bundleID
) {
946 CFBundleRef result
= NULL
;
948 pthread_mutex_lock(&CFBundleGlobalDataLock
);
949 (void)_CFBundleGetMainBundleAlreadyLocked();
950 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
951 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
953 // Try to create the bundle for the caller and try again
954 void *p
= __builtin_return_address(0);
956 CFStringRef imagePath
= NULL
;
957 #if defined(BINARY_SUPPORT_DYLD)
958 if (!imagePath
) imagePath
= _CFBundleDYLDCopyLoadedImagePathForPointer(p
);
959 #elif defined(BINARY_SUPPORT_DLFCN)
960 if (!imagePath
) imagePath
= _CFBundleDlfcnCopyLoadedImagePathForPointer(p
);
961 #endif /* BINARY_SUPPORT_DYLD */
963 _CFBundleEnsureBundleExistsForImagePath(imagePath
);
964 CFRelease(imagePath
);
966 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
971 // Try to guess the bundle from the identifier and try again
972 _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(bundleID
);
973 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
976 // Make sure all bundles have been created and try again.
977 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
978 result
= _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID
);
980 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
985 static CFStringRef
__CFBundleCopyDescription(CFTypeRef cf
) {
986 char buff
[CFMaxPathSize
];
987 CFStringRef path
= NULL
, binaryType
= NULL
, retval
= NULL
;
988 if (((CFBundleRef
)cf
)->_url
&& CFURLGetFileSystemRepresentation(((CFBundleRef
)cf
)->_url
, true, (uint8_t *)buff
, CFMaxPathSize
)) path
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, buff
);
989 switch (((CFBundleRef
)cf
)->_binaryType
) {
990 case __CFBundleCFMBinary
:
991 binaryType
= CFSTR("");
993 case __CFBundleDYLDExecutableBinary
:
994 binaryType
= CFSTR("executable, ");
996 case __CFBundleDYLDBundleBinary
:
997 binaryType
= CFSTR("bundle, ");
999 case __CFBundleDYLDFrameworkBinary
:
1000 binaryType
= CFSTR("framework, ");
1002 case __CFBundleDLLBinary
:
1003 binaryType
= CFSTR("DLL, ");
1005 case __CFBundleUnreadableBinary
:
1006 binaryType
= CFSTR("");
1009 binaryType
= CFSTR("");
1012 if (((CFBundleRef
)cf
)->_plugInData
._isPlugIn
) {
1013 retval
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("CFBundle/CFPlugIn %p <%@> (%@%@loaded)"), cf
, path
, binaryType
, ((CFBundleRef
)cf
)->_isLoaded
? CFSTR("") : CFSTR("not "));
1015 retval
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("CFBundle %p <%@> (%@%@loaded)"), cf
, path
, binaryType
, ((CFBundleRef
)cf
)->_isLoaded
? CFSTR("") : CFSTR("not "));
1017 if (path
) CFRelease(path
);
1021 static void _CFBundleDeallocateGlue(const void *key
, const void *value
, void *context
) {
1022 CFAllocatorRef allocator
= (CFAllocatorRef
)context
;
1023 if (value
) CFAllocatorDeallocate(allocator
, (void *)value
);
1026 static void __CFBundleDeallocate(CFTypeRef cf
) {
1027 CFBundleRef bundle
= (CFBundleRef
)cf
;
1029 CFStringRef bundleID
= NULL
;
1031 __CFGenericValidateType(cf
, __kCFBundleTypeID
);
1032 bundleURL
= bundle
->_url
;
1033 bundle
->_url
= NULL
;
1034 if (bundle
->_infoDict
) bundleID
= (CFStringRef
)CFDictionaryGetValue(bundle
->_infoDict
, kCFBundleIdentifierKey
);
1035 _CFBundleRemoveFromTables(bundle
, bundleURL
, bundleID
);
1036 CFBundleUnloadExecutable(bundle
);
1037 _CFBundleDeallocatePlugIn(bundle
);
1039 CFRelease(bundleURL
);
1041 if (bundle
->_infoDict
&& !(0)) CFRelease(bundle
->_infoDict
);
1042 if (bundle
->_modDate
) CFRelease(bundle
->_modDate
);
1043 if (bundle
->_localInfoDict
&& !(0)) CFRelease(bundle
->_localInfoDict
);
1044 if (bundle
->_searchLanguages
) CFRelease(bundle
->_searchLanguages
);
1045 if (bundle
->_executablePath
) CFRelease(bundle
->_executablePath
);
1046 if (bundle
->_developmentRegion
) CFRelease(bundle
->_developmentRegion
);
1047 if (bundle
->_glueDict
) {
1048 CFDictionaryApplyFunction(bundle
->_glueDict
, _CFBundleDeallocateGlue
, (void *)CFGetAllocator(bundle
));
1049 CFRelease(bundle
->_glueDict
);
1051 if (bundle
->_resourceData
._stringTableCache
) CFRelease(bundle
->_resourceData
._stringTableCache
);
1053 if (bundle
->_bundleBasePath
) CFRelease(bundle
->_bundleBasePath
);
1054 if (bundle
->_queryTable
) CFRelease(bundle
->_queryTable
);
1056 if (bundle
->_localizations
) CFRelease(bundle
->_localizations
);
1057 if (bundle
->_resourceDirectoryContents
) CFRelease(bundle
->_resourceDirectoryContents
);
1059 pthread_mutex_destroy(&(bundle
->_bundleLoadingLock
));
1062 static const CFRuntimeClass __CFBundleClass
= {
1063 _kCFRuntimeScannedObject
,
1067 __CFBundleDeallocate
,
1071 __CFBundleCopyDescription
1074 // From CFBundle_Resources.c
1075 CF_PRIVATE
void _CFBundleResourcesInitialize();
1077 CF_PRIVATE
void __CFBundleInitialize(void) {
1078 __kCFBundleTypeID
= _CFRuntimeRegisterClass(&__CFBundleClass
);
1079 _CFBundleResourcesInitialize();
1082 CFTypeID
CFBundleGetTypeID(void) {
1083 return __kCFBundleTypeID
;
1086 CFBundleRef
_CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL
) {
1087 CFBundleRef bundle
= NULL
;
1088 char buff
[CFMaxPathSize
];
1089 CFURLRef newURL
= NULL
;
1091 if (!CFURLGetFileSystemRepresentation(bundleURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) return NULL
;
1093 newURL
= CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault
, (uint8_t *)buff
, strlen(buff
), true);
1094 if (!newURL
) newURL
= (CFURLRef
)CFRetain(bundleURL
);
1095 bundle
= _CFBundleCopyBundleForURL(newURL
, false);
1096 if (bundle
) CFRelease(bundle
);
1101 static CFBundleRef
_CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
, Boolean alreadyLocked
, Boolean doFinalProcessing
) {
1102 CFBundleRef bundle
= NULL
;
1103 char buff
[CFMaxPathSize
];
1104 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
1105 Boolean exists
= false;
1107 CFURLRef newURL
= NULL
;
1108 uint8_t localVersion
= 0;
1110 if (!CFURLGetFileSystemRepresentation(bundleURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) return NULL
;
1112 newURL
= CFURLCreateFromFileSystemRepresentation(allocator
, (uint8_t *)buff
, strlen(buff
), true);
1113 if (!newURL
) newURL
= (CFURLRef
)CFRetain(bundleURL
);
1114 bundle
= _CFBundleCopyBundleForURL(newURL
, alreadyLocked
);
1120 localVersion
= _CFBundleGetBundleVersionForURL(newURL
);
1121 if (localVersion
== 3) {
1122 SInt32 res
= _CFGetPathProperties(allocator
, (char *)buff
, &exists
, &mode
, NULL
, NULL
, NULL
, NULL
);
1123 #if DEPLOYMENT_TARGET_WINDOWS
1124 if (!(res
== 0 && exists
&& ((mode
& S_IFMT
) == S_IFDIR
))) {
1125 // 2nd chance at finding a bundle path - remove the last path component (e.g., mybundle.resources) and try again
1130 CFURLRef shorterPath
= CFURLCreateCopyDeletingLastPathComponent(allocator
, newURL
);
1132 newURL
= shorterPath
;
1133 res
= _CFGetFileProperties(allocator
, newURL
, &exists
, &mode
, NULL
, NULL
, NULL
, NULL
);
1137 if (!exists
|| ((mode
& S_IFMT
) != S_IFDIR
)) {
1138 if (modDate
) CFRelease(modDate
);
1148 bundle
= (CFBundleRef
)_CFRuntimeCreateInstance(allocator
, __kCFBundleTypeID
, sizeof(struct __CFBundle
) - sizeof(CFRuntimeBase
), NULL
);
1154 bundle
->_url
= newURL
;
1156 bundle
->_modDate
= modDate
;
1157 bundle
->_version
= localVersion
;
1158 bundle
->_infoDict
= NULL
;
1159 bundle
->_localInfoDict
= NULL
;
1160 bundle
->_searchLanguages
= NULL
;
1161 bundle
->_executablePath
= NULL
;
1162 bundle
->_developmentRegion
= NULL
;
1163 bundle
->_developmentRegionCalculated
= false;
1164 #if defined(BINARY_SUPPORT_DYLD)
1165 /* We'll have to figure it out later */
1166 bundle
->_binaryType
= __CFBundleUnknownBinary
;
1167 #elif defined(BINARY_SUPPORT_DLL)
1168 /* We support DLL only */
1169 bundle
->_binaryType
= __CFBundleDLLBinary
;
1170 bundle
->_hModule
= NULL
;
1172 /* We'll have to figure it out later */
1173 bundle
->_binaryType
= __CFBundleUnknownBinary
;
1174 #endif /* BINARY_SUPPORT_DYLD */
1176 bundle
->_isLoaded
= false;
1177 bundle
->_sharesStringsFiles
= false;
1179 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1180 if (!__CFgetenv("CFBundleDisableStringsSharing") &&
1181 (strncmp(buff
, "/System/Library/Frameworks", 26) == 0) &&
1182 (strncmp(buff
+ strlen(buff
) - 10, ".framework", 10) == 0)) bundle
->_sharesStringsFiles
= true;
1185 bundle
->_connectionCookie
= NULL
;
1186 bundle
->_handleCookie
= NULL
;
1187 bundle
->_imageCookie
= NULL
;
1188 bundle
->_moduleCookie
= NULL
;
1190 bundle
->_glueDict
= NULL
;
1192 bundle
->_resourceData
._executableLacksResourceFork
= false;
1193 bundle
->_resourceData
._infoDictionaryFromResourceFork
= false;
1194 bundle
->_resourceData
._stringTableCache
= NULL
;
1196 bundle
->_plugInData
._isPlugIn
= false;
1197 bundle
->_plugInData
._loadOnDemand
= false;
1198 bundle
->_plugInData
._isDoingDynamicRegistration
= false;
1199 bundle
->_plugInData
._instanceCount
= 0;
1200 bundle
->_plugInData
._factories
= NULL
;
1202 pthread_mutexattr_t mattr
;
1203 pthread_mutexattr_init(&mattr
);
1204 pthread_mutexattr_settype(&mattr
, PTHREAD_MUTEX_DEFAULT
);
1205 int32_t mret
= pthread_mutex_init(&(bundle
->_bundleLoadingLock
), &mattr
);
1206 pthread_mutexattr_destroy(&mattr
);
1208 CFLog(4, CFSTR("%s: failed to initialize bundle loading lock for bundle %@."), __PRETTY_FUNCTION__
, bundle
);
1211 bundle
->_lock
= CFSpinLockInit
;
1212 bundle
->_resourceDirectoryContents
= NULL
;
1214 bundle
->_localizations
= NULL
;
1215 bundle
->_lookedForLocalizations
= false;
1217 bundle
->_queryLock
= CFSpinLockInit
;
1218 bundle
->_queryTable
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFCopyStringDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1219 CFURLRef absoURL
= CFURLCopyAbsoluteURL(bundle
->_url
);
1220 bundle
->_bundleBasePath
= CFURLCopyFileSystemPath(absoURL
, PLATFORM_PATH_STYLE
);
1223 CFBundleGetInfoDictionary(bundle
);
1225 _CFBundleAddToTables(bundle
, alreadyLocked
);
1227 if (doFinalProcessing
) {
1228 if (_CFBundleNeedsInitPlugIn(bundle
)) {
1229 if (alreadyLocked
) pthread_mutex_unlock(&CFBundleGlobalDataLock
);
1230 _CFBundleInitPlugIn(bundle
);
1231 if (alreadyLocked
) pthread_mutex_lock(&CFBundleGlobalDataLock
);
1238 CFBundleRef
CFBundleCreate(CFAllocatorRef allocator
, CFURLRef bundleURL
) {
1239 return _CFBundleCreate(allocator
, bundleURL
, false, true);
1242 CFArrayRef
CFBundleCreateBundlesFromDirectory(CFAllocatorRef alloc
, CFURLRef directoryURL
, CFStringRef bundleType
) {
1243 CFMutableArrayRef bundles
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
);
1244 CFArrayRef URLs
= _CFCreateContentsOfDirectory(alloc
, NULL
, NULL
, directoryURL
, bundleType
);
1246 CFIndex i
, c
= CFArrayGetCount(URLs
);
1248 CFBundleRef curBundle
;
1250 for (i
= 0; i
< c
; i
++) {
1251 curURL
= (CFURLRef
)CFArrayGetValueAtIndex(URLs
, i
);
1252 curBundle
= CFBundleCreate(alloc
, curURL
);
1253 if (curBundle
) CFArrayAppendValue(bundles
, curBundle
);
1261 CFURLRef
CFBundleCopyBundleURL(CFBundleRef bundle
) {
1262 if (bundle
->_url
) CFRetain(bundle
->_url
);
1263 return bundle
->_url
;
1266 #define DEVELOPMENT_STAGE 0x20
1267 #define ALPHA_STAGE 0x40
1268 #define BETA_STAGE 0x60
1269 #define RELEASE_STAGE 0x80
1271 #define MAX_VERS_LEN 10
1273 CF_INLINE Boolean
_isDigit(UniChar aChar
) {return ((aChar
>= (UniChar
)'0' && aChar
<= (UniChar
)'9') ? true : false);}
1275 CF_PRIVATE CFStringRef
_CFCreateStringFromVersionNumber(CFAllocatorRef alloc
, UInt32 vers
) {
1276 CFStringRef result
= NULL
;
1277 uint8_t major1
, major2
, minor1
, minor2
, stage
, build
;
1279 major1
= (vers
& 0xF0000000) >> 28;
1280 major2
= (vers
& 0x0F000000) >> 24;
1281 minor1
= (vers
& 0x00F00000) >> 20;
1282 minor2
= (vers
& 0x000F0000) >> 16;
1283 stage
= (vers
& 0x0000FF00) >> 8;
1284 build
= (vers
& 0x000000FF);
1286 if (stage
== RELEASE_STAGE
) {
1288 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d%d.%d.%d"), major1
, major2
, minor1
, minor2
);
1290 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d.%d.%d"), major2
, minor1
, minor2
);
1294 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
);
1296 result
= CFStringCreateWithFormat(alloc
, NULL
, CFSTR("%d.%d.%d%c%d"), major2
, minor1
, minor2
, ((stage
== DEVELOPMENT_STAGE
) ? 'd' : ((stage
== ALPHA_STAGE
) ? 'a' : 'b')), build
);
1302 CF_PRIVATE UInt32
_CFVersionNumberFromString(CFStringRef versStr
) {
1303 // Parse version number from string.
1304 // String can begin with "." for major version number 0. String can end at any point, but elements within the string cannot be skipped.
1305 UInt32 major1
= 0, major2
= 0, minor1
= 0, minor2
= 0, stage
= RELEASE_STAGE
, build
= 0;
1306 UniChar versChars
[MAX_VERS_LEN
];
1307 UniChar
*chars
= NULL
;
1310 Boolean digitsDone
= false;
1312 if (!versStr
) return 0;
1313 len
= CFStringGetLength(versStr
);
1314 if (len
<= 0 || len
> MAX_VERS_LEN
) return 0;
1316 CFStringGetCharacters(versStr
, CFRangeMake(0, len
), versChars
);
1319 // Get major version number.
1320 major1
= major2
= 0;
1321 if (_isDigit(*chars
)) {
1322 major2
= *chars
- (UniChar
)'0';
1326 if (_isDigit(*chars
)) {
1328 major2
= *chars
- (UniChar
)'0';
1332 if (*chars
== (UniChar
)'.') {
1339 } else if (*chars
== (UniChar
)'.') {
1346 } else if (*chars
== (UniChar
)'.') {
1353 // Now major1 and major2 contain first and second digit of the major version number as ints.
1354 // Now either len is 0 or chars points at the first char beyond the first decimal point.
1356 // Get the first minor version number.
1357 if (len
> 0 && !digitsDone
) {
1358 if (_isDigit(*chars
)) {
1359 minor1
= *chars
- (UniChar
)'0';
1363 if (*chars
== (UniChar
)'.') {
1375 // Now minor1 contains the first minor version number as an int.
1376 // Now either len is 0 or chars points at the first char beyond the second decimal point.
1378 // Get the second minor version number.
1379 if (len
> 0 && !digitsDone
) {
1380 if (_isDigit(*chars
)) {
1381 minor2
= *chars
- (UniChar
)'0';
1389 // Now minor2 contains the second minor version number as an int.
1390 // Now either len is 0 or chars points at the build stage letter.
1392 // Get the build stage letter. We must find 'd', 'a', 'b', or 'f' next, if there is anything next.
1394 if (*chars
== (UniChar
)'d') {
1395 stage
= DEVELOPMENT_STAGE
;
1396 } else if (*chars
== (UniChar
)'a') {
1397 stage
= ALPHA_STAGE
;
1398 } else if (*chars
== (UniChar
)'b') {
1400 } else if (*chars
== (UniChar
)'f') {
1401 stage
= RELEASE_STAGE
;
1409 // Now stage contains the release stage.
1410 // Now either len is 0 or chars points at the build number.
1412 // Get the first digit of the build number.
1414 if (_isDigit(*chars
)) {
1415 build
= *chars
- (UniChar
)'0';
1422 // Get the second digit of the build number.
1424 if (_isDigit(*chars
)) {
1426 build
+= *chars
- (UniChar
)'0';
1433 // Get the third digit of the build number.
1435 if (_isDigit(*chars
)) {
1437 build
+= *chars
- (UniChar
)'0';
1445 // Range check the build number and make sure we exhausted the string.
1446 if (build
> 0xFF || len
> 0) return 0;
1449 theVers
= major1
<< 28;
1450 theVers
+= major2
<< 24;
1451 theVers
+= minor1
<< 20;
1452 theVers
+= minor2
<< 16;
1453 theVers
+= stage
<< 8;
1459 UInt32
CFBundleGetVersionNumber(CFBundleRef bundle
) {
1460 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1461 CFNumberRef versionValue
= (CFNumberRef
)CFDictionaryGetValue(infoDict
, _kCFBundleNumericVersionKey
);
1462 if (!versionValue
|| CFGetTypeID(versionValue
) != CFNumberGetTypeID()) return 0;
1465 CFNumberGetValue(versionValue
, kCFNumberSInt32Type
, &vers
);
1469 CFStringRef
CFBundleGetDevelopmentRegion(CFBundleRef bundle
) {
1470 CFStringRef devRegion
= NULL
;
1471 devRegion
= bundle
->_developmentRegion
;
1473 if (!devRegion
&& !bundle
->_developmentRegionCalculated
) {
1474 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
1476 devRegion
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleDevelopmentRegionKey
);
1477 if (devRegion
&& (CFGetTypeID(devRegion
) != CFStringGetTypeID() || CFStringGetLength(devRegion
) == 0)) {
1482 if (devRegion
) bundle
->_developmentRegion
= (CFStringRef
)CFRetain(devRegion
);
1483 bundle
->_developmentRegionCalculated
= true;
1489 Boolean
_CFBundleGetHasChanged(CFBundleRef bundle
) {
1491 Boolean result
= false;
1492 Boolean exists
= false;
1495 if (_CFGetFileProperties(CFGetAllocator(bundle
), bundle
->_url
, &exists
, &mode
, NULL
, &modDate
, NULL
, NULL
) == 0) {
1496 // If the bundle no longer exists or is not a folder, it must have "changed"
1497 if (!exists
|| ((mode
& S_IFMT
) != S_IFDIR
)) result
= true;
1499 // Something is wrong. The stat failed.
1502 if (bundle
->_modDate
&& !CFEqual(bundle
->_modDate
, modDate
)) {
1503 // mod date is different from when we created.
1510 void _CFBundleSetStringsFilesShared(CFBundleRef bundle
, Boolean flag
) {
1511 bundle
->_sharesStringsFiles
= flag
;
1514 Boolean
_CFBundleGetStringsFilesShared(CFBundleRef bundle
) {
1515 return bundle
->_sharesStringsFiles
;
1518 static Boolean
_urlExists(CFURLRef url
) {
1520 return url
&& (0 == _CFGetFileProperties(kCFAllocatorSystemDefault
, url
, &exists
, NULL
, NULL
, NULL
, NULL
, NULL
)) && exists
;
1523 // This is here because on iPhoneOS with the dyld shared cache, we remove binaries from their
1524 // original locations on disk, so checking whether a binary's path exists is no longer sufficient.
1525 // For performance reasons, we only call dlopen_preflight() after we've verified that the binary
1526 // does not exist at its original path with _urlExists().
1527 // See <rdar://problem/6956670>
1528 static Boolean
_binaryLoadable(CFURLRef url
) {
1529 Boolean loadable
= _urlExists(url
);
1530 #if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1532 uint8_t path
[PATH_MAX
];
1533 if (url
&& CFURLGetFileSystemRepresentation(url
, true, path
, sizeof(path
))) {
1534 loadable
= dlopen_preflight((char *)path
);
1541 CF_PRIVATE CFURLRef
_CFBundleCopySupportFilesDirectoryURLInDirectory(CFURLRef bundleURL
, uint8_t version
) {
1542 CFURLRef result
= NULL
;
1545 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleSupportFilesURLFromBase1
, bundleURL
);
1546 } else if (2 == version
) {
1547 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleSupportFilesURLFromBase2
, bundleURL
);
1549 result
= (CFURLRef
)CFRetain(bundleURL
);
1555 CF_EXPORT CFURLRef
CFBundleCopySupportFilesDirectoryURL(CFBundleRef bundle
) {
1556 return _CFBundleCopySupportFilesDirectoryURLInDirectory(bundle
->_url
, bundle
->_version
);
1559 CF_PRIVATE CFURLRef
_CFBundleCopyResourcesDirectoryURLInDirectory(CFURLRef bundleURL
, uint8_t version
) {
1560 CFURLRef result
= NULL
;
1563 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleResourcesURLFromBase0
, bundleURL
);
1564 } else if (1 == version
) {
1565 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleResourcesURLFromBase1
, bundleURL
);
1566 } else if (2 == version
) {
1567 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleResourcesURLFromBase2
, bundleURL
);
1569 result
= (CFURLRef
)CFRetain(bundleURL
);
1575 CFURLRef
CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle
) {
1576 return _CFBundleCopyResourcesDirectoryURLInDirectory(bundle
->_url
, bundle
->_version
);
1579 CF_PRIVATE CFURLRef
_CFBundleCopyAppStoreReceiptURLInDirectory(CFURLRef bundleURL
, uint8_t version
) {
1580 CFURLRef result
= NULL
;
1583 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleAppStoreReceiptURLFromBase0
, bundleURL
);
1584 } else if (1 == version
) {
1585 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleAppStoreReceiptURLFromBase1
, bundleURL
);
1586 } else if (2 == version
) {
1587 result
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleAppStoreReceiptURLFromBase2
, bundleURL
);
1593 CFURLRef
_CFBundleCopyAppStoreReceiptURL(CFBundleRef bundle
) {
1594 return _CFBundleCopyAppStoreReceiptURLInDirectory(bundle
->_url
, bundle
->_version
);
1597 static CFURLRef
_CFBundleCopyExecutableURLRaw(CFURLRef urlPath
, CFStringRef exeName
) {
1598 // 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.
1599 CFURLRef executableURL
= NULL
;
1600 if (!urlPath
|| !exeName
) return NULL
;
1602 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1603 const uint8_t *image_suffix
= (uint8_t *)__CFgetenv("DYLD_IMAGE_SUFFIX");
1605 CFStringRef newExeName
, imageSuffix
;
1606 imageSuffix
= CFStringCreateWithCString(kCFAllocatorSystemDefault
, (char *)image_suffix
, kCFStringEncodingUTF8
);
1607 if (CFStringHasSuffix(exeName
, CFSTR(".dylib"))) {
1608 CFStringRef bareExeName
= CFStringCreateWithSubstring(kCFAllocatorSystemDefault
, exeName
, CFRangeMake(0, CFStringGetLength(exeName
)-6));
1609 newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@.dylib"), exeName
, imageSuffix
);
1610 CFRelease(bareExeName
);
1612 newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@"), exeName
, imageSuffix
);
1614 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, newExeName
, kCFURLPOSIXPathStyle
, false, urlPath
);
1615 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1616 CFRelease(executableURL
);
1617 executableURL
= NULL
;
1619 CFRelease(newExeName
);
1620 CFRelease(imageSuffix
);
1622 if (!executableURL
) {
1623 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, exeName
, kCFURLPOSIXPathStyle
, false, urlPath
);
1624 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1625 CFRelease(executableURL
);
1626 executableURL
= NULL
;
1629 #elif DEPLOYMENT_TARGET_WINDOWS
1630 if (!executableURL
) {
1631 executableURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, exeName
, kCFURLWindowsPathStyle
, false, urlPath
);
1632 if (executableURL
&& !_urlExists(executableURL
)) {
1633 CFRelease(executableURL
);
1634 executableURL
= NULL
;
1637 if (!executableURL
) {
1638 if (!CFStringFindWithOptions(exeName
, CFSTR(".dll"), CFRangeMake(0, CFStringGetLength(exeName
)), kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
)) {
1640 CFStringRef extension
= CFSTR("_debug.dll");
1642 CFStringRef extension
= CFSTR(".dll");
1644 CFStringRef newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@"), exeName
, extension
);
1645 executableURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, newExeName
, urlPath
);
1646 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1647 CFRelease(executableURL
);
1648 executableURL
= NULL
;
1650 CFRelease(newExeName
);
1653 if (!executableURL
) {
1654 if (!CFStringFindWithOptions(exeName
, CFSTR(".exe"), CFRangeMake(0, CFStringGetLength(exeName
)), kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
)) {
1656 CFStringRef extension
= CFSTR("_debug.exe");
1658 CFStringRef extension
= CFSTR(".exe");
1660 CFStringRef newExeName
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@%@"), exeName
, extension
);
1661 executableURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, newExeName
, urlPath
);
1662 if (executableURL
&& !_binaryLoadable(executableURL
)) {
1663 CFRelease(executableURL
);
1664 executableURL
= NULL
;
1666 CFRelease(newExeName
);
1670 return executableURL
;
1673 CF_PRIVATE CFStringRef
_CFBundleCopyExecutableName(CFBundleRef bundle
, CFURLRef url
, CFDictionaryRef infoDict
) {
1674 CFStringRef executableName
= NULL
;
1676 if (!infoDict
&& bundle
) infoDict
= CFBundleGetInfoDictionary(bundle
);
1677 if (!url
&& bundle
) url
= bundle
->_url
;
1680 // Figure out the name of the executable.
1681 // First try for the new key in the plist.
1682 executableName
= (CFStringRef
)CFDictionaryGetValue(infoDict
, kCFBundleExecutableKey
);
1683 // Second try for the old key in the plist.
1684 if (!executableName
) executableName
= (CFStringRef
)CFDictionaryGetValue(infoDict
, _kCFBundleOldExecutableKey
);
1685 if (executableName
&& CFGetTypeID(executableName
) == CFStringGetTypeID() && CFStringGetLength(executableName
) > 0) {
1686 CFRetain(executableName
);
1688 executableName
= NULL
;
1691 if (!executableName
&& url
) {
1692 // Third, take the name of the bundle itself (with path extension stripped)
1693 CFURLRef absoluteURL
= CFURLCopyAbsoluteURL(url
);
1694 CFStringRef bundlePath
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
);
1695 CFRelease(absoluteURL
);
1697 CFIndex len
= CFStringGetLength(bundlePath
);
1698 CFIndex startOfBundleName
= _CFStartOfLastPathComponent2(bundlePath
);
1699 CFIndex endOfBundleName
= _CFLengthAfterDeletingPathExtension2(bundlePath
);
1701 if (startOfBundleName
<= len
&& endOfBundleName
<= len
&& startOfBundleName
< endOfBundleName
) {
1702 executableName
= CFStringCreateWithSubstring(kCFAllocatorSystemDefault
, bundlePath
, CFRangeMake(startOfBundleName
, endOfBundleName
- startOfBundleName
));
1704 CFRelease(bundlePath
);
1708 return executableName
;
1711 static CFURLRef
_CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle
, CFURLRef url
, CFStringRef executableName
, Boolean ignoreCache
, Boolean useOtherPlatform
) {
1712 uint8_t version
= 0;
1713 CFDictionaryRef infoDict
= NULL
;
1714 CFStringRef executablePath
= NULL
;
1715 CFURLRef executableURL
= NULL
;
1716 Boolean foundIt
= false;
1717 Boolean lookupMainExe
= (executableName
? false : true);
1720 infoDict
= CFBundleGetInfoDictionary(bundle
);
1721 version
= bundle
->_version
;
1723 infoDict
= _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault
, url
, &version
);
1726 // If we have a bundle instance and an info dict, see if we have already cached the path
1727 if (lookupMainExe
&& !ignoreCache
&& !useOtherPlatform
&& bundle
&& bundle
->_executablePath
) {
1728 __CFSpinLock(&bundle
->_lock
);
1729 executablePath
= bundle
->_executablePath
;
1730 if (executablePath
) CFRetain(executablePath
);
1731 __CFSpinUnlock(&bundle
->_lock
);
1732 if (executablePath
) {
1733 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1734 executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, executablePath
, kCFURLPOSIXPathStyle
, false);
1735 #elif DEPLOYMENT_TARGET_WINDOWS
1736 executableURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, executablePath
, kCFURLWindowsPathStyle
, false);
1738 if (executableURL
) {
1741 CFRelease(executablePath
);
1746 if (lookupMainExe
) executableName
= _CFBundleCopyExecutableName(bundle
, url
, infoDict
);
1747 if (executableName
) {
1748 #if (DEPLOYMENT_TARGET_EMBEDDED && !TARGET_IPHONE_SIMULATOR)
1749 Boolean doExecSearch
= false;
1751 Boolean doExecSearch
= true;
1753 // Now, look for the executable inside the bundle.
1754 if (doExecSearch
&& 0 != version
) {
1755 CFURLRef exeDirURL
= NULL
;
1756 CFURLRef exeSubdirURL
;
1759 exeDirURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleExecutablesURLFromBase1
, url
);
1760 } else if (2 == version
) {
1761 exeDirURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, _CFBundleExecutablesURLFromBase2
, url
);
1763 #if DEPLOYMENT_TARGET_WINDOWS
1764 // On Windows, if the bundle URL is foo.resources, then the executable is at the same level as the .resources directory
1765 CFStringRef extension
= CFURLCopyPathExtension(url
);
1766 if (extension
&& CFEqual(extension
, _CFBundleWindowsResourceDirectoryExtension
)) {
1767 exeDirURL
= CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault
, url
);
1769 exeDirURL
= (CFURLRef
)CFRetain(url
);
1771 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1772 exeDirURL
= (CFURLRef
)CFRetain(url
);
1775 CFStringRef platformSubDir
= useOtherPlatform
? _CFBundleGetOtherPlatformExecutablesSubdirectoryName() : _CFBundleGetPlatformExecutablesSubdirectoryName();
1776 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1777 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
1778 if (!executableURL
) {
1779 CFRelease(exeSubdirURL
);
1780 platformSubDir
= useOtherPlatform
? _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetAlternatePlatformExecutablesSubdirectoryName();
1781 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1782 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
1784 if (!executableURL
) {
1785 CFRelease(exeSubdirURL
);
1786 platformSubDir
= useOtherPlatform
? _CFBundleGetPlatformExecutablesSubdirectoryName() : _CFBundleGetOtherPlatformExecutablesSubdirectoryName();
1787 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1788 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
1790 if (!executableURL
) {
1791 CFRelease(exeSubdirURL
);
1792 platformSubDir
= useOtherPlatform
? _CFBundleGetAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName();
1793 exeSubdirURL
= CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault
, platformSubDir
, kCFURLPOSIXPathStyle
, true, exeDirURL
);
1794 executableURL
= _CFBundleCopyExecutableURLRaw(exeSubdirURL
, executableName
);
1796 if (!executableURL
) executableURL
= _CFBundleCopyExecutableURLRaw(exeDirURL
, executableName
);
1797 CFRelease(exeDirURL
);
1798 CFRelease(exeSubdirURL
);
1801 // If this was an old bundle, or we did not find the executable in the Executables subdirectory, look directly in the bundle wrapper.
1802 if (!executableURL
) executableURL
= _CFBundleCopyExecutableURLRaw(url
, executableName
);
1804 #if DEPLOYMENT_TARGET_WINDOWS
1805 // Windows only: If we still haven't found the exe, look in the Executables folder.
1806 // But only for the main bundle exe
1807 if (lookupMainExe
&& !executableURL
) {
1808 CFURLRef exeDirURL
= CFURLCreateWithString(kCFAllocatorSystemDefault
, CFSTR("../../Executables"), url
);
1809 executableURL
= _CFBundleCopyExecutableURLRaw(exeDirURL
, executableName
);
1810 CFRelease(exeDirURL
);
1814 if (lookupMainExe
&& !ignoreCache
&& !useOtherPlatform
&& bundle
&& executableURL
) {
1815 // We found it. Cache the path.
1816 CFURLRef absURL
= CFURLCopyAbsoluteURL(executableURL
);
1817 #if DEPLOYMENT_TARGET_WINDOWS
1818 executablePath
= CFURLCopyFileSystemPath(absURL
, kCFURLWindowsPathStyle
);
1819 #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1820 executablePath
= CFURLCopyFileSystemPath(absURL
, kCFURLPOSIXPathStyle
);
1823 __CFSpinLock(&bundle
->_lock
);
1824 bundle
->_executablePath
= (CFStringRef
)CFRetain(executablePath
);
1825 __CFSpinUnlock(&bundle
->_lock
);
1826 CFRelease(executablePath
);
1828 if (lookupMainExe
&& !useOtherPlatform
&& bundle
&& !executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
1829 if (lookupMainExe
) CFRelease(executableName
);
1832 if (!bundle
&& infoDict
&& !(0)) CFRelease(infoDict
);
1833 return executableURL
;
1837 CFURLRef
_CFBundleCopyExecutableURLInDirectory(CFURLRef url
) {
1838 return _CFBundleCopyExecutableURLInDirectory2(NULL
, url
, NULL
, true, false);
1841 CFURLRef
_CFBundleCopyOtherExecutableURLInDirectory(CFURLRef url
) {
1842 return _CFBundleCopyExecutableURLInDirectory2(NULL
, url
, NULL
, true, true);
1845 CFURLRef
CFBundleCopyExecutableURL(CFBundleRef bundle
) {
1846 return _CFBundleCopyExecutableURLInDirectory2(bundle
, bundle
->_url
, NULL
, false, false);
1849 static CFURLRef
_CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle
) {
1850 return _CFBundleCopyExecutableURLInDirectory2(bundle
, bundle
->_url
, NULL
, true, false);
1853 CFURLRef
CFBundleCopyAuxiliaryExecutableURL(CFBundleRef bundle
, CFStringRef executableName
) {
1854 return _CFBundleCopyExecutableURLInDirectory2(bundle
, bundle
->_url
, executableName
, true, false);
1857 Boolean
CFBundleIsExecutableLoaded(CFBundleRef bundle
) {
1858 return bundle
->_isLoaded
;
1861 CFBundleExecutableType
CFBundleGetExecutableType(CFBundleRef bundle
) {
1862 CFBundleExecutableType result
= kCFBundleOtherExecutableType
;
1863 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
1865 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
1866 #if defined(BINARY_SUPPORT_DYLD)
1867 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
1868 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
1869 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
1871 #endif /* BINARY_SUPPORT_DYLD */
1872 if (executableURL
) CFRelease(executableURL
);
1874 if (bundle
->_binaryType
== __CFBundleCFMBinary
) {
1875 result
= kCFBundlePEFExecutableType
;
1876 } else if (bundle
->_binaryType
== __CFBundleDYLDExecutableBinary
|| bundle
->_binaryType
== __CFBundleDYLDBundleBinary
|| bundle
->_binaryType
== __CFBundleDYLDFrameworkBinary
) {
1877 result
= kCFBundleMachOExecutableType
;
1878 } else if (bundle
->_binaryType
== __CFBundleDLLBinary
) {
1879 result
= kCFBundleDLLExecutableType
;
1880 } else if (bundle
->_binaryType
== __CFBundleELFBinary
) {
1881 result
= kCFBundleELFExecutableType
;
1886 static SInt32
_CFBundleCurrentArchitecture(void) {
1888 #if defined(__ppc__)
1889 arch
= kCFBundleExecutableArchitecturePPC
;
1890 #elif defined(__ppc64__)
1891 arch
= kCFBundleExecutableArchitecturePPC64
;
1892 #elif defined(__i386__)
1893 arch
= kCFBundleExecutableArchitectureI386
;
1894 #elif defined(__x86_64__)
1895 arch
= kCFBundleExecutableArchitectureX86_64
;
1896 #elif defined(BINARY_SUPPORT_DYLD)
1897 const NXArchInfo
*archInfo
= NXGetLocalArchInfo();
1898 if (archInfo
) arch
= archInfo
->cputype
;
1903 #define UNKNOWN_FILETYPE 0x0
1904 #define PEF_FILETYPE 0x1000
1905 #define PEF_MAGIC 0x4a6f7921
1906 #define PEF_CIGAM 0x21796f4a
1907 #define TEXT_SEGMENT "__TEXT"
1908 #define PLIST_SECTION "__info_plist"
1909 #define OBJC_SEGMENT "__OBJC"
1910 #define IMAGE_INFO_SECTION "__image_info"
1911 #define OBJC_SEGMENT_64 "__DATA"
1912 #define IMAGE_INFO_SECTION_64 "__objc_imageinfo"
1913 #define LIB_X11 "/usr/X11R6/lib/libX"
1915 #define XLS_NAME "Book"
1916 #define XLS_NAME2 "Workbook"
1917 #define DOC_NAME "WordDocument"
1918 #define PPT_NAME "PowerPoint Document"
1920 #define ustrncmp(x, y, z) strncmp((char *)(x), (char *)(y), (z))
1921 #define ustrncasecmp(x, y, z) strncasecmp_l((char *)(x), (char *)(y), (z), NULL)
1923 static const uint32_t __CFBundleMagicNumbersArray
[] = {
1924 0xcafebabe, 0xbebafeca, 0xfeedface, 0xcefaedfe, 0xfeedfacf, 0xcffaedfe, 0x4a6f7921, 0x21796f4a,
1925 0x7f454c46, 0xffd8ffe0, 0x4d4d002a, 0x49492a00, 0x47494638, 0x89504e47, 0x69636e73, 0x00000100,
1926 0x7b5c7274, 0x25504446, 0x2e7261fd, 0x2e524d46, 0x2e736e64, 0x2e736400, 0x464f524d, 0x52494646,
1927 0x38425053, 0x000001b3, 0x000001ba, 0x4d546864, 0x504b0304, 0x53495421, 0x53495432, 0x53495435,
1928 0x53495444, 0x53747566, 0x30373037, 0x3c212d2d, 0x25215053, 0xd0cf11e0, 0x62656769, 0x3d796265,
1929 0x6b6f6c79, 0x3026b275, 0x0000000c, 0xfe370023, 0x09020600, 0x09040600, 0x4f676753, 0x664c6143,
1930 0x00010000, 0x74727565, 0x4f54544f, 0x41433130, 0xc809fe02, 0x0809fe02, 0x2356524d, 0x67696d70,
1931 0x3c435058, 0x28445746, 0x424f4d53, 0x49544f4c, 0x72746664, 0x63616666, 0x802a5fd7, 0x762f3101
1934 // string, with groups of 5 characters being 1 element in the array
1935 static const char * __CFBundleExtensionsArray
=
1936 "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "mach\0" "pef\0\0" "pef\0\0"
1937 "elf\0\0" "jpeg\0" "tiff\0" "tiff\0" "gif\0\0" "png\0\0" "icns\0" "ico\0\0"
1938 "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"
1939 "psd\0\0" "mpeg\0" "mpeg\0" "mid\0\0" "zip\0\0" "sit\0\0" "sit\0\0" "sit\0\0"
1940 "sit\0\0" "sit\0\0" "cpio\0" "html\0" "ps\0\0\0""ole\0\0" "uu\0\0\0""ync\0\0"
1941 "dmg\0\0" "wmv\0\0" "jp2\0\0" "doc\0\0" "xls\0\0" "xls\0\0" "ogg\0\0" "flac\0"
1942 "ttf\0\0" "ttf\0\0" "otf\0\0" "dwg\0\0" "dgn\0\0" "dgn\0\0" "wrl\0\0" "xcf\0\0"
1943 "cpx\0\0" "dwf\0\0" "bom\0\0" "lit\0\0" "rtfd\0" "caf\0\0" "cin\0\0" "exr\0\0";
1945 static const char * __CFBundleOOExtensionsArray
= "sxc\0\0" "sxd\0\0" "sxg\0\0" "sxi\0\0" "sxm\0\0" "sxw\0\0";
1946 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";
1948 #define EXTENSION_LENGTH 5
1949 #define NUM_EXTENSIONS 64
1950 #define MAGIC_BYTES_TO_READ 512
1951 #define DMG_BYTES_TO_READ 512
1952 #define ZIP_BYTES_TO_READ 1024
1953 #define OLE_BYTES_TO_READ 512
1954 #define X11_BYTES_TO_READ 4096
1955 #define IMAGE_INFO_BYTES_TO_READ 4096
1957 #if defined(BINARY_SUPPORT_DYLD)
1959 CF_INLINE
uint32_t _CFBundleSwapInt32Conditional(uint32_t arg
, Boolean swap
) {return swap
? CFSwapInt32(arg
) : arg
;}
1960 CF_INLINE
uint32_t _CFBundleSwapInt64Conditional(uint64_t arg
, Boolean swap
) {return swap
? CFSwapInt64(arg
) : arg
;}
1962 static CFMutableDictionaryRef
_CFBundleCreateInfoDictFromData(const char *bytes
, uint32_t length
) {
1963 CFMutableDictionaryRef result
= NULL
;
1964 CFDataRef infoData
= NULL
;
1965 if (bytes
&& 0 < length
) {
1966 infoData
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, (uint8_t *)bytes
, length
, kCFAllocatorNull
);
1968 result
= (CFMutableDictionaryRef
)CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault
, infoData
, kCFPropertyListMutableContainers
, NULL
);
1969 if (result
&& CFDictionaryGetTypeID() != CFGetTypeID(result
)) {
1973 CFRelease(infoData
);
1975 if (!result
) result
= CFDictionaryCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
1977 if (result
) _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef
)result
);
1981 static char *_CFBundleGetSectData(const char *segname
, const char *sectname
, unsigned long *size
) {
1982 char *retval
= NULL
;
1983 unsigned long localSize
= 0;
1984 uint32_t i
, numImages
= _dyld_image_count();
1985 const void *mhp
= (const void *)_NSGetMachExecuteHeader();
1987 for (i
= 0; i
< numImages
; i
++) {
1988 if (mhp
== (void *)_dyld_get_image_header(i
)) {
1990 const struct section_64
*sp
= getsectbynamefromheader_64((const struct mach_header_64
*)mhp
, segname
, sectname
);
1992 retval
= (char *)(sp
->addr
+ _dyld_get_image_vmaddr_slide(i
));
1993 localSize
= (unsigned long)sp
->size
;
1995 #else /* __LP64__ */
1996 const struct section
*sp
= getsectbynamefromheader((const struct mach_header
*)mhp
, segname
, sectname
);
1998 retval
= (char *)(sp
->addr
+ _dyld_get_image_vmaddr_slide(i
));
1999 localSize
= (unsigned long)sp
->size
;
2001 #endif /* __LP64__ */
2005 if (size
) *size
= localSize
;
2009 static CFMutableDictionaryRef
_CFBundleCreateInfoDictFromMainExecutable() {
2011 unsigned long length
= 0;
2012 if (getsegbyname(TEXT_SEGMENT
)) bytes
= _CFBundleGetSectData(TEXT_SEGMENT
, PLIST_SECTION
, &length
);
2013 return _CFBundleCreateInfoDictFromData(bytes
, length
);
2016 static Boolean
_CFBundleGrokObjCImageInfoFromMainExecutable(uint32_t *objcVersion
, uint32_t *objcFlags
) {
2017 Boolean retval
= false;
2018 uint32_t localVersion
= 0, localFlags
= 0;
2020 unsigned long length
= 0;
2022 if (getsegbyname(OBJC_SEGMENT_64
)) bytes
= _CFBundleGetSectData(OBJC_SEGMENT_64
, IMAGE_INFO_SECTION_64
, &length
);
2023 #else /* __LP64__ */
2024 if (getsegbyname(OBJC_SEGMENT
)) bytes
= _CFBundleGetSectData(OBJC_SEGMENT
, IMAGE_INFO_SECTION
, &length
);
2025 #endif /* __LP64__ */
2026 if (bytes
&& length
>= 8) {
2027 localVersion
= *(uint32_t *)bytes
;
2028 localFlags
= *(uint32_t *)(bytes
+ 4);
2031 if (objcVersion
) *objcVersion
= localVersion
;
2032 if (objcFlags
) *objcFlags
= localFlags
;
2036 static Boolean
_CFBundleGrokX11FromFile(int fd
, const void *bytes
, CFIndex length
, uint32_t offset
, Boolean swapped
, Boolean sixtyFour
) {
2037 static const char libX11name
[] = LIB_X11
;
2038 char *buffer
= NULL
;
2039 const char *loc
= NULL
;
2041 Boolean result
= false;
2043 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
2044 buffer
= malloc(X11_BYTES_TO_READ
);
2045 if (buffer
&& read(fd
, buffer
, X11_BYTES_TO_READ
) >= X11_BYTES_TO_READ
) loc
= buffer
;
2046 } else if (bytes
&& length
>= offset
+ X11_BYTES_TO_READ
) {
2047 loc
= bytes
+ offset
;
2051 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->ncmds
, swapped
);
2052 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->sizeofcmds
, swapped
);
2053 const char *startofcmds
= loc
+ sizeof(struct mach_header_64
);
2054 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2055 struct dylib_command
*dlp
= (struct dylib_command
*)startofcmds
;
2056 if (endofcmds
> loc
+ X11_BYTES_TO_READ
) endofcmds
= loc
+ X11_BYTES_TO_READ
;
2057 for (i
= 0; !result
&& i
< ncmds
&& startofcmds
<= (char *)dlp
&& (char *)dlp
< endofcmds
; i
++) {
2058 if (LC_LOAD_DYLIB
== _CFBundleSwapInt32Conditional(dlp
->cmd
, swapped
)) {
2059 uint32_t nameoffset
= _CFBundleSwapInt32Conditional(dlp
->dylib
.name
.offset
, swapped
);
2060 const char *name
= (const char *)dlp
+ nameoffset
;
2061 if (startofcmds
<= name
&& name
+ sizeof(libX11name
) <= endofcmds
&& 0 == strncmp(name
, libX11name
, sizeof(libX11name
) - 1)) result
= true;
2063 dlp
= (struct dylib_command
*)((char *)dlp
+ _CFBundleSwapInt32Conditional(dlp
->cmdsize
, swapped
));
2066 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->ncmds
, swapped
);
2067 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->sizeofcmds
, swapped
);
2068 const char *startofcmds
= loc
+ sizeof(struct mach_header
);
2069 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2070 struct dylib_command
*dlp
= (struct dylib_command
*)startofcmds
;
2071 if (endofcmds
> loc
+ X11_BYTES_TO_READ
) endofcmds
= loc
+ X11_BYTES_TO_READ
;
2072 for (i
= 0; !result
&& i
< ncmds
&& startofcmds
<= (char *)dlp
&& (char *)dlp
< endofcmds
; i
++) {
2073 if (LC_LOAD_DYLIB
== _CFBundleSwapInt32Conditional(dlp
->cmd
, swapped
)) {
2074 uint32_t nameoffset
= _CFBundleSwapInt32Conditional(dlp
->dylib
.name
.offset
, swapped
);
2075 const char *name
= (const char *)dlp
+ nameoffset
;
2076 if (startofcmds
<= name
&& name
+ sizeof(libX11name
) <= endofcmds
&& 0 == strncmp(name
, libX11name
, sizeof(libX11name
) - 1)) result
= true;
2078 dlp
= (struct dylib_command
*)((char *)dlp
+ _CFBundleSwapInt32Conditional(dlp
->cmdsize
, swapped
));
2082 if (buffer
) free(buffer
);
2086 static CFDictionaryRef
_CFBundleCreateInfoDictFromFile(int fd
, const void *bytes
, CFIndex length
, uint32_t offset
, Boolean swapped
, Boolean sixtyFour
) {
2087 struct statinfo statBuf
;
2088 off_t fileLength
= 0;
2089 char *maploc
= NULL
;
2092 CFDictionaryRef result
= NULL
;
2093 Boolean foundit
= false;
2094 if (fd
>= 0 && fstat(fd
, &statBuf
) == 0 && (maploc
= mmap(0, statBuf
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0)) != (void *)-1) {
2096 fileLength
= statBuf
.st_size
;
2099 fileLength
= length
;
2101 if (fileLength
> offset
+ sizeof(struct mach_header_64
)) {
2103 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)(loc
+ offset
))->ncmds
, swapped
);
2104 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)(loc
+ offset
))->sizeofcmds
, swapped
);
2105 const char *startofcmds
= loc
+ offset
+ sizeof(struct mach_header_64
);
2106 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2107 struct segment_command_64
*sgp
= (struct segment_command_64
*)startofcmds
;
2108 if (endofcmds
> loc
+ fileLength
) endofcmds
= loc
+ fileLength
;
2109 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2110 if (LC_SEGMENT_64
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2111 struct section_64
*sp
= (struct section_64
*)((char *)sgp
+ sizeof(struct segment_command_64
));
2112 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2113 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2114 if (0 == strncmp(sp
->sectname
, PLIST_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, TEXT_SEGMENT
, sizeof(sp
->segname
))) {
2115 uint64_t sectlength64
= _CFBundleSwapInt64Conditional(sp
->size
, swapped
);
2116 uint32_t sectlength
= (uint32_t)(sectlength64
& 0xffffffff);
2117 uint32_t sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2118 const char *sectbytes
= loc
+ offset
+ sectoffset
;
2119 // we don't support huge-sized plists
2120 if (sectlength64
<= 0xffffffff && loc
<= sectbytes
&& sectbytes
+ sectlength
<= loc
+ fileLength
) result
= (CFDictionaryRef
)_CFBundleCreateInfoDictFromData(sectbytes
, sectlength
);
2123 sp
= (struct section_64
*)((char *)sp
+ sizeof(struct section_64
));
2126 sgp
= (struct segment_command_64
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2129 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)(loc
+ offset
))->ncmds
, swapped
);
2130 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)(loc
+ offset
))->sizeofcmds
, swapped
);
2131 const char *startofcmds
= loc
+ offset
+ sizeof(struct mach_header
);
2132 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2133 struct segment_command
*sgp
= (struct segment_command
*)startofcmds
;
2134 if (endofcmds
> loc
+ fileLength
) endofcmds
= loc
+ fileLength
;
2135 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2136 if (LC_SEGMENT
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2137 struct section
*sp
= (struct section
*)((char *)sgp
+ sizeof(struct segment_command
));
2138 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2139 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2140 if (0 == strncmp(sp
->sectname
, PLIST_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, TEXT_SEGMENT
, sizeof(sp
->segname
))) {
2141 uint32_t sectlength
= _CFBundleSwapInt32Conditional(sp
->size
, swapped
);
2142 uint32_t sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2143 const char *sectbytes
= loc
+ offset
+ sectoffset
;
2144 if (loc
<= sectbytes
&& sectbytes
+ sectlength
<= loc
+ fileLength
) result
= (CFDictionaryRef
)_CFBundleCreateInfoDictFromData(sectbytes
, sectlength
);
2147 sp
= (struct section
*)((char *)sp
+ sizeof(struct section
));
2150 sgp
= (struct segment_command
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2154 if (maploc
) munmap(maploc
, statBuf
.st_size
);
2158 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
) {
2159 uint32_t sectlength
= 0, sectoffset
= 0, localVersion
= 0, localFlags
= 0;
2160 char *buffer
= NULL
;
2162 const char *loc
= NULL
;
2164 Boolean foundit
= false, localHasObjc
= false;
2166 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
2167 buffer
= malloc(IMAGE_INFO_BYTES_TO_READ
);
2168 if (buffer
&& read(fd
, buffer
, IMAGE_INFO_BYTES_TO_READ
) >= IMAGE_INFO_BYTES_TO_READ
) loc
= buffer
;
2169 } else if (bytes
&& length
>= offset
+ IMAGE_INFO_BYTES_TO_READ
) {
2170 loc
= bytes
+ offset
;
2174 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->ncmds
, swapped
);
2175 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header_64
*)loc
)->sizeofcmds
, swapped
);
2176 const char *startofcmds
= loc
+ sizeof(struct mach_header_64
);
2177 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2178 struct segment_command_64
*sgp
= (struct segment_command_64
*)startofcmds
;
2179 if (endofcmds
> loc
+ IMAGE_INFO_BYTES_TO_READ
) endofcmds
= loc
+ IMAGE_INFO_BYTES_TO_READ
;
2180 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2181 if (LC_SEGMENT_64
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2182 struct section_64
*sp
= (struct section_64
*)((char *)sgp
+ sizeof(struct segment_command_64
));
2183 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2184 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2185 if (0 == strncmp(sp
->segname
, OBJC_SEGMENT_64
, sizeof(sp
->segname
))) localHasObjc
= true;
2186 if (0 == strncmp(sp
->sectname
, IMAGE_INFO_SECTION_64
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, OBJC_SEGMENT_64
, sizeof(sp
->segname
))) {
2187 uint64_t sectlength64
= _CFBundleSwapInt64Conditional(sp
->size
, swapped
);
2188 sectlength
= (uint32_t)(sectlength64
& 0xffffffff);
2189 sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2192 sp
= (struct section_64
*)((char *)sp
+ sizeof(struct section_64
));
2195 sgp
= (struct segment_command_64
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2198 uint32_t ncmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->ncmds
, swapped
);
2199 uint32_t sizeofcmds
= _CFBundleSwapInt32Conditional(((struct mach_header
*)loc
)->sizeofcmds
, swapped
);
2200 const char *startofcmds
= loc
+ sizeof(struct mach_header
);
2201 const char *endofcmds
= startofcmds
+ sizeofcmds
;
2202 struct segment_command
*sgp
= (struct segment_command
*)startofcmds
;
2203 if (endofcmds
> loc
+ IMAGE_INFO_BYTES_TO_READ
) endofcmds
= loc
+ IMAGE_INFO_BYTES_TO_READ
;
2204 for (i
= 0; !foundit
&& i
< ncmds
&& startofcmds
<= (char *)sgp
&& (char *)sgp
< endofcmds
; i
++) {
2205 if (LC_SEGMENT
== _CFBundleSwapInt32Conditional(sgp
->cmd
, swapped
)) {
2206 struct section
*sp
= (struct section
*)((char *)sgp
+ sizeof(struct segment_command
));
2207 uint32_t nsects
= _CFBundleSwapInt32Conditional(sgp
->nsects
, swapped
);
2208 for (j
= 0; !foundit
&& j
< nsects
&& startofcmds
<= (char *)sp
&& (char *)sp
< endofcmds
; j
++) {
2209 if (0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) localHasObjc
= true;
2210 if (0 == strncmp(sp
->sectname
, IMAGE_INFO_SECTION
, sizeof(sp
->sectname
)) && 0 == strncmp(sp
->segname
, OBJC_SEGMENT
, sizeof(sp
->segname
))) {
2211 sectlength
= _CFBundleSwapInt32Conditional(sp
->size
, swapped
);
2212 sectoffset
= _CFBundleSwapInt32Conditional(sp
->offset
, swapped
);
2215 sp
= (struct section
*)((char *)sp
+ sizeof(struct section
));
2218 sgp
= (struct segment_command
*)((char *)sgp
+ _CFBundleSwapInt32Conditional(sgp
->cmdsize
, swapped
));
2221 if (sectlength
>= 8) {
2222 if (fd
>= 0 && lseek(fd
, offset
+ sectoffset
, SEEK_SET
) == (off_t
)(offset
+ sectoffset
) && read(fd
, sectbuffer
, 8) >= 8) {
2223 localVersion
= _CFBundleSwapInt32Conditional(*(uint32_t *)sectbuffer
, swapped
);
2224 localFlags
= _CFBundleSwapInt32Conditional(*(uint32_t *)(sectbuffer
+ 4), swapped
);
2225 } else if (bytes
&& length
>= offset
+ sectoffset
+ 8) {
2226 localVersion
= _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes
+ offset
+ sectoffset
), swapped
);
2227 localFlags
= _CFBundleSwapInt32Conditional(*(uint32_t *)(bytes
+ offset
+ sectoffset
+ 4), swapped
);
2231 if (buffer
) free(buffer
);
2232 if (hasObjc
) *hasObjc
= localHasObjc
;
2233 if (objcVersion
) *objcVersion
= localVersion
;
2234 if (objcFlags
) *objcFlags
= localFlags
;
2237 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
) {
2238 CFIndex headerLength
= length
;
2239 unsigned char headerBuffer
[MAGIC_BYTES_TO_READ
];
2240 UInt32 machtype
= UNKNOWN_FILETYPE
, magic
, numFatHeaders
, maxFatHeaders
, i
;
2241 unsigned char buffer
[sizeof(struct mach_header_64
)];
2242 const unsigned char *moreBytes
= NULL
;
2243 const NXArchInfo
*archInfo
= NXGetLocalArchInfo();
2244 SInt32 curArch
= _CFBundleCurrentArchitecture();
2246 struct fat_arch
*fat
= NULL
;
2248 if (isX11
) *isX11
= false;
2249 if (architectures
) *architectures
= NULL
;
2250 if (infodict
) *infodict
= NULL
;
2251 if (hasObjc
) *hasObjc
= false;
2252 if (objcVersion
) *objcVersion
= 0;
2253 if (objcFlags
) *objcFlags
= 0;
2255 if (headerLength
> MAGIC_BYTES_TO_READ
) headerLength
= MAGIC_BYTES_TO_READ
;
2256 (void)memmove(headerBuffer
, bytes
, headerLength
);
2258 for (i
= 0; i
< headerLength
; i
+= 4) *(UInt32
*)(headerBuffer
+ i
) = CFSwapInt32(*(UInt32
*)(headerBuffer
+ i
));
2260 numFatHeaders
= ((struct fat_header
*)headerBuffer
)->nfat_arch
;
2261 maxFatHeaders
= (headerLength
- sizeof(struct fat_header
)) / sizeof(struct fat_arch
);
2262 if (numFatHeaders
> maxFatHeaders
) numFatHeaders
= maxFatHeaders
;
2263 if (numFatHeaders
> 0) {
2264 if (archInfo
) fat
= NXFindBestFatArch(archInfo
->cputype
, archInfo
->cpusubtype
, (struct fat_arch
*)(headerBuffer
+ sizeof(struct fat_header
)), numFatHeaders
);
2265 if (!fat
&& curArch
!= 0) fat
= NXFindBestFatArch((cpu_type_t
)curArch
, (cpu_subtype_t
)0, (struct fat_arch
*)(headerBuffer
+ sizeof(struct fat_header
)), numFatHeaders
);
2266 if (!fat
) fat
= (struct fat_arch
*)(headerBuffer
+ sizeof(struct fat_header
));
2267 if (architectures
) {
2268 CFMutableArrayRef mutableArchitectures
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
2269 for (i
= 0; i
< numFatHeaders
; i
++) {
2270 CFNumberRef architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, headerBuffer
+ sizeof(struct fat_header
) + i
* sizeof(struct fat_arch
));
2271 if (CFArrayGetFirstIndexOfValue(mutableArchitectures
, CFRangeMake(0, CFArrayGetCount(mutableArchitectures
)), architecture
) < 0) CFArrayAppendValue(mutableArchitectures
, architecture
);
2272 CFRelease(architecture
);
2274 *architectures
= (CFArrayRef
)mutableArchitectures
;
2278 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
)) {
2280 } else if (bytes
&& (uint32_t)length
>= fat
->offset
+ sizeof(struct mach_header_64
)) {
2281 moreBytes
= bytes
+ fat
->offset
;
2284 magic
= *((UInt32
*)moreBytes
);
2285 if (MH_MAGIC
== magic
) {
2286 machtype
= ((struct mach_header
*)moreBytes
)->filetype
;
2287 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, false, false);
2288 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, false, false);
2289 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, false, false, hasObjc
, objcVersion
, objcFlags
);
2290 } else if (MH_CIGAM
== magic
) {
2291 machtype
= CFSwapInt32(((struct mach_header
*)moreBytes
)->filetype
);
2292 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, true, false);
2293 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, true, false);
2294 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, true, false, hasObjc
, objcVersion
, objcFlags
);
2295 } else if (MH_MAGIC_64
== magic
) {
2296 machtype
= ((struct mach_header_64
*)moreBytes
)->filetype
;
2297 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, false, true);
2298 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, false, true);
2299 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, false, true, hasObjc
, objcVersion
, objcFlags
);
2300 } else if (MH_CIGAM_64
== magic
) {
2301 machtype
= CFSwapInt32(((struct mach_header_64
*)moreBytes
)->filetype
);
2302 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, fat
->offset
, true, true);
2303 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, fat
->offset
, true, true);
2304 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, fat
->offset
, true, true, hasObjc
, objcVersion
, objcFlags
);
2311 static UInt32
_CFBundleGrokMachType(int fd
, const void *bytes
, CFIndex length
, Boolean
*isX11
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2312 unsigned int magic
= *((UInt32
*)bytes
), machtype
= UNKNOWN_FILETYPE
, cputype
;
2313 CFNumberRef architecture
= NULL
;
2315 if (isX11
) *isX11
= false;
2316 if (architectures
) *architectures
= NULL
;
2317 if (infodict
) *infodict
= NULL
;
2318 if (hasObjc
) *hasObjc
= false;
2319 if (objcVersion
) *objcVersion
= 0;
2320 if (objcFlags
) *objcFlags
= 0;
2321 if (MH_MAGIC
== magic
) {
2322 machtype
= ((struct mach_header
*)bytes
)->filetype
;
2323 cputype
= ((struct mach_header
*)bytes
)->cputype
;
2324 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2325 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, false, false);
2326 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, 0, false, false);
2327 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, false, false, hasObjc
, objcVersion
, objcFlags
);
2328 } else if (MH_CIGAM
== magic
) {
2329 machtype
= CFSwapInt32(((struct mach_header
*)bytes
)->filetype
);
2330 cputype
= CFSwapInt32(((struct mach_header
*)bytes
)->cputype
);
2331 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2332 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, true, false);
2333 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, 0, true, false);
2334 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, true, false, hasObjc
, objcVersion
, objcFlags
);
2335 } else if (MH_MAGIC_64
== magic
) {
2336 machtype
= ((struct mach_header_64
*)bytes
)->filetype
;
2337 cputype
= ((struct mach_header_64
*)bytes
)->cputype
;
2338 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2339 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, false, true);
2340 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, 0, false, true);
2341 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, false, true, hasObjc
, objcVersion
, objcFlags
);
2342 } else if (MH_CIGAM_64
== magic
) {
2343 machtype
= CFSwapInt32(((struct mach_header_64
*)bytes
)->filetype
);
2344 cputype
= CFSwapInt32(((struct mach_header_64
*)bytes
)->cputype
);
2345 if (architectures
) architecture
= CFNumberCreate(kCFAllocatorSystemDefault
, kCFNumberSInt32Type
, &cputype
);
2346 if (isX11
&& MH_EXECUTE
== machtype
) *isX11
= _CFBundleGrokX11FromFile(fd
, bytes
, length
, 0, true, true);
2347 if (infodict
) *infodict
= _CFBundleCreateInfoDictFromFile(fd
, bytes
, length
, 0, true, true);
2348 if (hasObjc
|| objcVersion
|| objcFlags
) _CFBundleGrokObjcImageInfoFromFile(fd
, bytes
, length
, 0, true, true, hasObjc
, objcVersion
, objcFlags
);
2349 } else if (FAT_MAGIC
== magic
) {
2350 machtype
= _CFBundleGrokMachTypeForFatFile(fd
, bytes
, length
, false, isX11
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2351 } else if (FAT_CIGAM
== magic
) {
2352 machtype
= _CFBundleGrokMachTypeForFatFile(fd
, bytes
, length
, true, isX11
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2353 } else if (PEF_MAGIC
== magic
|| PEF_CIGAM
== magic
) {
2354 machtype
= PEF_FILETYPE
;
2356 if (architectures
&& architecture
) *architectures
= CFArrayCreate(kCFAllocatorSystemDefault
, (const void **)&architecture
, 1, &kCFTypeArrayCallBacks
);
2357 if (architecture
) CFRelease(architecture
);
2361 #endif /* BINARY_SUPPORT_DYLD */
2363 static Boolean
_CFBundleGrokFileTypeForZipMimeType(const unsigned char *bytes
, CFIndex length
, const char **ext
) {
2364 unsigned namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 26))), extralength
= CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 28)));
2365 const unsigned char *data
= bytes
+ 30 + namelength
+ extralength
;
2367 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))) {
2368 data
+= ('.' == *(data
+ 15)) ? 16 : 18;
2369 if (0 == ustrncasecmp(data
, "sun.xml.", 8)) {
2371 if (0 == ustrncasecmp(data
, "calc", 4)) i
= 0;
2372 else if (0 == ustrncasecmp(data
, "draw", 4)) i
= 1;
2373 else if (0 == ustrncasecmp(data
, "writer.global", 13)) i
= 2;
2374 else if (0 == ustrncasecmp(data
, "impress", 7)) i
= 3;
2375 else if (0 == ustrncasecmp(data
, "math", 4)) i
= 4;
2376 else if (0 == ustrncasecmp(data
, "writer", 6)) i
= 5;
2377 if (i
>= 0 && ext
) *ext
= __CFBundleOOExtensionsArray
+ i
* EXTENSION_LENGTH
;
2378 } else if (0 == ustrncasecmp(data
, "oasis.opendocument.", 19)) {
2380 if (0 == ustrncasecmp(data
, "chart", 5)) i
= 0;
2381 else if (0 == ustrncasecmp(data
, "formula", 7)) i
= 1;
2382 else if (0 == ustrncasecmp(data
, "graphics", 8)) i
= 2;
2383 else if (0 == ustrncasecmp(data
, "text-web", 8)) i
= 3;
2384 else if (0 == ustrncasecmp(data
, "image", 5)) i
= 4;
2385 else if (0 == ustrncasecmp(data
, "text-master", 11)) i
= 5;
2386 else if (0 == ustrncasecmp(data
, "presentation", 12)) i
= 6;
2387 else if (0 == ustrncasecmp(data
, "spreadsheet", 11)) i
= 7;
2388 else if (0 == ustrncasecmp(data
, "text", 4)) i
= 8;
2389 if (i
>= 0 && ext
) *ext
= __CFBundleODExtensionsArray
+ i
* EXTENSION_LENGTH
;
2391 } else if (bytes
< data
&& data
+ 41 <= bytes
+ length
&& 8 == CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ 8))) && 0x4b2c28c8 == CFSwapInt32HostToBig(*((UInt32
*)data
)) && 0xc94c4e2c == CFSwapInt32HostToBig(*((UInt32
*)(data
+ 4)))) {
2392 // AbiWord compressed mimetype odt
2393 if (ext
) *ext
= "odt";
2394 // almost certainly this should set i to 0 but I don't want to upset the apple cart now
2395 } else if (bytes
< data
&& data
+ 29 <= bytes
+ length
&& (0 == ustrncasecmp(data
, "application/oebps-package+xml", 29))) {
2396 // epub, official epub 3 mime type
2397 if (ext
) *ext
= "epub";
2399 } else if (bytes
< data
&& data
+ 20 <= bytes
+ length
&& (0 == ustrncasecmp(data
, "application/epub+zip", 20))) {
2400 // epub, unofficial epub 2 mime type
2401 if (ext
) *ext
= "epub";
2407 static const char *_CFBundleGrokFileTypeForZipFile(int fd
, const unsigned char *bytes
, CFIndex length
, off_t fileLength
) {
2408 const char *ext
= "zip";
2409 const unsigned char *moreBytes
= NULL
;
2410 unsigned char *buffer
= NULL
;
2412 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;
2415 for (i
= 0; !foundMimetype
&& i
+ 30 < length
; i
++) {
2416 if (0x50 == bytes
[i
] && 0x4b == bytes
[i
+ 1]) {
2417 unsigned namelength
= 0, offset
= 0;
2418 if (0x01 == bytes
[i
+ 2] && 0x02 == bytes
[i
+ 3]) {
2419 namelength
= (unsigned)CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ i
+ 28)));
2421 } else if (0x03 == bytes
[i
+ 2] && 0x04 == bytes
[i
+ 3]) {
2422 namelength
= (unsigned)CFSwapInt16HostToLittle(*((UInt16
*)(bytes
+ i
+ 26)));
2425 if (offset
> 0 && (CFIndex
)(i
+ offset
+ namelength
) <= length
) {
2426 //printf("%.*s\n", namelength, bytes + i + offset);
2427 if (8 == namelength
&& 30 == offset
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "mimetype", 8)) foundMimetype
= _CFBundleGrokFileTypeForZipMimeType(bytes
+ i
, length
- i
, &ext
);
2428 else if (9 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/", 9)) hasMetaInf
= true;
2429 else if (11 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "content.xml", 11)) hasContentXML
= true;
2430 else if (11 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "_rels/.rels", 11)) hasRels
= true;
2431 else if (19 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "[Content_Types].xml", 19)) hasContentTypes
= true;
2432 else if (20 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/MANIFEST.MF", 20)) hasManifestMF
= true;
2433 else if (21 == namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "META-INF/manifest.xml", 21)) hasManifestXML
= true;
2434 else if (4 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".opf", 4)) hasOPF
= true;
2435 else if (4 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".sml", 4)) hasSMIL
= true;
2436 else if (5 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 5, ".smil", 5)) hasSMIL
= true;
2437 else if (7 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "xl/", 3) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2438 else if (8 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "ppt/", 4) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2439 else if (9 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "word/", 5) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasWordDocument
= true;
2440 else if (10 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "excel/", 6) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2441 else if (15 < namelength
&& 0 == ustrncasecmp(bytes
+ i
+ offset
, "powerpoint/", 11) && 0 == ustrncasecmp(bytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2442 i
+= offset
+ namelength
- 1;
2447 if (!foundMimetype
) {
2448 if (fileLength
>= ZIP_BYTES_TO_READ
) {
2449 if (fd
>= 0 && lseek(fd
, fileLength
- ZIP_BYTES_TO_READ
, SEEK_SET
) == fileLength
- ZIP_BYTES_TO_READ
) {
2450 buffer
= (unsigned char *)malloc(ZIP_BYTES_TO_READ
);
2451 if (buffer
&& read(fd
, buffer
, ZIP_BYTES_TO_READ
) >= ZIP_BYTES_TO_READ
) moreBytes
= buffer
;
2452 } else if (bytes
&& length
>= ZIP_BYTES_TO_READ
) {
2453 moreBytes
= bytes
+ length
- ZIP_BYTES_TO_READ
;
2457 for (i
= 0; i
+ 30 < ZIP_BYTES_TO_READ
; i
++) {
2458 if (0x50 == moreBytes
[i
] && 0x4b == moreBytes
[i
+ 1]) {
2459 unsigned namelength
= 0, offset
= 0;
2460 if (0x01 == moreBytes
[i
+ 2] && 0x02 == moreBytes
[i
+ 3]) {
2461 namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(moreBytes
+ i
+ 28)));
2463 } else if (0x03 == moreBytes
[i
+ 2] && 0x04 == moreBytes
[i
+ 3]) {
2464 namelength
= CFSwapInt16HostToLittle(*((UInt16
*)(moreBytes
+ i
+ 26)));
2467 if (offset
> 0 && i
+ offset
+ namelength
<= ZIP_BYTES_TO_READ
) {
2468 //printf("%.*s\n", namelength, moreBytes + i + offset);
2469 if (9 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/", 9)) hasMetaInf
= true;
2470 else if (11 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "content.xml", 11)) hasContentXML
= true;
2471 else if (11 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "_rels/.rels", 11)) hasRels
= true;
2472 else if (19 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "[Content_Types].xml", 19)) hasContentTypes
= true;
2473 else if (20 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/MANIFEST.MF", 20)) hasManifestMF
= true;
2474 else if (21 == namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "META-INF/manifest.xml", 21)) hasManifestXML
= true;
2475 else if (4 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".opf", 4)) hasOPF
= true;
2476 else if (4 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".sml", 4)) hasSMIL
= true;
2477 else if (5 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 5, ".smil", 5)) hasSMIL
= true;
2478 else if (7 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "xl/", 3) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2479 else if (8 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "ppt/", 4) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2480 else if (9 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "word/", 5) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasWordDocument
= true;
2481 else if (10 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "excel/", 6) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasExcelDocument
= true;
2482 else if (15 < namelength
&& 0 == ustrncasecmp(moreBytes
+ i
+ offset
, "powerpoint/", 11) && 0 == ustrncasecmp(moreBytes
+ i
+ offset
+ namelength
- 4, ".xml", 4)) hasPowerPointDocument
= true;
2483 i
+= offset
+ namelength
- 1;
2488 //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);
2489 if (hasManifestMF
) ext
= "jar";
2490 else if ((hasRels
|| hasContentTypes
) && hasWordDocument
) ext
= "docx";
2491 else if ((hasRels
|| hasContentTypes
) && hasExcelDocument
) ext
= "xlsx";
2492 else if ((hasRels
|| hasContentTypes
) && hasPowerPointDocument
) ext
= "pptx";
2493 else if (hasManifestXML
|| hasContentXML
) ext
= "odt";
2494 else if (hasMetaInf
) ext
= "jar";
2495 else if (hasOPF
&& hasSMIL
) ext
= "dtb";
2496 else if (hasOPF
) ext
= "oeb";
2498 if (buffer
) free(buffer
);
2503 static Boolean
_CFBundleCheckOLEName(const char *name
, const char *bytes
, unsigned length
) {
2504 Boolean retval
= true;
2506 for (j
= 0; retval
&& j
< length
; j
++) if (bytes
[2 * j
] != name
[j
]) retval
= false;
2510 static const char *_CFBundleGrokFileTypeForOLEFile(int fd
, const void *bytes
, CFIndex length
, off_t offset
) {
2511 const char *ext
= "ole", *moreBytes
= NULL
;
2512 char *buffer
= NULL
;
2514 if (fd
>= 0 && lseek(fd
, offset
, SEEK_SET
) == (off_t
)offset
) {
2515 buffer
= (char *)malloc(OLE_BYTES_TO_READ
);
2516 if (buffer
&& read(fd
, buffer
, OLE_BYTES_TO_READ
) >= OLE_BYTES_TO_READ
) moreBytes
= buffer
;
2517 } else if (bytes
&& length
>= offset
+ OLE_BYTES_TO_READ
) {
2518 moreBytes
= (char *)bytes
+ offset
;
2521 Boolean foundit
= false;
2523 for (i
= 0; !foundit
&& i
< 4; i
++) {
2524 char namelength
= moreBytes
[128 * i
+ 64] / 2;
2526 if (sizeof(XLS_NAME
) == namelength
&& _CFBundleCheckOLEName(XLS_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "xls";
2527 else if (sizeof(XLS_NAME2
) == namelength
&& _CFBundleCheckOLEName(XLS_NAME2
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "xls";
2528 else if (sizeof(DOC_NAME
) == namelength
&& _CFBundleCheckOLEName(DOC_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "doc";
2529 else if (sizeof(PPT_NAME
) == namelength
&& _CFBundleCheckOLEName(PPT_NAME
, moreBytes
+ 128 * i
, namelength
- 1)) ext
= "ppt";
2530 else foundit
= false;
2533 if (buffer
) free(buffer
);
2537 static Boolean
_CFBundleGrokFileType(CFURLRef url
, CFDataRef data
, CFStringRef
*extension
, UInt32
*machtype
, CFArrayRef
*architectures
, CFDictionaryRef
*infodict
, Boolean
*hasObjc
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2539 const unsigned char *bytes
= NULL
;
2540 unsigned char buffer
[MAGIC_BYTES_TO_READ
];
2541 CFIndex i
, length
= 0;
2542 off_t fileLength
= 0;
2543 const char *ext
= NULL
;
2544 UInt32 mt
= UNKNOWN_FILETYPE
;
2545 #if defined(BINARY_SUPPORT_DYLD)
2546 Boolean isX11
= false;
2547 #endif /* BINARY_SUPPORT_DYLD */
2548 Boolean isFile
= false, isPlain
= true, isZero
= true, isSpace
= true, hasBOM
= false;
2549 // 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
2550 // ??? we do not distinguish between different wm types, returning wmv for any of wmv, wma, or asf
2551 // ??? we do not distinguish between ordinary documents and template versions (often there is no difference in file contents)
2552 // ??? the distinctions between docx, xlsx, and pptx may not be entirely reliable
2553 if (architectures
) *architectures
= NULL
;
2554 if (infodict
) *infodict
= NULL
;
2555 if (hasObjc
) *hasObjc
= false;
2556 if (objcVersion
) *objcVersion
= 0;
2557 if (objcFlags
) *objcFlags
= 0;
2559 Boolean gotPath
= FALSE
;
2560 char path
[CFMaxPathSize
];
2561 gotPath
= CFURLGetFileSystemRepresentation(url
, true, (uint8_t *)path
, CFMaxPathSize
);
2562 struct statinfo statBuf
;
2563 if (gotPath
&& stat(path
, &statBuf
) == 0 && (statBuf
.st_mode
& S_IFMT
) == S_IFREG
&& (fd
= open(path
, O_RDONLY
| CF_OPENFLGS
, 0777)) >= 0) {
2564 length
= read(fd
, buffer
, MAGIC_BYTES_TO_READ
);
2565 fileLength
= statBuf
.st_size
;
2570 if (!isFile
&& data
) {
2571 length
= CFDataGetLength(data
);
2572 fileLength
= (off_t
)length
;
2573 bytes
= CFDataGetBytePtr(data
);
2574 if (length
== 0) ext
= "txt";
2578 UInt32 magic
= CFSwapInt32HostToBig(*((UInt32
*)bytes
));
2579 for (i
= 0; !ext
&& i
< NUM_EXTENSIONS
; i
++) {
2580 if (__CFBundleMagicNumbersArray
[i
] == magic
) ext
= __CFBundleExtensionsArray
+ i
* EXTENSION_LENGTH
;
2583 if (0xcafebabe == magic
&& 8 <= length
&& 0 != *((UInt16
*)(bytes
+ 4))) ext
= "class";
2584 #if defined(BINARY_SUPPORT_DYLD)
2585 else if ((int)sizeof(struct mach_header_64
) <= length
) mt
= _CFBundleGrokMachType(fd
, bytes
, length
, extension
? &isX11
: NULL
, architectures
, infodict
, hasObjc
, objcVersion
, objcFlags
);
2587 if (MH_OBJECT
== mt
) ext
= "o";
2588 else if (MH_EXECUTE
== mt
) ext
= isX11
? "x11app" : "tool";
2589 else if (PEF_FILETYPE
== mt
) ext
= "pef";
2590 else if (MH_CORE
== mt
) ext
= "core";
2591 else if (MH_DYLIB
== mt
) ext
= "dylib";
2592 else if (MH_BUNDLE
== mt
) ext
= "bundle";
2593 #endif /* BINARY_SUPPORT_DYLD */
2594 else if (0x7b5c7274 == magic
&& (6 > length
|| 'f' != bytes
[4])) ext
= NULL
;
2595 else if (0x25504446 == magic
&& (6 > length
|| '-' != bytes
[4])) ext
= NULL
;
2596 else if (0x00010000 == magic
&& (6 > length
|| 0 != bytes
[4])) ext
= NULL
;
2597 else if (0x47494638 == magic
&& (6 > length
|| (0x3761 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))) && 0x3961 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4)))))) ext
= NULL
;
2598 else if (0x0000000c == magic
&& (6 > length
|| 0x6a50 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2599 else if (0x2356524d == magic
&& (6 > length
|| 0x4c20 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2600 else if (0x28445746 == magic
&& (6 > length
|| 0x2056 != CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))))) ext
= NULL
;
2601 else if (0x30373037 == magic
&& (6 > length
|| 0x30 != bytes
[4] || !isdigit(bytes
[5]))) ext
= NULL
;
2602 else if (0x41433130 == magic
&& (6 > length
|| 0x31 != bytes
[4] || !isdigit(bytes
[5]))) ext
= NULL
;
2603 else if (0x89504e47 == magic
&& (8 > length
|| 0x0d0a1a0a != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2604 else if (0x53747566 == magic
&& (8 > length
|| 0x66497420 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2605 else if (0x3026b275 == magic
&& (8 > length
|| 0x8e66cf11 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2606 else if (0x67696d70 == magic
&& (8 > length
|| 0x20786366 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2607 else if (0x424f4d53 == magic
&& (8 > length
|| 0x746f7265 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2608 else if (0x49544f4c == magic
&& (8 > length
|| 0x49544c53 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2609 else if (0x72746664 == magic
&& (8 > length
|| 0x00000000 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= NULL
;
2610 else if (0x3d796265 == magic
&& (12 > length
|| 0x67696e20 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || (0x6c696e65 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8))) && 0x70617274 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)))))) ext
= NULL
;
2611 else if (0x63616666 == magic
&& (12 > length
|| 0 != bytes
[4] || 0x64657363 != CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8))))) ext
= NULL
;
2612 else if (0x504b0304 == magic
) ext
= _CFBundleGrokFileTypeForZipFile(fd
, bytes
, length
, fileLength
);
2613 else if (0x25215053 == magic
) {
2614 if (11 <= length
&& 0 == ustrncmp(bytes
+ 4, "-Adobe-", 7)) ext
= "ps";
2615 else if (14 <= length
&& 0 == ustrncmp(bytes
+ 4, "-AdobeFont", 10)) ext
= "pfa";
2617 } else if (0x464f524d == magic
) {
2621 UInt32 iffMagic
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2622 if (0x41494646 == iffMagic
) ext
= "aiff";
2623 else if (0x414946 == iffMagic
) ext
= "aifc";
2625 } else if (0x52494646 == magic
) {
2629 UInt32 riffMagic
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2630 if (0x57415645 == riffMagic
) ext
= "wav";
2631 else if (0x41564920 == riffMagic
) ext
= "avi";
2633 } else if (0xd0cf11e0 == magic
) {
2635 if (52 <= length
) ext
= _CFBundleGrokFileTypeForOLEFile(fd
, bytes
, length
, 512 * (1 + CFSwapInt32HostToLittle(*((UInt32
*)(bytes
+ 48)))));
2636 } else if (0x62656769 == magic
) {
2639 if (76 <= length
&& 'n' == bytes
[4] && ' ' == bytes
[5] && isdigit(bytes
[6]) && isdigit(bytes
[7]) && isdigit(bytes
[8]) && ' ' == bytes
[9]) {
2640 CFIndex endOfLine
= 0;
2641 for (i
= 10; 0 == endOfLine
&& i
< length
; i
++) if ('\n' == bytes
[i
]) endOfLine
= i
;
2642 if (10 <= endOfLine
&& endOfLine
+ 62 < length
&& 'M' == bytes
[endOfLine
+ 1] && '\n' == bytes
[endOfLine
+ 62]) {
2644 for (i
= endOfLine
+ 1; ext
&& i
< endOfLine
+ 62; i
++) if (!isprint(bytes
[i
])) ext
= NULL
;
2649 if (extension
&& !ext
) {
2650 UInt16 shortMagic
= CFSwapInt16HostToBig(*((UInt16
*)bytes
));
2651 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";
2652 else if (8 <= length
&& (0x6d6f6f76 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x6d646174 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x77696465 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "mov";
2653 else if (8 <= length
&& (0x69647363 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x69646174 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "qtif";
2654 else if (8 <= length
&& 0x424f424f == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4)))) ext
= "cwk";
2655 else if (8 <= length
&& 0x62706c69 == magic
&& 0x7374 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 4))) && isdigit(bytes
[6]) && isdigit(bytes
[7])) {
2656 for (i
= 8; !ext
&& i
< 128 && i
+ 16 <= length
; i
++) {
2657 if (0 == ustrncmp(bytes
+ i
, "WebMainResource", 15)) ext
= "webarchive";
2659 if (!ext
) ext
= "plist";
2660 } else if (0 == shortMagic
&& 12 <= length
&& 0x66747970 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4)))) {
2661 // ??? may want more ftyp values
2662 UInt32 ftyp
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 8)));
2663 if (0x6d703431 == ftyp
|| 0x6d703432 == ftyp
|| 0x69736f6d == ftyp
|| 0x69736f32 == ftyp
) ext
= "mp4";
2664 else if (0x4d344120 == ftyp
) ext
= "m4a";
2665 else if (0x4d344220 == ftyp
) ext
= "m4b";
2666 else if (0x4d345020 == ftyp
) ext
= "m4p";
2667 else if (0x4d345620 == ftyp
|| 0x4d345648 == ftyp
|| 0x4d345650 == ftyp
) ext
= "m4v";
2668 else if (0x3367 == (ftyp
>> 16)) {
2669 UInt16 remainder
= (ftyp
& 0xffff);
2670 if (0x6536 == remainder
|| 0x6537 == remainder
|| 0x6736 == remainder
|| 0x7034 == remainder
|| 0x7035 == remainder
|| 0x7036 == remainder
|| 0x7236 == remainder
|| 0x7336 == remainder
|| 0x7337 == remainder
) ext
= "3gp";
2671 else if (0x3261 == remainder
) ext
= "3g2";
2673 } else if (0x424d == shortMagic
&& 18 <= length
) {
2674 UInt32 btyp
= CFSwapInt32HostToLittle(*((UInt32
*)(bytes
+ 14)));
2675 if (40 == btyp
|| btyp
== 12 || btyp
== 64 || btyp
== 108 || btyp
== 124) ext
= "bmp";
2676 } else if (20 <= length
&& 0 == ustrncmp(bytes
+ 6, "%!PS-AdobeFont", 14)) ext
= "pfb";
2677 else if (40 <= length
&& 0x42696e48 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 34))) && 0x6578 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 38)))) ext
= "hqx";
2678 else if (128 <= length
&& 0x6d42494e == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 102)))) ext
= "bin";
2679 else if (128 <= length
&& 0 == bytes
[0] && 0 < bytes
[1] && bytes
[1] < 64 && 0 == bytes
[74] && 0 == bytes
[82] && 0 == (fileLength
% 128)) {
2680 UInt32 df
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 83))), rf
= CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 87))), blocks
= 1 + (df
+ 127) / 128 + (rf
+ 127) / 128;
2681 if (df
< 0x00800000 && rf
< 0x00800000 && 1 < blocks
&& (off_t
)(128 * blocks
) == fileLength
) ext
= "bin";
2682 } else if (265 <= length
&& 0x75737461 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 257))) && (0x72202000 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 261))) || 0x7200 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 261))))) ext
= "tar";
2683 else if (0xfeff == shortMagic
|| 0xfffe == shortMagic
) {
2685 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";
2686 } else if (0x1f9d == shortMagic
) ext
= "Z";
2687 else if (0x1f8b == shortMagic
) ext
= "gz";
2688 else if (0x71c7 == shortMagic
|| 0xc771 == shortMagic
) ext
= "cpio";
2689 else if (0xf702 == shortMagic
) ext
= "dvi";
2690 else if (0x01da == shortMagic
&& (0 == bytes
[2] || 1 == bytes
[2]) && (0 < bytes
[3] && 16 > bytes
[3])) ext
= "sgi";
2691 else if (0x2321 == shortMagic
) {
2692 CFIndex endOfLine
= 0, lastSlash
= 0;
2693 for (i
= 2; 0 == endOfLine
&& i
< length
; i
++) if ('\n' == bytes
[i
]) endOfLine
= i
;
2694 if (endOfLine
> 3) {
2695 for (i
= endOfLine
- 1; 0 == lastSlash
&& i
> 1; i
--) if ('/' == bytes
[i
]) lastSlash
= i
;
2696 if (lastSlash
> 0) {
2697 if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "perl", 4)) ext
= "pl";
2698 else if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "python", 6)) ext
= "py";
2699 else if (0 == ustrncmp(bytes
+ lastSlash
+ 1, "ruby", 4)) ext
= "rb";
2703 } else if (0xffd8 == shortMagic
&& 0xff == bytes
[2]) ext
= "jpeg";
2704 else if (0x4657 == shortMagic
&& 0x53 == bytes
[2]) ext
= "swf";
2705 else if (0x4357 == shortMagic
&& 0x53 == bytes
[2]) ext
= "swc";
2706 else if (0x4944 == shortMagic
&& '3' == bytes
[2] && 0x20 > bytes
[3]) ext
= "mp3";
2707 else if (0x425a == shortMagic
&& isdigit(bytes
[2]) && isdigit(bytes
[3])) ext
= "bz";
2708 else if (0x425a == shortMagic
&& 'h' == bytes
[2] && isdigit(bytes
[3]) && 8 <= length
&& (0x31415926 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))) || 0x17724538 == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 4))))) ext
= "bz2";
2709 else if (0x0011 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 2))) || 0x0012 == CFSwapInt16HostToBig(*((UInt16
*)(bytes
+ 2)))) ext
= "tfm";
2712 if (extension
&& !ext
) {
2713 //??? what about MacOSRoman?
2714 if (0xef == bytes
[0] && 0xbb == bytes
[1] && 0xbf == bytes
[2]) { // UTF-8 BOM
2718 for (i
= (hasBOM
? 3 : 0); (isPlain
|| isZero
) && !ext
&& i
< length
&& i
< 512; i
++) {
2720 if (isPlain
&& '<' == c
&& i
+ 14 <= length
&& 0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype html", 13)) ext
= "html";
2721 if (isSpace
&& '<' == c
&& i
+ 14 <= length
) {
2722 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)) {
2724 } else if (0 == ustrncasecmp(bytes
+ i
+ 1, "?xml", 4)) {
2725 for (i
+= 4; !ext
&& i
< 128 && i
+ 20 <= length
; i
++) {
2726 if ('<' == bytes
[i
]) {
2727 if (0 == ustrncasecmp(bytes
+ i
+ 1, "abiword", 7)) ext
= "abw";
2728 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype svg", 12)) ext
= "svg";
2729 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype rdf", 12)) ext
= "rdf";
2730 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype x3d", 12)) ext
= "x3d";
2731 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype html", 13)) ext
= "html";
2732 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype posingfont", 19)) ext
= "sfont";
2733 else if (0 == ustrncasecmp(bytes
+ i
+ 1, "!doctype plist", 14)) {
2734 for (i
+= 14; !ext
&& i
< 256 && i
+ 16 <= length
; i
++) {
2735 if (0 == ustrncmp(bytes
+ i
, "WebMainResource", 15)) ext
= "webarchive";
2737 if (!ext
) ext
= "plist";
2741 if (!ext
) ext
= "xml";
2744 if (0 != c
) isZero
= false;
2745 if (isZero
|| 0x7f <= c
|| (0x20 > c
&& !isspace(c
))) isPlain
= false;
2746 if (isZero
|| !isspace(c
)) isSpace
= false;
2750 if (16 <= length
&& 0 == ustrncmp(bytes
, "StartFontMetrics", 16)) ext
= "afm";
2752 } else if (isZero
&& length
>= MAGIC_BYTES_TO_READ
&& fileLength
>= 526) {
2754 if (lseek(fd
, 512, SEEK_SET
) == 512 && read(fd
, buffer
, MAGIC_BYTES_TO_READ
) >= 14) {
2755 if (0x001102ff == CFSwapInt32HostToBig(*((UInt32
*)(buffer
+ 10)))) ext
= "pict";
2758 if (526 <= length
&& 0x001102ff == CFSwapInt32HostToBig(*((UInt32
*)(bytes
+ 522)))) ext
= "pict";
2763 if (extension
&& (!ext
|| 0 == strcmp(ext
, "bz2")) && length
>= MAGIC_BYTES_TO_READ
&& fileLength
>= DMG_BYTES_TO_READ
) {
2765 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
) {
2766 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";
2769 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";
2773 if (extension
) *extension
= ext
? CFStringCreateWithCStringNoCopy(kCFAllocatorSystemDefault
, ext
, kCFStringEncodingUTF8
, kCFAllocatorNull
) : NULL
;
2774 if (machtype
) *machtype
= mt
;
2775 if (fd
>= 0) close(fd
);
2776 return (ext
? true : false);
2779 CFStringRef
_CFBundleCopyFileTypeForFileURL(CFURLRef url
) {
2780 CFStringRef extension
= NULL
;
2781 (void)_CFBundleGrokFileType(url
, NULL
, &extension
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2785 CFStringRef
_CFBundleCopyFileTypeForFileData(CFDataRef data
) {
2786 CFStringRef extension
= NULL
;
2787 (void)_CFBundleGrokFileType(NULL
, data
, &extension
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2791 CF_PRIVATE CFDictionaryRef
_CFBundleCopyInfoDictionaryInExecutable(CFURLRef url
) {
2792 CFDictionaryRef result
= NULL
;
2793 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, NULL
, &result
, NULL
, NULL
, NULL
);
2797 CF_PRIVATE CFArrayRef
_CFBundleCopyArchitecturesForExecutable(CFURLRef url
) {
2798 CFArrayRef result
= NULL
;
2799 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, &result
, NULL
, NULL
, NULL
, NULL
);
2803 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
2804 static Boolean
_CFBundleGetObjCImageInfoForExecutable(CFURLRef url
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
2805 Boolean retval
= false;
2806 (void)_CFBundleGrokFileType(url
, NULL
, NULL
, NULL
, NULL
, NULL
, &retval
, objcVersion
, objcFlags
);
2811 #if defined(BINARY_SUPPORT_DYLD)
2813 CF_PRIVATE __CFPBinaryType
_CFBundleGrokBinaryType(CFURLRef executableURL
) {
2814 // 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.
2815 __CFPBinaryType result
= executableURL
? __CFBundleUnreadableBinary
: __CFBundleNoBinary
;
2816 UInt32 machtype
= UNKNOWN_FILETYPE
;
2817 if (_CFBundleGrokFileType(executableURL
, NULL
, NULL
, &machtype
, NULL
, NULL
, NULL
, NULL
, NULL
)) {
2820 result
= __CFBundleDYLDExecutableBinary
;
2823 result
= __CFBundleDYLDBundleBinary
;
2826 result
= __CFBundleDYLDFrameworkBinary
;
2829 result
= __CFBundleCFMBinary
;
2836 #endif /* BINARY_SUPPORT_DYLD */
2838 void _CFBundleSetCFMConnectionID(CFBundleRef bundle
, void *connectionID
) {
2839 bundle
->_connectionCookie
= connectionID
;
2840 bundle
->_isLoaded
= true;
2843 static CFStringRef
_CFBundleCopyLastPathComponent(CFBundleRef bundle
) {
2844 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
);
2846 return CFSTR("<unknown>");
2848 CFStringRef str
= CFURLCopyFileSystemPath(bundleURL
, kCFURLPOSIXPathStyle
);
2849 UniChar buff
[CFMaxPathSize
];
2850 CFIndex buffLen
= CFStringGetLength(str
), startOfLastDir
= 0;
2852 CFRelease(bundleURL
);
2853 if (buffLen
> CFMaxPathSize
) buffLen
= CFMaxPathSize
;
2854 CFStringGetCharacters(str
, CFRangeMake(0, buffLen
), buff
);
2856 if (buffLen
> 0) startOfLastDir
= _CFStartOfLastPathComponent(buff
, buffLen
);
2857 return CFStringCreateWithCharacters(kCFAllocatorSystemDefault
, &(buff
[startOfLastDir
]), buffLen
- startOfLastDir
);
2860 static CFErrorRef
_CFBundleCreateErrorDebug(CFAllocatorRef allocator
, CFBundleRef bundle
, CFIndex code
, CFStringRef debugString
) {
2861 const void *userInfoKeys
[6], *userInfoValues
[6];
2862 CFIndex numKeys
= 0;
2863 CFURLRef bundleURL
= CFBundleCopyBundleURL(bundle
), absoluteURL
= CFURLCopyAbsoluteURL(bundleURL
), executableURL
= CFBundleCopyExecutableURL(bundle
);
2864 CFBundleRef bdl
= CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreFoundation"));
2865 CFStringRef bundlePath
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
), executablePath
= executableURL
? CFURLCopyFileSystemPath(executableURL
, PLATFORM_PATH_STYLE
) : NULL
, descFormat
= NULL
, desc
= NULL
, reason
= NULL
, suggestion
= NULL
;
2868 CFStringRef name
= (CFStringRef
)CFBundleGetValueForInfoDictionaryKey(bundle
, kCFBundleNameKey
);
2869 name
= name
? (CFStringRef
)CFRetain(name
) : _CFBundleCopyLastPathComponent(bundle
);
2870 if (CFBundleExecutableNotFoundError
== code
) {
2871 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
2872 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl
, CFSTR("The bundle\\U2019s executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
2873 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSFileNoSuchFileError");
2874 } else if (CFBundleExecutableNotLoadableError
== code
) {
2875 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
2876 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl
, CFSTR("The bundle\\U2019s executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
2877 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableNotLoadableError");
2878 } else if (CFBundleExecutableArchitectureMismatchError
== code
) {
2879 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");
2880 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl
, CFSTR("The bundle doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
2881 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-R"), CFSTR("Error"), bdl
, CFSTR("Try installing a universal version of the bundle."), "NSExecutableArchitectureMismatchError");
2882 } else if (CFBundleExecutableRuntimeMismatchError
== code
) {
2883 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");
2884 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl
, CFSTR("The bundle isn\\U2019t compatible with this application."), "NSExecutableRuntimeMismatchError");
2885 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-R"), CFSTR("Error"), bdl
, CFSTR("Try installing a newer version of the bundle."), "NSExecutableRuntimeMismatchError");
2886 } else if (CFBundleExecutableLoadError
== code
) {
2887 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");
2888 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-C"), CFSTR("Error"), bdl
, CFSTR("The bundle is damaged or missing necessary resources."), "NSExecutableLoadError");
2889 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableLoadError");
2890 } else if (CFBundleExecutableLinkError
== code
) {
2891 descFormat
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl
, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded."), "NSExecutableLinkError");
2892 reason
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl
, CFSTR("The bundle couldn\\U2019t be loaded."), "NSExecutableLinkError");
2893 suggestion
= CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-R"), CFSTR("Error"), bdl
, CFSTR("Try reinstalling the bundle."), "NSExecutableLinkError");
2896 desc
= CFStringCreateWithFormat(allocator
, NULL
, descFormat
, name
);
2897 CFRelease(descFormat
);
2902 userInfoKeys
[numKeys
] = CFSTR("NSBundlePath");
2903 userInfoValues
[numKeys
] = bundlePath
;
2906 if (executablePath
) {
2907 userInfoKeys
[numKeys
] = CFSTR("NSFilePath");
2908 userInfoValues
[numKeys
] = executablePath
;
2912 userInfoKeys
[numKeys
] = kCFErrorLocalizedDescriptionKey
;
2913 userInfoValues
[numKeys
] = desc
;
2917 userInfoKeys
[numKeys
] = kCFErrorLocalizedFailureReasonKey
;
2918 userInfoValues
[numKeys
] = reason
;
2922 userInfoKeys
[numKeys
] = kCFErrorLocalizedRecoverySuggestionKey
;
2923 userInfoValues
[numKeys
] = suggestion
;
2927 userInfoKeys
[numKeys
] = CFSTR("NSDebugDescription");
2928 userInfoValues
[numKeys
] = debugString
;
2931 error
= CFErrorCreateWithUserInfoKeysAndValues(allocator
, kCFErrorDomainCocoa
, code
, userInfoKeys
, userInfoValues
, numKeys
);
2932 if (bundleURL
) CFRelease(bundleURL
);
2933 if (absoluteURL
) CFRelease(absoluteURL
);
2934 if (executableURL
) CFRelease(executableURL
);
2935 if (bundlePath
) CFRelease(bundlePath
);
2936 if (executablePath
) CFRelease(executablePath
);
2937 if (desc
) CFRelease(desc
);
2938 if (reason
) CFRelease(reason
);
2939 if (suggestion
) CFRelease(suggestion
);
2943 CFErrorRef
_CFBundleCreateError(CFAllocatorRef allocator
, CFBundleRef bundle
, CFIndex code
) {
2944 return _CFBundleCreateErrorDebug(allocator
, bundle
, code
, NULL
);
2947 Boolean
_CFBundleLoadExecutableAndReturnError(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
2948 Boolean result
= false;
2949 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
2950 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
2953 pthread_mutex_lock(&(bundle
->_bundleLoadingLock
));
2954 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
2955 // make sure we know whether bundle is already loaded or not
2956 #if defined(BINARY_SUPPORT_DLFCN)
2957 if (!bundle
->_isLoaded
) _CFBundleDlfcnCheckLoaded(bundle
);
2958 #elif defined(BINARY_SUPPORT_DYLD)
2959 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
2960 #endif /* BINARY_SUPPORT_DLFCN */
2961 #if defined(BINARY_SUPPORT_DYLD)
2962 // We might need to figure out what it is
2963 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
2964 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
2965 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
2967 #endif /* BINARY_SUPPORT_DYLD */
2968 if (executableURL
) CFRelease(executableURL
);
2970 if (bundle
->_isLoaded
) {
2971 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
2972 // Remove from the scheduled unload set if we are there.
2973 pthread_mutex_lock(&CFBundleGlobalDataLock
);
2974 #if AVOID_WEAK_COLLECTIONS
2975 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
2976 #else /* AVOID_WEAK_COLLECTIONS */
2977 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
2978 #endif /* AVOID_WEAK_COLLECTIONS */
2979 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
2983 // Unload bundles scheduled for unloading
2984 if (!_scheduledBundlesAreUnloading
) {
2985 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
2986 _CFBundleUnloadScheduledBundles();
2987 pthread_mutex_lock(&(bundle
->_bundleLoadingLock
));
2990 if (bundle
->_isLoaded
) {
2991 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
2992 // Remove from the scheduled unload set if we are there.
2993 pthread_mutex_lock(&CFBundleGlobalDataLock
);
2994 #if AVOID_WEAK_COLLECTIONS
2995 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
2996 #else /* AVOID_WEAK_COLLECTIONS */
2997 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
2998 #endif /* AVOID_WEAK_COLLECTIONS */
2999 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3002 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
3004 switch (bundle
->_binaryType
) {
3005 #if defined(BINARY_SUPPORT_DLFCN)
3006 case __CFBundleUnreadableBinary
:
3007 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
3009 #endif /* BINARY_SUPPORT_DLFCN */
3010 #if defined(BINARY_SUPPORT_DYLD)
3011 case __CFBundleDYLDBundleBinary
:
3012 #if defined(BINARY_SUPPORT_DLFCN)
3013 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
3014 #else /* BINARY_SUPPORT_DLFCN */
3015 result
= _CFBundleDYLDLoadBundle(bundle
, forceGlobal
, subError
);
3016 #endif /* BINARY_SUPPORT_DLFCN */
3018 case __CFBundleDYLDFrameworkBinary
:
3019 #if defined(BINARY_SUPPORT_DLFCN)
3020 result
= _CFBundleDlfcnLoadFramework(bundle
, subError
);
3021 #else /* BINARY_SUPPORT_DLFCN */
3022 result
= _CFBundleDYLDLoadFramework(bundle
, subError
);
3023 #endif /* BINARY_SUPPORT_DLFCN */
3025 case __CFBundleDYLDExecutableBinary
:
3027 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3029 CFLog(__kCFLogBundle
, CFSTR("Attempt to load executable of a type that cannot be dynamically loaded for %@"), bundle
);
3032 #endif /* BINARY_SUPPORT_DYLD */
3033 #if defined(BINARY_SUPPORT_DLFCN)
3034 case __CFBundleUnknownBinary
:
3035 case __CFBundleELFBinary
:
3036 result
= _CFBundleDlfcnLoadBundle(bundle
, forceGlobal
, subError
);
3038 #endif /* BINARY_SUPPORT_DLFCN */
3039 #if defined(BINARY_SUPPORT_DLL)
3040 case __CFBundleDLLBinary
:
3041 result
= _CFBundleDLLLoad(bundle
, subError
);
3043 #endif /* BINARY_SUPPORT_DLL */
3044 case __CFBundleNoBinary
:
3046 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3048 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for %@"), bundle
);
3053 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3055 CFLog(__kCFLogBundle
, CFSTR("Cannot recognize type of executable for %@"), bundle
);
3059 if (result
&& bundle
->_plugInData
._isPlugIn
) _CFBundlePlugInLoaded(bundle
);
3060 if (!result
&& error
) *error
= localError
;
3064 Boolean
CFBundleLoadExecutableAndReturnError(CFBundleRef bundle
, CFErrorRef
*error
) {
3065 return _CFBundleLoadExecutableAndReturnError(bundle
, false, error
);
3068 Boolean
CFBundleLoadExecutable(CFBundleRef bundle
) {
3069 return _CFBundleLoadExecutableAndReturnError(bundle
, false, NULL
);
3072 Boolean
CFBundlePreflightExecutable(CFBundleRef bundle
, CFErrorRef
*error
) {
3073 Boolean result
= false;
3074 CFErrorRef localError
= NULL
;
3075 #if defined(BINARY_SUPPORT_DLFCN)
3076 CFErrorRef
*subError
= (error
? &localError
: NULL
);
3078 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3080 pthread_mutex_lock(&(bundle
->_bundleLoadingLock
));
3081 if (!executableURL
) bundle
->_binaryType
= __CFBundleNoBinary
;
3082 // make sure we know whether bundle is already loaded or not
3083 #if defined(BINARY_SUPPORT_DLFCN)
3084 if (!bundle
->_isLoaded
) _CFBundleDlfcnCheckLoaded(bundle
);
3085 #elif defined(BINARY_SUPPORT_DYLD)
3086 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
3087 #endif /* BINARY_SUPPORT_DLFCN */
3088 #if defined(BINARY_SUPPORT_DYLD)
3089 // We might need to figure out what it is
3090 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) {
3091 bundle
->_binaryType
= _CFBundleGrokBinaryType(executableURL
);
3092 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
3094 #endif /* BINARY_SUPPORT_DYLD */
3095 if (executableURL
) CFRelease(executableURL
);
3097 if (bundle
->_isLoaded
) {
3098 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
3101 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
3103 switch (bundle
->_binaryType
) {
3104 #if defined(BINARY_SUPPORT_DLFCN)
3105 case __CFBundleUnreadableBinary
:
3106 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3108 #endif /* BINARY_SUPPORT_DLFCN */
3109 #if defined(BINARY_SUPPORT_DYLD)
3110 case __CFBundleDYLDBundleBinary
:
3112 #if defined(BINARY_SUPPORT_DLFCN)
3113 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3114 #endif /* BINARY_SUPPORT_DLFCN */
3116 case __CFBundleDYLDFrameworkBinary
:
3118 #if defined(BINARY_SUPPORT_DLFCN)
3119 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3120 #endif /* BINARY_SUPPORT_DLFCN */
3122 case __CFBundleDYLDExecutableBinary
:
3123 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3125 #endif /* BINARY_SUPPORT_DYLD */
3126 #if defined(BINARY_SUPPORT_DLFCN)
3127 case __CFBundleUnknownBinary
:
3128 case __CFBundleELFBinary
:
3129 result
= _CFBundleDlfcnPreflight(bundle
, subError
);
3131 #endif /* BINARY_SUPPORT_DLFCN */
3132 #if defined(BINARY_SUPPORT_DLL)
3133 case __CFBundleDLLBinary
:
3136 #endif /* BINARY_SUPPORT_DLL */
3137 case __CFBundleNoBinary
:
3138 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
3141 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
3144 if (!result
&& error
) *error
= localError
;
3148 CFArrayRef
CFBundleCopyExecutableArchitectures(CFBundleRef bundle
) {
3149 CFArrayRef result
= NULL
;
3150 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3151 if (executableURL
) {
3152 result
= _CFBundleCopyArchitecturesForExecutable(executableURL
);
3153 CFRelease(executableURL
);
3158 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
3159 static Boolean
_CFBundleGetObjCImageInfo(CFBundleRef bundle
, uint32_t *objcVersion
, uint32_t *objcFlags
) {
3160 Boolean retval
= false;
3161 uint32_t localVersion
= 0, localFlags
= 0;
3162 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
3163 if (executableURL
) {
3164 retval
= _CFBundleGetObjCImageInfoForExecutable(executableURL
, &localVersion
, &localFlags
);
3165 CFRelease(executableURL
);
3167 if (objcVersion
) *objcVersion
= localVersion
;
3168 if (objcFlags
) *objcFlags
= localFlags
;
3173 void CFBundleUnloadExecutable(CFBundleRef bundle
) {
3174 // First unload bundles scheduled for unloading (if that's not what we are already doing.)
3175 if (!_scheduledBundlesAreUnloading
) _CFBundleUnloadScheduledBundles();
3177 if (!bundle
->_isLoaded
) return;
3179 // Remove from the scheduled unload set if we are there.
3180 if (!_scheduledBundlesAreUnloading
) pthread_mutex_lock(&CFBundleGlobalDataLock
);
3181 #if AVOID_WEAK_COLLECTIONS
3182 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
3183 #else /* AVOID_WEAK_COLLECTIONS */
3184 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
3185 #endif /* AVOID_WEAK_COLLECTIONS */
3186 if (!_scheduledBundlesAreUnloading
) pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3188 // Give the plugIn code a chance to realize this...
3189 _CFPlugInWillUnload(bundle
);
3191 pthread_mutex_lock(&(bundle
->_bundleLoadingLock
));
3192 if (!bundle
->_isLoaded
) {
3193 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
3196 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
3198 switch (bundle
->_binaryType
) {
3199 #if defined(BINARY_SUPPORT_DYLD)
3200 case __CFBundleDYLDBundleBinary
:
3201 #if defined(BINARY_SUPPORT_DLFCN)
3202 if (bundle
->_handleCookie
) _CFBundleDlfcnUnload(bundle
);
3203 #else /* BINARY_SUPPORT_DLFCN */
3204 _CFBundleDYLDUnloadBundle(bundle
);
3205 #endif /* BINARY_SUPPORT_DLFCN */
3207 case __CFBundleDYLDFrameworkBinary
:
3208 #if defined(BINARY_SUPPORT_DLFCN)
3209 if (bundle
->_handleCookie
&& _CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard
)) _CFBundleDlfcnUnload(bundle
);
3210 #endif /* BINARY_SUPPORT_DLFCN */
3212 #endif /* BINARY_SUPPORT_DYLD */
3213 #if defined(BINARY_SUPPORT_DLL)
3214 case __CFBundleDLLBinary
:
3215 _CFBundleDLLUnload(bundle
);
3217 #endif /* BINARY_SUPPORT_DLL */
3219 #if defined(BINARY_SUPPORT_DLFCN)
3220 if (bundle
->_handleCookie
) _CFBundleDlfcnUnload(bundle
);
3221 #endif /* BINARY_SUPPORT_DLFCN */
3224 if (!bundle
->_isLoaded
&& bundle
->_glueDict
) {
3225 CFDictionaryApplyFunction(bundle
->_glueDict
, _CFBundleDeallocateGlue
, (void *)CFGetAllocator(bundle
));
3226 CFRelease(bundle
->_glueDict
);
3227 bundle
->_glueDict
= NULL
;
3231 #if AVOID_WEAK_COLLECTIONS
3233 CF_PRIVATE
void _CFBundleScheduleForUnloading(CFBundleRef bundle
) {
3234 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3235 if (!_bundlesToUnload
) {
3236 CFSetCallBacks nonRetainingCallbacks
= kCFTypeSetCallBacks
;
3237 nonRetainingCallbacks
.retain
= NULL
;
3238 nonRetainingCallbacks
.release
= NULL
;
3239 _bundlesToUnload
= CFSetCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingCallbacks
);
3241 CFSetAddValue(_bundlesToUnload
, bundle
);
3242 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3245 CF_PRIVATE
void _CFBundleUnscheduleForUnloading(CFBundleRef bundle
) {
3246 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3247 if (_bundlesToUnload
) CFSetRemoveValue(_bundlesToUnload
, bundle
);
3248 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3251 CF_PRIVATE
void _CFBundleUnloadScheduledBundles(void) {
3252 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3253 if (_bundlesToUnload
) {
3254 CFIndex i
, c
= CFSetGetCount(_bundlesToUnload
);
3256 CFBundleRef
*unloadThese
= (CFBundleRef
*)CFAllocatorAllocate(kCFAllocatorSystemDefault
, sizeof(CFBundleRef
) * c
, 0);
3257 CFSetGetValues(_bundlesToUnload
, (const void **)unloadThese
);
3258 _scheduledBundlesAreUnloading
= true;
3259 for (i
= 0; i
< c
; i
++) {
3260 // This will cause them to be removed from the set. (Which is why we copied all the values out of the set up front.)
3261 CFBundleUnloadExecutable(unloadThese
[i
]);
3263 _scheduledBundlesAreUnloading
= false;
3264 CFAllocatorDeallocate(kCFAllocatorSystemDefault
, unloadThese
);
3267 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3270 #else /* AVOID_WEAK_COLLECTIONS */
3272 CF_PRIVATE
void _CFBundleScheduleForUnloading(CFBundleRef bundle
) {
3273 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3274 if (!_bundlesToUnload
) _bundlesToUnload
= [[__CFHashTable alloc
] initWithOptions
:CFPointerFunctionsZeroingWeakMemory capacity
:0];
3275 [_bundlesToUnload addObject
:(id
)bundle
];
3276 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3279 CF_PRIVATE
void _CFBundleUnscheduleForUnloading(CFBundleRef bundle
) {
3280 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3281 if (_bundlesToUnload
) [_bundlesToUnload removeObject
:(id
)bundle
];
3282 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3285 CF_PRIVATE
void _CFBundleUnloadScheduledBundles(void) {
3286 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3287 if (_bundlesToUnload
&& [_bundlesToUnload count
] > 0) {
3289 CFMutableArrayRef unloadThese
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
3290 for (id value in _bundlesToUnload
) CFArrayAppendValue(unloadThese
, value
);
3291 c
= CFArrayGetCount(unloadThese
);
3293 _scheduledBundlesAreUnloading
= true;
3294 for (i
= 0; i
< c
; i
++) {
3295 // This will cause them to be removed from the set. (Which is why we copied all the values out of the set up front.)
3296 CFBundleUnloadExecutable((CFBundleRef
)CFArrayGetValueAtIndex(unloadThese
, i
));
3298 _scheduledBundlesAreUnloading
= false;
3300 CFRelease(unloadThese
);
3302 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3305 #endif /* AVOID_WEAK_COLLECTIONS */
3307 void *CFBundleGetFunctionPointerForName(CFBundleRef bundle
, CFStringRef funcName
) {
3309 // Load if necessary
3310 if (!bundle
->_isLoaded
) {
3311 if (!CFBundleLoadExecutable(bundle
)) return NULL
;
3314 switch (bundle
->_binaryType
) {
3315 #if defined(BINARY_SUPPORT_DYLD)
3316 case __CFBundleDYLDBundleBinary
:
3317 case __CFBundleDYLDFrameworkBinary
:
3318 case __CFBundleDYLDExecutableBinary
:
3319 #if defined(BINARY_SUPPORT_DLFCN)
3320 if (bundle
->_handleCookie
) return _CFBundleDlfcnGetSymbolByName(bundle
, funcName
);
3321 #else /* BINARY_SUPPORT_DLFCN */
3322 return _CFBundleDYLDGetSymbolByName(bundle
, funcName
);
3323 #endif /* BINARY_SUPPORT_DLFCN */
3325 #endif /* BINARY_SUPPORT_DYLD */
3326 #if defined(BINARY_SUPPORT_DLL)
3327 case __CFBundleDLLBinary
:
3328 tvp
= _CFBundleDLLGetSymbolByName(bundle
, funcName
);
3330 #endif /* BINARY_SUPPORT_DLL */
3332 #if defined(BINARY_SUPPORT_DLFCN)
3333 if (bundle
->_handleCookie
) return _CFBundleDlfcnGetSymbolByName(bundle
, funcName
);
3334 #endif /* BINARY_SUPPORT_DLFCN */
3340 void *_CFBundleGetCFMFunctionPointerForName(CFBundleRef bundle
, CFStringRef funcName
) {
3342 // Load if necessary
3343 if (!bundle
->_isLoaded
) {
3344 if (!CFBundleLoadExecutable(bundle
)) return NULL
;
3346 #if defined (BINARY_SUPPORT_DYLD) || defined (BINARY_SUPPORT_DLFCN)
3347 switch (bundle
->_binaryType
) {
3348 #if defined(BINARY_SUPPORT_DYLD)
3349 case __CFBundleDYLDBundleBinary
:
3350 case __CFBundleDYLDFrameworkBinary
:
3351 case __CFBundleDYLDExecutableBinary
:
3352 #if defined(BINARY_SUPPORT_DLFCN)
3353 if (bundle
->_handleCookie
) fp
= _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, funcName
, true);
3354 #else /* BINARY_SUPPORT_DLFCN */
3355 fp
= _CFBundleDYLDGetSymbolByNameWithSearch(bundle
, funcName
, true);
3356 #endif /* BINARY_SUPPORT_DLFCN */
3358 #endif /* BINARY_SUPPORT_DYLD */
3360 #if defined(BINARY_SUPPORT_DLFCN)
3361 if (bundle
->_handleCookie
) fp
= _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, funcName
, true);
3362 #endif /* BINARY_SUPPORT_DLFCN */
3365 #endif /* BINARY_SUPPORT_DYLD || BINARY_SUPPORT_DLFCN */
3369 void CFBundleGetFunctionPointersForNames(CFBundleRef bundle
, CFArrayRef functionNames
, void *ftbl
[]) {
3374 c
= CFArrayGetCount(functionNames
);
3375 for (i
= 0; i
< c
; i
++) ftbl
[i
] = CFBundleGetFunctionPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(functionNames
, i
));
3378 void _CFBundleGetCFMFunctionPointersForNames(CFBundleRef bundle
, CFArrayRef functionNames
, void *ftbl
[]) {
3383 c
= CFArrayGetCount(functionNames
);
3384 for (i
= 0; i
< c
; i
++) ftbl
[i
] = _CFBundleGetCFMFunctionPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(functionNames
, i
));
3387 void *CFBundleGetDataPointerForName(CFBundleRef bundle
, CFStringRef symbolName
) {
3389 // Load if necessary
3390 if (!bundle
->_isLoaded
&& !CFBundleLoadExecutable(bundle
)) return NULL
;
3392 switch (bundle
->_binaryType
) {
3393 #if defined(BINARY_SUPPORT_DYLD)
3394 case __CFBundleDYLDBundleBinary
:
3395 case __CFBundleDYLDFrameworkBinary
:
3396 case __CFBundleDYLDExecutableBinary
:
3397 #if defined(BINARY_SUPPORT_DLFCN)
3398 if (bundle
->_handleCookie
) dp
= _CFBundleDlfcnGetSymbolByName(bundle
, symbolName
);
3399 #else /* BINARY_SUPPORT_DLFCN */
3400 dp
= _CFBundleDYLDGetSymbolByName(bundle
, symbolName
);
3401 #endif /* BINARY_SUPPORT_DLFCN */
3403 #endif /* BINARY_SUPPORT_DYLD */
3404 #if defined(BINARY_SUPPORT_DLL)
3405 case __CFBundleDLLBinary
:
3406 /* MF:!!! Handle this someday */
3408 #endif /* BINARY_SUPPORT_DLL */
3410 #if defined(BINARY_SUPPORT_DLFCN)
3411 if (bundle
->_handleCookie
) dp
= _CFBundleDlfcnGetSymbolByName(bundle
, symbolName
);
3412 #endif /* BINARY_SUPPORT_DLFCN */
3418 void CFBundleGetDataPointersForNames(CFBundleRef bundle
, CFArrayRef symbolNames
, void *stbl
[]) {
3423 c
= CFArrayGetCount(symbolNames
);
3424 for (i
= 0; i
< c
; i
++) stbl
[i
] = CFBundleGetDataPointerForName(bundle
, (CFStringRef
)CFArrayGetValueAtIndex(symbolNames
, i
));
3427 CF_PRIVATE _CFResourceData
*__CFBundleGetResourceData(CFBundleRef bundle
) {
3428 return &(bundle
->_resourceData
);
3431 CFPlugInRef
CFBundleGetPlugIn(CFBundleRef bundle
) {
3432 return (bundle
->_plugInData
._isPlugIn
) ? (CFPlugInRef
)bundle
: NULL
;
3435 CF_PRIVATE _CFPlugInData
*__CFBundleGetPlugInData(CFBundleRef bundle
) {
3436 return &(bundle
->_plugInData
);
3439 CF_PRIVATE Boolean
_CFBundleCouldBeBundle(CFURLRef url
) {
3440 Boolean result
= false;
3443 if (_CFGetFileProperties(kCFAllocatorSystemDefault
, url
, &exists
, &mode
, NULL
, NULL
, NULL
, NULL
) == 0) result
= (exists
&& (mode
& S_IFMT
) == S_IFDIR
&& (mode
& 0444) != 0);
3447 #define LENGTH_OF(A) (sizeof(A) / sizeof(A[0]))
3449 //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/
3450 static CFURLRef
__CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath
, Boolean permissive
) {
3451 // 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.
3452 #if DEPLOYMENT_TARGET_WINDOWS
3453 UniChar executablesToFrameworksPathBuff
[] = {'.', '.', '\\', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
3454 UniChar executablesToPrivateFrameworksPathBuff
[] = {'.', '.', '\\', 'P', 'r', 'i', 'v', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
3455 UniChar frameworksExtension
[] = {'f', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k'};
3457 UniChar pathBuff
[CFMaxPathSize
] = {0};
3458 UniChar nameBuff
[CFMaxPathSize
] = {0};
3459 CFIndex length
, nameStart
, nameLength
, savedLength
;
3460 CFMutableStringRef cheapStr
= CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault
, NULL
, 0, 0, NULL
);
3461 CFURLRef bundleURL
= NULL
;
3463 length
= CFStringGetLength(executablePath
);
3464 if (length
> CFMaxPathSize
) length
= CFMaxPathSize
;
3465 CFStringGetCharacters(executablePath
, CFRangeMake(0, length
), pathBuff
);
3467 // Save the name in nameBuff
3468 length
= _CFLengthAfterDeletingPathExtension(pathBuff
, length
);
3469 nameStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3470 nameLength
= length
- nameStart
;
3471 memmove(nameBuff
, &(pathBuff
[nameStart
]), nameLength
* sizeof(UniChar
));
3473 // Strip the name from pathBuff
3474 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3475 savedLength
= length
;
3477 #if DEPLOYMENT_TARGET_WINDOWS
3478 // * (Windows-only) First check the "Executables" directory parallel to the "Frameworks" directory case.
3479 if (_CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, executablesToFrameworksPathBuff
, LENGTH_OF(executablesToFrameworksPathBuff
)) && _CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, nameBuff
, nameLength
) && _CFAppendPathExtension(pathBuff
, &length
, CFMaxPathSize
, frameworksExtension
, LENGTH_OF(frameworksExtension
))) {
3480 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3481 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3482 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3483 CFRelease(bundleURL
);
3487 // * (Windows-only) Next check the "Executables" directory parallel to the "PrivateFrameworks" directory case.
3489 length
= savedLength
;
3490 if (_CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, executablesToPrivateFrameworksPathBuff
, LENGTH_OF(executablesToPrivateFrameworksPathBuff
)) && _CFAppendPathComponent(pathBuff
, &length
, CFMaxPathSize
, nameBuff
, nameLength
) && _CFAppendPathExtension(pathBuff
, &length
, CFMaxPathSize
, frameworksExtension
, LENGTH_OF(frameworksExtension
))) {
3491 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3492 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3493 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3494 CFRelease(bundleURL
);
3500 // * Finally check the executable inside the framework case.
3502 length
= savedLength
;
3503 // To catch all the cases, we just peel off level looking for one ending in .framework or one called "Supporting Files".
3505 CFStringRef name
= permissive
? CFSTR("") : CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, (const char *)nameBuff
);
3507 while (length
> 0) {
3508 CFIndex curStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3509 if (curStart
>= length
) break;
3510 CFStringSetExternalCharactersNoCopy(cheapStr
, &(pathBuff
[curStart
]), length
- curStart
, CFMaxPathSize
- curStart
);
3511 if (!permissive
&& CFEqual(cheapStr
, _CFBundleResourcesDirectoryName
)) break;
3512 if (CFEqual(cheapStr
, _CFBundleSupportFilesDirectoryName1
) || CFEqual(cheapStr
, _CFBundleSupportFilesDirectoryName2
)) {
3514 CFIndex fmwkStart
= _CFStartOfLastPathComponent(pathBuff
, length
);
3515 CFStringSetExternalCharactersNoCopy(cheapStr
, &(pathBuff
[fmwkStart
]), length
- fmwkStart
, CFMaxPathSize
- fmwkStart
);
3517 if (permissive
|| CFStringHasPrefix(cheapStr
, name
)) {
3518 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3519 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3521 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3522 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3523 CFRelease(bundleURL
);
3528 } else if (CFStringHasSuffix(cheapStr
, CFSTR(".framework")) && (permissive
|| CFStringHasPrefix(cheapStr
, name
))) {
3529 CFStringSetExternalCharactersNoCopy(cheapStr
, pathBuff
, length
, CFMaxPathSize
);
3530 bundleURL
= CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault
, cheapStr
, PLATFORM_PATH_STYLE
, true);
3531 if (!_CFBundleCouldBeBundle(bundleURL
)) {
3532 CFRelease(bundleURL
);
3537 length
= _CFLengthAfterDeletingLastPathComponent(pathBuff
, length
);
3539 if (!permissive
) CFRelease(name
);
3541 CFStringSetExternalCharactersNoCopy(cheapStr
, NULL
, 0, 0);
3542 CFRelease(cheapStr
);
3547 //SPI version; separated out to minimize linkage changes
3548 CFURLRef
_CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath
) {
3549 return __CFBundleCopyFrameworkURLForExecutablePath(executablePath
, false);
3552 static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath
) {
3553 // This finds the bundle for the given path.
3554 // 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.
3556 CFURLRef curURL
= __CFBundleCopyFrameworkURLForExecutablePath(imagePath
, true);
3557 Boolean createdBundle
= false;
3560 bundle
= _CFBundleCopyBundleForURL(curURL
, true);
3562 // Ensure bundle exists by creating it if necessary
3563 // NB doFinalProcessing must be false here, see below
3564 bundle
= _CFBundleCreate(kCFAllocatorSystemDefault
, curURL
, true, false);
3565 createdBundle
= true;
3568 pthread_mutex_lock(&(bundle
->_bundleLoadingLock
));
3569 if (!bundle
->_isLoaded
) {
3570 // 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)
3571 #if defined(BINARY_SUPPORT_DLFCN)
3572 if (!bundle
->_isLoaded
) _CFBundleDlfcnCheckLoaded(bundle
);
3573 #elif defined(BINARY_SUPPORT_DYLD)
3574 if (!bundle
->_isLoaded
) _CFBundleDYLDCheckLoaded(bundle
);
3575 #endif /* BINARY_SUPPORT_DLFCN */
3576 #if defined(BINARY_SUPPORT_DYLD)
3577 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= __CFBundleDYLDFrameworkBinary
;
3578 if (bundle
->_binaryType
!= __CFBundleCFMBinary
&& bundle
->_binaryType
!= __CFBundleUnreadableBinary
) bundle
->_resourceData
._executableLacksResourceFork
= true;
3579 #endif /* BINARY_SUPPORT_DYLD */
3581 if (!bundle
->_isLoaded
) printf("ensure bundle %p set loaded fallback, handle %p image %p conn %p\n", bundle
, bundle
->_handleCookie
, bundle
->_imageCookie
, bundle
->_connectionCookie
);
3582 #endif /* LOG_BUNDLE_LOAD */
3583 bundle
->_isLoaded
= true;
3585 pthread_mutex_unlock(&(bundle
->_bundleLoadingLock
));
3586 if (createdBundle
) {
3587 // Perform delayed final processing steps.
3588 // This must be done after _isLoaded has been set, for security reasons (3624341).
3589 if (_CFBundleNeedsInitPlugIn(bundle
)) {
3590 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3591 _CFBundleInitPlugIn(bundle
);
3592 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3595 // Release the bundle if we did not create it here
3603 static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths
) {
3604 // This finds the bundles for the given paths.
3605 // 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).
3606 CFIndex i
, imagePathCount
= CFArrayGetCount(imagePaths
);
3607 for (i
= 0; i
< imagePathCount
; i
++) _CFBundleEnsureBundleExistsForImagePath((CFStringRef
)CFArrayGetValueAtIndex(imagePaths
, i
));
3610 static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint
) {
3611 CFArrayRef imagePaths
= NULL
;
3612 // Tickle the main bundle into existence
3613 (void)_CFBundleGetMainBundleAlreadyLocked();
3614 #if defined(BINARY_SUPPORT_DYLD)
3615 imagePaths
= _CFBundleDYLDCopyLoadedImagePathsForHint(hint
);
3616 #endif /* BINARY_SUPPORT_DYLD */
3618 _CFBundleEnsureBundlesExistForImagePaths(imagePaths
);
3619 CFRelease(imagePaths
);
3623 static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void) {
3624 // 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.
3625 CFArrayRef imagePaths
= NULL
;
3626 // Tickle the main bundle into existence
3627 (void)_CFBundleGetMainBundleAlreadyLocked();
3629 #if defined(BINARY_SUPPORT_DLL)
3630 // Dont know how to find static bundles for DLLs
3631 #endif /* BINARY_SUPPORT_DLL */
3633 #if defined(BINARY_SUPPORT_DYLD)
3634 imagePaths
= _CFBundleDYLDCopyLoadedImagePathsIfChanged();
3635 #endif /* BINARY_SUPPORT_DYLD */
3637 _CFBundleEnsureBundlesExistForImagePaths(imagePaths
);
3638 CFRelease(imagePaths
);
3642 CFArrayRef
CFBundleGetAllBundles(void) {
3643 // To answer this properly, we have to have created the static bundles!
3644 #if !AVOID_WEAK_COLLECTIONS
3645 static CFMutableArrayRef externalAllBundles
= NULL
;
3646 #endif /* AVOID_WEAK_COLLECTIONS */
3648 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3649 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
3650 #if AVOID_WEAK_COLLECTIONS
3651 bundles
= _allBundles
;
3652 #else /* AVOID_WEAK_COLLECTIONS */
3653 if (!externalAllBundles
) {
3654 CFArrayCallBacks nonRetainingArrayCallbacks
= kCFTypeArrayCallBacks
;
3655 nonRetainingArrayCallbacks
.retain
= NULL
;
3656 nonRetainingArrayCallbacks
.release
= NULL
;
3657 externalAllBundles
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &nonRetainingArrayCallbacks
);
3659 CFArrayRemoveAllValues(externalAllBundles
);
3660 for (id value in _allBundles
) CFArrayAppendValue(externalAllBundles
, value
);
3661 bundles
= externalAllBundles
;
3662 #endif /* AVOID_WEAK_COLLECTIONS */
3663 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3667 CF_EXPORT CFArrayRef
_CFBundleCopyAllBundles(void) {
3668 // To answer this properly, we have to have created the static bundles!
3669 pthread_mutex_lock(&CFBundleGlobalDataLock
);
3670 _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
3671 #if AVOID_WEAK_COLLECTIONS
3672 CFArrayRef bundles
= CFArrayCreateCopy(kCFAllocatorSystemDefault
, _allBundles
);
3673 #else /* AVOID_WEAK_COLLECTIONS */
3674 CFMutableArrayRef bundles
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
3675 for (id value in _allBundles
) CFArrayAppendValue(bundles
, value
);
3676 #endif /* AVOID_WEAK_COLLECTIONS */
3677 pthread_mutex_unlock(&CFBundleGlobalDataLock
);
3681 CF_PRIVATE
uint8_t _CFBundleLayoutVersion(CFBundleRef bundle
) {
3682 return bundle
->_version
;
3685 static void __addPlatformAndProductNamesToKeys(const void *value
, void *context
) {
3686 CFMutableSetRef newKeys
= (CFMutableSetRef
)context
;
3687 CFStringRef key
= (CFStringRef
)value
;
3688 CFStringRef firstPartOfKey
= NULL
;
3689 CFStringRef restOfKey
= NULL
;
3691 // Find the first ':'
3693 Boolean success
= CFStringFindWithOptions(key
, CFSTR(":"), CFRangeMake(0, CFStringGetLength(key
)), 0, &range
);
3695 firstPartOfKey
= CFStringCreateWithSubstring(kCFAllocatorSystemDefault
, key
, CFRangeMake(0, range
.location
));
3696 restOfKey
= CFStringCreateWithSubstring(kCFAllocatorSystemDefault
, key
, CFRangeMake(range
.location
+ 1, CFStringGetLength(key
) - range
.location
- 1));
3698 firstPartOfKey
= (CFStringRef
)CFRetain(key
);
3701 // only apply product and platform to top-level key
3702 CFStringRef newKeyWithPlatform
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@-%@%@%@"), firstPartOfKey
, _CFGetPlatformName(), restOfKey
? CFSTR(":") : CFSTR(""), restOfKey
? restOfKey
: CFSTR(""));
3703 CFStringRef newKeyWithProduct
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@~%@%@%@"), firstPartOfKey
, _CFGetProductName(), restOfKey
? CFSTR(":") : CFSTR(""), restOfKey
? restOfKey
: CFSTR(""));
3704 CFStringRef newKeyWithProductAndPlatform
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("%@-%@~%@%@%@"), firstPartOfKey
, _CFGetPlatformName(), _CFGetProductName(), restOfKey
? CFSTR(":") : CFSTR(""), restOfKey
? restOfKey
: CFSTR(""));
3706 CFSetAddValue(newKeys
, key
);
3707 CFSetAddValue(newKeys
, newKeyWithPlatform
);
3708 CFSetAddValue(newKeys
, newKeyWithProduct
);
3709 CFSetAddValue(newKeys
, newKeyWithProductAndPlatform
);
3711 if (firstPartOfKey
) CFRelease(firstPartOfKey
);
3712 if (restOfKey
) CFRelease(restOfKey
);
3713 CFRelease(newKeyWithPlatform
);
3714 CFRelease(newKeyWithProduct
);
3715 CFRelease(newKeyWithProductAndPlatform
);
3718 // from CFUtilities.c
3719 CF_PRIVATE Boolean
_CFReadMappedFromFile(CFStringRef path
, Boolean map
, Boolean uncached
, void **outBytes
, CFIndex
*outLength
, CFErrorRef
*errorPtr
);
3721 // implementation of below functions - takes URL as parameter
3722 static CFPropertyListRef
_CFBundleCreateFilteredInfoPlistWithURL(CFURLRef infoPlistURL
, CFSetRef keyPaths
, _CFBundleFilteredPlistOptions options
) {
3723 CFPropertyListRef result
= NULL
;
3725 if (!infoPlistURL
) return CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
3727 CFURLRef absoluteURL
= CFURLCopyAbsoluteURL(infoPlistURL
);
3728 CFStringRef filePath
= CFURLCopyFileSystemPath(absoluteURL
, PLATFORM_PATH_STYLE
);
3729 CFRelease(absoluteURL
);
3731 if (!filePath
) return CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
3735 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3736 Boolean mapped
= options
& _CFBundleFilteredPlistMemoryMapped
? true : false;
3738 Boolean mapped
= false;
3740 Boolean success
= _CFReadMappedFromFile(filePath
, mapped
, false, &bytes
, &length
, NULL
);
3741 CFRelease(filePath
);
3742 if (!success
) return CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
3744 CFDataRef infoPlistData
= CFDataCreateWithBytesNoCopy(kCFAllocatorSystemDefault
, (const UInt8
*)bytes
, length
, kCFAllocatorNull
);
3745 // We need to include all possible variants of the platform/product combo as possible keys.
3746 CFMutableSetRef newKeyPaths
= CFSetCreateMutable(kCFAllocatorSystemDefault
, CFSetGetCount(keyPaths
), &kCFTypeSetCallBacks
);
3747 CFSetApplyFunction(keyPaths
, __addPlatformAndProductNamesToKeys
, newKeyPaths
);
3749 success
= _CFPropertyListCreateFiltered(kCFAllocatorSystemDefault
, infoPlistData
, kCFPropertyListMutableContainers
, newKeyPaths
, &result
, NULL
);
3752 result
= CFDictionaryCreate(kCFAllocatorSystemDefault
, NULL
, NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
3754 _CFBundleInfoPlistProcessInfoDictionary((CFMutableDictionaryRef
)result
);
3757 CFRelease(newKeyPaths
);
3758 CFRelease(infoPlistData
);
3760 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
3761 munmap(bytes
, length
);
3770 // Returns a subset of the bundle's property list, only including the keyPaths in the CFSet. If the top level object is not a dictionary, you will get back an empty dictionary as the result. If the Info.plist does not exist or could not be parsed, you will get back an empty dictionary.
3771 CF_EXPORT CFPropertyListRef
_CFBundleCreateFilteredInfoPlist(CFBundleRef bundle
, CFSetRef keyPaths
, _CFBundleFilteredPlistOptions options
) {
3772 CFURLRef infoPlistURL
= _CFBundleCopyInfoPlistURL(bundle
);
3773 CFPropertyListRef result
= _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL
, keyPaths
, options
);
3774 if (infoPlistURL
) CFRelease(infoPlistURL
);
3778 CF_EXPORT CFPropertyListRef
_CFBundleCreateFilteredLocalizedInfoPlist(CFBundleRef bundle
, CFSetRef keyPaths
, CFStringRef localizationName
, _CFBundleFilteredPlistOptions options
) {
3779 CFURLRef infoPlistURL
= CFBundleCopyResourceURLForLocalization(bundle
, _CFBundleLocalInfoName
, _CFBundleStringTableType
, NULL
, localizationName
);
3780 CFPropertyListRef result
= _CFBundleCreateFilteredInfoPlistWithURL(infoPlistURL
, keyPaths
, options
);
3781 if (infoPlistURL
) CFRelease(infoPlistURL
);
3785 CF_EXPORT CFURLRef
_CFBundleCopyInfoPlistURL(CFBundleRef bundle
) {
3786 CFDictionaryRef infoDict
= CFBundleGetInfoDictionary(bundle
);
3787 CFURLRef url
= (CFURLRef
)CFDictionaryGetValue(infoDict
, _kCFBundleInfoPlistURLKey
);
3788 if (!url
) url
= (CFURLRef
)CFDictionaryGetValue(infoDict
, _kCFBundleRawInfoPlistURLKey
);
3789 return (url
? (CFURLRef
)CFRetain(url
) : NULL
);
3792 CF_EXPORT CFURLRef
_CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle
) {
3793 return CFBundleCopyPrivateFrameworksURL(bundle
);
3796 CF_EXPORT CFURLRef
CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle
) {
3797 CFURLRef result
= NULL
;
3799 if (1 == bundle
->_version
) {
3800 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase1
, bundle
->_url
);
3801 } else if (2 == bundle
->_version
) {
3802 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase2
, bundle
->_url
);
3804 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundlePrivateFrameworksURLFromBase0
, bundle
->_url
);
3809 CF_EXPORT CFURLRef
_CFBundleCopySharedFrameworksURL(CFBundleRef bundle
) {
3810 return CFBundleCopySharedFrameworksURL(bundle
);
3813 CF_EXPORT CFURLRef
CFBundleCopySharedFrameworksURL(CFBundleRef bundle
) {
3814 CFURLRef result
= NULL
;
3816 if (1 == bundle
->_version
) {
3817 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase1
, bundle
->_url
);
3818 } else if (2 == bundle
->_version
) {
3819 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase2
, bundle
->_url
);
3821 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedFrameworksURLFromBase0
, bundle
->_url
);
3826 CF_EXPORT CFURLRef
_CFBundleCopySharedSupportURL(CFBundleRef bundle
) {
3827 return CFBundleCopySharedSupportURL(bundle
);
3830 CF_EXPORT CFURLRef
CFBundleCopySharedSupportURL(CFBundleRef bundle
) {
3831 CFURLRef result
= NULL
;
3833 if (1 == bundle
->_version
) {
3834 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase1
, bundle
->_url
);
3835 } else if (2 == bundle
->_version
) {
3836 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase2
, bundle
->_url
);
3838 result
= CFURLCreateWithString(CFGetAllocator(bundle
), _CFBundleSharedSupportURLFromBase0
, bundle
->_url
);
3843 CF_PRIVATE CFURLRef
_CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle
) {
3844 return CFBundleCopyBuiltInPlugInsURL(bundle
);
3847 CF_EXPORT CFURLRef
CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle
) {
3848 CFURLRef result
= NULL
, alternateResult
= NULL
;
3850 CFAllocatorRef alloc
= CFGetAllocator(bundle
);
3851 if (1 == bundle
->_version
) {
3852 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase1
, bundle
->_url
);
3853 } else if (2 == bundle
->_version
) {
3854 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase2
, bundle
->_url
);
3856 result
= CFURLCreateWithString(alloc
, _CFBundleBuiltInPlugInsURLFromBase0
, bundle
->_url
);
3858 if (!result
|| !_urlExists(result
)) {
3859 if (1 == bundle
->_version
) {
3860 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase1
, bundle
->_url
);
3861 } else if (2 == bundle
->_version
) {
3862 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase2
, bundle
->_url
);
3864 alternateResult
= CFURLCreateWithString(alloc
, _CFBundleAlternateBuiltInPlugInsURLFromBase0
, bundle
->_url
);
3866 if (alternateResult
&& _urlExists(alternateResult
)) {
3867 if (result
) CFRelease(result
);
3868 result
= alternateResult
;
3870 if (alternateResult
) CFRelease(alternateResult
);
3876 #if defined(BINARY_SUPPORT_DYLD)
3878 CF_PRIVATE CFArrayRef
_CFBundleDYLDCopyLoadedImagePathsForHint(CFStringRef hint
) {
3879 uint32_t i
, numImages
= _dyld_image_count();
3880 CFMutableArrayRef result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
3881 CFRange range
= CFRangeMake(0, CFStringGetLength(hint
)), altRange
= CFRangeMake(0, 0), testRange
= CFRangeMake(0, 0);
3882 const char *processPath
= _CFProcessPath();
3883 const void *mhp
= (const void *)_NSGetMachExecuteHeader();
3885 if (range
.length
> 14) {
3886 // handle some common variations on framework bundle identifiers
3887 if (CFStringFindWithOptions(hint
, CFSTR(".framework"), range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, &testRange
) && testRange
.location
> 0 && testRange
.length
> 0) {
3888 // identifier has .framework appended
3889 altRange
.length
= testRange
.location
;
3890 } else if (CFStringFindWithOptions(hint
, CFSTR("framework"), range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, &testRange
) && testRange
.location
> 0 && testRange
.length
> 0) {
3891 // identifier has Framework appended
3892 altRange
.length
= testRange
.location
;
3893 } else if (CFStringFindWithOptions(hint
, CFSTR("fw"), range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, &testRange
) && testRange
.location
> 0 && testRange
.length
> 0) {
3894 // identifier has FW appended
3895 altRange
.length
= testRange
.location
;
3898 for (i
= 0; i
< numImages
; i
++) {
3899 const char *curName
= _dyld_get_image_name(i
), *lastComponent
= NULL
;
3900 if (curName
&& (!processPath
|| 0 != strcmp(curName
, processPath
)) && mhp
!= (void *)_dyld_get_image_header(i
)) lastComponent
= strrchr(curName
, '/');
3901 if (lastComponent
) {
3902 CFStringRef str
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, lastComponent
+ 1);
3904 if (CFStringFindWithOptions(hint
, str
, range
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
) || (altRange
.length
> 0 && CFStringFindWithOptions(hint
, str
, altRange
, kCFCompareAnchored
|kCFCompareBackwards
|kCFCompareCaseInsensitive
, NULL
))) {
3905 CFStringRef curStr
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, curName
);
3907 CFArrayAppendValue(result
, curStr
);
3918 static char *_cleanedPathForPath(const char *curName
) {
3919 char *thePath
= strdup(curName
);
3921 // We are going to process the buffer replacing all "/./" and "//" with "/"
3922 CFIndex srcIndex
= 0, dstIndex
= 0;
3923 CFIndex len
= strlen(thePath
);
3924 for (srcIndex
=0; srcIndex
<len
; srcIndex
++) {
3925 thePath
[dstIndex
] = thePath
[srcIndex
];
3927 while (srcIndex
< len
-1 && thePath
[srcIndex
] == '/' && (thePath
[srcIndex
+1] == '/' || (thePath
[srcIndex
+1] == '.' && srcIndex
< len
-2 && thePath
[srcIndex
+2] == '/'))) srcIndex
+= (thePath
[srcIndex
+1] == '/' ? 1 : 2);
3929 thePath
[dstIndex
] = 0;
3934 CF_PRIVATE CFArrayRef
_CFBundleDYLDCopyLoadedImagePathsIfChanged(void) {
3935 // 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.
3936 uint32_t i
, numImages
= _dyld_image_count();
3937 CFMutableArrayRef result
= NULL
;
3938 static uint32_t _cachedDYLDImageCount
= -1;
3940 if (numImages
!= _cachedDYLDImageCount
) {
3941 const char *curName
;
3942 char *cleanedCurName
= NULL
;
3944 const char *processPath
= _CFProcessPath();
3945 const void *mhp
= (const void *)_NSGetMachExecuteHeader();
3947 result
= CFArrayCreateMutable(kCFAllocatorSystemDefault
, 0, &kCFTypeArrayCallBacks
);
3949 for (i
= 0; i
< numImages
; i
++) {
3950 curName
= _dyld_get_image_name(i
);
3951 if (curName
&& i
== 0) cleanedCurName
= _cleanedPathForPath(curName
);
3952 if (curName
&& (!processPath
|| 0 != strcmp(curName
, processPath
)) && (!processPath
|| !cleanedCurName
|| 0 != strcmp(cleanedCurName
, processPath
)) && mhp
!= (void *)_dyld_get_image_header(i
)) {
3953 curStr
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, curName
);
3955 CFArrayAppendValue(result
, curStr
);
3959 if (cleanedCurName
) {
3960 free(cleanedCurName
);
3961 cleanedCurName
= NULL
;
3964 _cachedDYLDImageCount
= numImages
;
3969 static CFStringRef
_CFBundleDYLDCopyLoadedImagePathForPointer(void *p
) {
3970 CFStringRef result
= NULL
;
3971 #if defined(USE_DYLD_PRIV)
3972 const char *name
= dyld_image_path_containing_address(p
);
3973 if (name
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, name
);
3974 #else /* USE_DYLD_PRIV */
3976 uint32_t i
, j
, n
= _dyld_image_count();
3977 Boolean foundit
= false;
3980 #define MACH_HEADER_TYPE struct mach_header_64
3981 #define MACH_SEGMENT_CMD_TYPE struct segment_command_64
3982 #define MACH_SEGMENT_FLAVOR LC_SEGMENT_64
3984 #define MACH_HEADER_TYPE struct mach_header
3985 #define MACH_SEGMENT_CMD_TYPE struct segment_command
3986 #define MACH_SEGMENT_FLAVOR LC_SEGMENT
3988 for (i
= 0; !foundit
&& i
< n
; i
++) {
3989 const MACH_HEADER_TYPE
*mh
= (const MACH_HEADER_TYPE
*)_dyld_get_image_header(i
);
3990 uintptr_t addr
= (uintptr_t)p
- _dyld_get_image_vmaddr_slide(i
);
3992 struct load_command
*lc
= (struct load_command
*)((char *)mh
+ sizeof(MACH_HEADER_TYPE
));
3993 for (j
= 0; !foundit
&& j
< mh
->ncmds
; j
++, lc
= (struct load_command
*)((char *)lc
+ lc
->cmdsize
)) {
3994 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
) {
3996 name
= _dyld_get_image_name(i
);
3997 if (name
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, name
);
4002 #undef MACH_HEADER_TYPE
4003 #undef MACH_SEGMENT_CMD_TYPE
4004 #undef MACH_SEGMENT_FLAVOR
4006 #endif /* USE_DYLD_PRIV */
4008 printf("dyld image path for pointer %p is %p\n", p
, result
);
4009 #endif /* LOG_BUNDLE_LOAD */
4013 #if !defined(BINARY_SUPPORT_DLFCN)
4015 static const void *__CFBundleDYLDFindImage(char *buff
) {
4016 const void *header
= NULL
;
4017 uint32_t i
, numImages
= _dyld_image_count(), numMatches
= 0;
4018 const char *curName
, *p
, *q
;
4020 for (i
= 0; !header
&& i
< numImages
; i
++) {
4021 curName
= _dyld_get_image_name(i
);
4022 if (curName
&& 0 == strncmp(curName
, buff
, CFMaxPathSize
)) {
4023 header
= _dyld_get_image_header(i
);
4028 for (i
= 0; i
< numImages
; i
++) {
4029 curName
= _dyld_get_image_name(i
);
4031 for (p
= buff
, q
= curName
; *p
&& *q
&& (q
- curName
< CFMaxPathSize
); p
++, q
++) {
4032 if (*p
!= *q
&& (q
- curName
> 11) && 0 == strncmp(q
- 11, ".framework/Versions/", 20) && *(q
+ 9) && '/' == *(q
+ 10)) q
+= 11;
4033 else if (*p
!= *q
&& (q
- curName
> 12) && 0 == strncmp(q
- 12, ".framework/Versions/", 20) && *(q
+ 8) && '/' == *(q
+ 9)) q
+= 10;
4034 if (*p
!= *q
) break;
4037 header
= _dyld_get_image_header(i
);
4043 return (numMatches
== 1) ? header
: NULL
;
4046 CF_PRIVATE Boolean
_CFBundleDYLDCheckLoaded(CFBundleRef bundle
) {
4047 if (!bundle
->_isLoaded
) {
4048 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4049 char buff
[CFMaxPathSize
];
4051 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4052 const void *header
= __CFBundleDYLDFindImage(buff
);
4054 if (bundle
->_binaryType
== __CFBundleUnknownBinary
) bundle
->_binaryType
= __CFBundleDYLDFrameworkBinary
;
4055 if (!bundle
->_imageCookie
) {
4056 bundle
->_imageCookie
= header
;
4058 printf("dyld check load bundle %p, find %s getting image %p\n", bundle
, buff
, bundle
->_imageCookie
);
4059 #endif /* LOG_BUNDLE_LOAD */
4061 bundle
->_isLoaded
= true;
4064 printf("dyld check load bundle %p, find %s no image\n", bundle
, buff
);
4065 #endif /* LOG_BUNDLE_LOAD */
4068 if (executableURL
) CFRelease(executableURL
);
4070 return bundle
->_isLoaded
;
4073 CF_PRIVATE Boolean
_CFBundleDYLDLoadBundle(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
4074 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4075 NSLinkEditErrors c
= NSLinkEditUndefinedError
;
4076 int errorNumber
= 0;
4077 const char *fileName
= NULL
;
4078 const char *errorString
= NULL
;
4080 if (!bundle
->_isLoaded
) {
4081 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4082 char buff
[CFMaxPathSize
];
4084 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4085 NSObjectFileImage image
;
4086 NSObjectFileImageReturnCode retCode
= NSCreateObjectFileImageFromFile(buff
, &image
);
4088 printf("dyld load bundle %p, create image of %s returns image %p retcode %d\n", bundle
, buff
, image
, retCode
);
4089 #endif /* LOG_BUNDLE_LOAD */
4090 if (retCode
== NSObjectFileImageSuccess
) {
4091 uint32_t options
= forceGlobal
? NSLINKMODULE_OPTION_RETURN_ON_ERROR
: (NSLINKMODULE_OPTION_BINDNOW
| NSLINKMODULE_OPTION_PRIVATE
| NSLINKMODULE_OPTION_RETURN_ON_ERROR
);
4092 NSModule
module = NSLinkModule(image
, buff
, options
);
4094 printf("dyld load bundle %p, link module of %s options 0x%x returns module %p image %p\n", bundle
, buff
, options
, module, image
);
4095 #endif /* LOG_BUNDLE_LOAD */
4097 bundle
->_imageCookie
= image
;
4098 bundle
->_moduleCookie
= module;
4099 bundle
->_isLoaded
= true;
4101 NSLinkEditError(&c
, &errorNumber
, &fileName
, &errorString
);
4103 #if defined(BINARY_SUPPORT_DLFCN)
4104 _CFBundleDlfcnPreflight(bundle
, subError
);
4105 #endif /* BINARY_SUPPORT_DLFCN */
4107 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("error code %d, error number %d (%@)"), c
, errorNumber
, tempString
);
4108 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4109 if (tempString
) CFRelease(tempString
);
4110 if (debugString
) CFRelease(debugString
);
4113 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, fileName
);
4114 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString
, c
, errorNumber
, tempString
);
4115 if (tempString
) CFRelease(tempString
);
4116 if (executableString
) CFRelease(executableString
);
4118 (void)NSDestroyObjectFileImage(image
);
4122 if (retCode
== NSObjectFileImageArch
) {
4123 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableArchitectureMismatchError
);
4124 } else if (retCode
== NSObjectFileImageInappropriateFile
) {
4125 Boolean hasRuntimeMismatch
= false;
4126 uint32_t mainFlags
= 0, bundleFlags
= 0;
4127 if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL
, &mainFlags
) && (mainFlags
& 0x2) != 0) {
4128 if (_CFBundleGetObjCImageInfo(bundle
, NULL
, &bundleFlags
) && (bundleFlags
& 0x2) == 0) hasRuntimeMismatch
= true;
4130 if (hasRuntimeMismatch
) {
4131 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableRuntimeMismatchError
);
4133 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotLoadableError
);
4136 #if defined(BINARY_SUPPORT_DLFCN)
4137 _CFBundleDlfcnPreflight(bundle
, subError
);
4138 #endif /* BINARY_SUPPORT_DLFCN */
4140 CFStringRef debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("dyld returns %d"), retCode
);
4141 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4142 CFRelease(debugString
);
4146 CFLog(__kCFLogBundle
, CFSTR("dyld returns %d when trying to load %@"), retCode
, executableURL
);
4151 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4153 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4156 if (executableURL
) CFRelease(executableURL
);
4158 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4159 return bundle
->_isLoaded
;
4162 CF_PRIVATE Boolean
_CFBundleDYLDLoadFramework(CFBundleRef bundle
, CFErrorRef
*error
) {
4163 // !!! Framework loading should be better. Can't unload frameworks.
4164 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4165 NSLinkEditErrors c
= NSLinkEditUndefinedError
;
4166 int errorNumber
= 0;
4167 const char *fileName
= NULL
;
4168 const char *errorString
= NULL
;
4170 if (!bundle
->_isLoaded
) {
4171 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4172 char buff
[CFMaxPathSize
];
4174 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4175 void *image
= (void *)NSAddImage(buff
, NSADDIMAGE_OPTION_RETURN_ON_ERROR
);
4177 printf("dyld load framework %p, add image of %s returns image %p\n", bundle
, buff
, image
);
4178 #endif /* LOG_BUNDLE_LOAD */
4180 bundle
->_imageCookie
= image
;
4181 bundle
->_isLoaded
= true;
4183 NSLinkEditError(&c
, &errorNumber
, &fileName
, &errorString
);
4185 #if defined(BINARY_SUPPORT_DLFCN)
4186 _CFBundleDlfcnPreflight(bundle
, subError
);
4187 #endif /* BINARY_SUPPORT_DLFCN */
4189 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), debugString
= CFStringCreateWithFormat(kCFAllocatorSystemDefault
, NULL
, CFSTR("error code %d, error number %d (%@)"), c
, errorNumber
, tempString
);
4190 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4191 if (tempString
) CFRelease(tempString
);
4192 if (debugString
) CFRelease(debugString
);
4195 CFStringRef tempString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
), executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, fileName
);
4196 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString
, c
, errorNumber
, tempString
);
4197 if (tempString
) CFRelease(tempString
);
4198 if (executableString
) CFRelease(executableString
);
4203 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4205 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4208 if (executableURL
) CFRelease(executableURL
);
4210 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4211 return bundle
->_isLoaded
;
4214 CF_PRIVATE
void _CFBundleDYLDUnloadBundle(CFBundleRef bundle
) {
4215 if (bundle
->_isLoaded
) {
4217 printf("dyld unload bundle %p, handle %p module %p image %p\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
);
4218 #endif /* LOG_BUNDLE_LOAD */
4219 if (bundle
->_moduleCookie
&& !NSUnLinkModule((NSModule
)(bundle
->_moduleCookie
), NSUNLINKMODULE_OPTION_NONE
)) {
4220 CFLog(__kCFLogBundle
, CFSTR("Internal error unloading bundle %@"), bundle
);
4222 if (bundle
->_moduleCookie
&& bundle
->_imageCookie
) (void)NSDestroyObjectFileImage((NSObjectFileImage
)(bundle
->_imageCookie
));
4223 bundle
->_connectionCookie
= bundle
->_handleCookie
= NULL
;
4224 bundle
->_imageCookie
= bundle
->_moduleCookie
= NULL
;
4225 bundle
->_isLoaded
= false;
4230 CF_PRIVATE
void *_CFBundleDYLDGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {
4231 return _CFBundleDYLDGetSymbolByNameWithSearch(bundle
, symbolName
, false);
4234 static void *_CFBundleDYLDGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
) {
4235 void *result
= NULL
;
4237 NSSymbol symbol
= NULL
;
4240 if (CFStringGetCString(symbolName
, &(buff
[1]), 1024, kCFStringEncodingUTF8
)) {
4241 if (bundle
->_moduleCookie
) {
4242 symbol
= NSLookupSymbolInModule((NSModule
)(bundle
->_moduleCookie
), buff
);
4243 } else if (bundle
->_imageCookie
) {
4244 symbol
= NSLookupSymbolInImage(bundle
->_imageCookie
, buff
, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
|NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
);
4246 if (!symbol
&& !bundle
->_moduleCookie
&& (!bundle
->_imageCookie
|| globalSearch
)) {
4247 char hintBuff
[1026];
4248 CFStringRef executableName
= _CFBundleCopyExecutableName(bundle
, NULL
, NULL
);
4250 if (executableName
) {
4251 if (!CFStringGetCString(executableName
, hintBuff
, 1024, kCFStringEncodingUTF8
)) hintBuff
[0] = '\0';
4252 CFRelease(executableName
);
4254 // Nowdays, NSIsSymbolNameDefinedWithHint() and NSLookupAndBindSymbolWithHint()
4255 // are identical, except the first just returns a bool, so checking with the
4256 // Is function first just causes a redundant lookup.
4257 // This returns NULL on failure.
4258 symbol
= NSLookupAndBindSymbolWithHint(buff
, hintBuff
);
4260 if (symbol
) result
= NSAddressOfSymbol(symbol
);
4262 if (!result
) CFLog(__kCFLogBundle
, CFSTR("dyld cannot find symbol %@ in %@"), symbolName
, bundle
);
4265 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);
4266 #endif /* LOG_BUNDLE_LOAD */
4271 #endif /* !BINARY_SUPPORT_DLFCN */
4272 #endif /* BINARY_SUPPORT_DYLD */
4274 #if defined(BINARY_SUPPORT_DLFCN)
4276 CF_PRIVATE Boolean
_CFBundleDlfcnCheckLoaded(CFBundleRef bundle
) {
4277 if (!bundle
->_isLoaded
) {
4278 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4279 char buff
[CFMaxPathSize
];
4281 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4282 int mode
= RTLD_LAZY
| RTLD_LOCAL
| RTLD_NOLOAD
| RTLD_FIRST
;
4283 void *handle
= dlopen(buff
, mode
);
4285 if (!bundle
->_handleCookie
) {
4286 bundle
->_handleCookie
= handle
;
4288 printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x getting handle %p\n", bundle
, buff
, mode
, bundle
->_handleCookie
);
4289 #endif /* LOG_BUNDLE_LOAD */
4291 bundle
->_isLoaded
= true;
4294 printf("dlfcn check load bundle %p, dlopen of %s mode 0x%x no handle\n", bundle
, buff
, mode
);
4295 #endif /* LOG_BUNDLE_LOAD */
4298 if (executableURL
) CFRelease(executableURL
);
4300 return bundle
->_isLoaded
;
4303 CF_EXPORT Boolean
_CFBundleDlfcnPreflight(CFBundleRef bundle
, CFErrorRef
*error
) {
4304 Boolean retval
= true;
4305 CFErrorRef localError
= NULL
;
4306 if (!bundle
->_isLoaded
) {
4307 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4308 char buff
[CFMaxPathSize
];
4311 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4312 retval
= dlopen_preflight(buff
);
4313 if (!retval
&& error
) {
4314 CFArrayRef archs
= CFBundleCopyExecutableArchitectures(bundle
);
4315 CFStringRef debugString
= NULL
;
4316 const char *errorString
= dlerror();
4317 if (errorString
&& strlen(errorString
) > 0) debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
4319 Boolean hasSuitableArch
= false, hasRuntimeMismatch
= false;
4320 CFIndex i
, count
= CFArrayGetCount(archs
);
4321 SInt32 arch
, curArch
= _CFBundleCurrentArchitecture();
4322 for (i
= 0; !hasSuitableArch
&& i
< count
; i
++) {
4323 if (CFNumberGetValue((CFNumberRef
)CFArrayGetValueAtIndex(archs
, i
), kCFNumberSInt32Type
, (void *)&arch
) && arch
== curArch
) hasSuitableArch
= true;
4325 #if defined(BINARY_SUPPORT_DYLD)
4326 if (hasSuitableArch
) {
4327 uint32_t mainFlags
= 0;
4328 if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL
, &mainFlags
) && (mainFlags
& 0x2) != 0) {
4329 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
4330 uint32_t bundleFlags
= 0;
4331 if (_CFBundleGetObjCImageInfo(bundle
, NULL
, &bundleFlags
) && (bundleFlags
& 0x2) == 0) hasRuntimeMismatch
= true;
4335 #endif /* BINARY_SUPPORT_DYLD */
4336 if (hasRuntimeMismatch
) {
4337 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableRuntimeMismatchError
, debugString
);
4338 } else if (!hasSuitableArch
) {
4339 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableArchitectureMismatchError
, debugString
);
4341 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLoadError
, debugString
);
4345 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLoadError
, debugString
);
4347 if (debugString
) CFRelease(debugString
);
4350 if (error
) localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4352 if (executableURL
) CFRelease(executableURL
);
4354 if (!retval
&& error
) *error
= localError
;
4358 CF_PRIVATE Boolean
_CFBundleDlfcnLoadBundle(CFBundleRef bundle
, Boolean forceGlobal
, CFErrorRef
*error
) {
4359 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4360 if (!bundle
->_isLoaded
) {
4361 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4362 char buff
[CFMaxPathSize
];
4363 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4364 int mode
= forceGlobal
? (RTLD_LAZY
| RTLD_GLOBAL
| RTLD_FIRST
) : (RTLD_NOW
| RTLD_LOCAL
| RTLD_FIRST
);
4365 void *cookie
= dlopen(buff
, mode
);
4367 printf("dlfcn load bundle %p, dlopen of %s mode 0x%x returns handle %p\n", bundle
, buff
, mode
, cookie
);
4368 #endif /* LOG_BUNDLE_LOAD */
4369 if (cookie
&& cookie
== bundle
->_handleCookie
) {
4370 // 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
4372 printf("dlfcn load bundle %p closing existing reference to handle %p\n", bundle
, cookie
);
4373 #endif /* LOG_BUNDLE_LOAD */
4374 dlclose(bundle
->_handleCookie
);
4376 bundle
->_handleCookie
= cookie
;
4377 if (bundle
->_handleCookie
) {
4378 bundle
->_isLoaded
= true;
4380 const char *errorString
= dlerror();
4382 _CFBundleDlfcnPreflight(bundle
, subError
);
4384 CFStringRef debugString
= errorString
? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
) : NULL
;
4385 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4386 if (debugString
) CFRelease(debugString
);
4389 CFStringRef executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, buff
);
4391 CFStringRef debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
4392 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: %@"), executableString
, debugString
);
4393 if (debugString
) CFRelease(debugString
);
4395 CFLog(__kCFLogBundle
, CFSTR("Error loading %@"), executableString
);
4397 if (executableString
) CFRelease(executableString
);
4402 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4404 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4407 if (executableURL
) CFRelease(executableURL
);
4409 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4410 return bundle
->_isLoaded
;
4413 CF_PRIVATE Boolean
_CFBundleDlfcnLoadFramework(CFBundleRef bundle
, CFErrorRef
*error
) {
4414 CFErrorRef localError
= NULL
, *subError
= (error
? &localError
: NULL
);
4415 if (!bundle
->_isLoaded
) {
4416 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4417 char buff
[CFMaxPathSize
];
4418 if (executableURL
&& CFURLGetFileSystemRepresentation(executableURL
, true, (uint8_t *)buff
, CFMaxPathSize
)) {
4419 int mode
= RTLD_LAZY
| RTLD_GLOBAL
| RTLD_FIRST
;
4420 void *cookie
= dlopen(buff
, mode
);
4422 printf("dlfcn load framework %p, dlopen of %s mode 0x%x returns handle %p\n", bundle
, buff
, mode
, cookie
);
4423 #endif /* LOG_BUNDLE_LOAD */
4424 if (cookie
&& cookie
== bundle
->_handleCookie
) {
4425 // 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
4427 printf("dlfcn load framework %p closing existing reference to handle %p\n", bundle
, cookie
);
4428 #endif /* LOG_BUNDLE_LOAD */
4429 dlclose(bundle
->_handleCookie
);
4431 bundle
->_handleCookie
= cookie
;
4432 if (bundle
->_handleCookie
) {
4433 bundle
->_isLoaded
= true;
4435 const char *errorString
= dlerror();
4437 _CFBundleDlfcnPreflight(bundle
, subError
);
4439 CFStringRef debugString
= errorString
? CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
) : NULL
;
4440 localError
= _CFBundleCreateErrorDebug(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
, debugString
);
4441 if (debugString
) CFRelease(debugString
);
4444 CFStringRef executableString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, buff
);
4446 CFStringRef debugString
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, errorString
);
4447 CFLog(__kCFLogBundle
, CFSTR("Error loading %@: %@"), executableString
, debugString
);
4448 if (debugString
) CFRelease(debugString
);
4450 CFLog(__kCFLogBundle
, CFSTR("Error loading %@"), executableString
);
4452 if (executableString
) CFRelease(executableString
);
4457 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4459 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4462 if (executableURL
) CFRelease(executableURL
);
4464 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4465 return bundle
->_isLoaded
;
4468 CF_PRIVATE
void _CFBundleDlfcnUnload(CFBundleRef bundle
) {
4469 if (bundle
->_isLoaded
) {
4471 printf("dlfcn unload bundle %p, handle %p module %p image %p\n", bundle
, bundle
->_handleCookie
, bundle
->_moduleCookie
, bundle
->_imageCookie
);
4472 #endif /* LOG_BUNDLE_LOAD */
4473 if (0 != dlclose(bundle
->_handleCookie
)) {
4474 CFLog(__kCFLogBundle
, CFSTR("Internal error unloading bundle %@"), bundle
);
4476 bundle
->_connectionCookie
= bundle
->_handleCookie
= NULL
;
4477 bundle
->_imageCookie
= bundle
->_moduleCookie
= NULL
;
4478 bundle
->_isLoaded
= false;
4483 CF_PRIVATE
void *_CFBundleDlfcnGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {
4484 return _CFBundleDlfcnGetSymbolByNameWithSearch(bundle
, symbolName
, false);
4487 static void *_CFBundleDlfcnGetSymbolByNameWithSearch(CFBundleRef bundle
, CFStringRef symbolName
, Boolean globalSearch
) {
4488 void *result
= NULL
;
4491 if (CFStringGetCString(symbolName
, buff
, 1024, kCFStringEncodingUTF8
)) {
4492 result
= dlsym(bundle
->_handleCookie
, buff
);
4493 if (!result
&& globalSearch
) result
= dlsym(RTLD_DEFAULT
, buff
);
4495 if (!result
) CFLog(__kCFLogBundle
, CFSTR("dlsym cannot find symbol %@ in %@"), symbolName
, bundle
);
4498 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
);
4499 #endif /* LOG_BUNDLE_LOAD */
4504 #if !defined(BINARY_SUPPORT_DYLD)
4506 static CFStringRef
_CFBundleDlfcnCopyLoadedImagePathForPointer(void *p
) {
4507 CFStringRef result
= NULL
;
4509 if (0 != dladdr(p
, &info
) && info
.dli_fname
) result
= CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault
, info
.dli_fname
);
4511 printf("dlfcn image path for pointer %p is %p\n", p
, result
);
4512 #endif /* LOG_BUNDLE_LOAD */
4516 #endif /* !BINARY_SUPPORT_DYLD */
4517 #endif /* BINARY_SUPPORT_DLFCN */
4519 #if defined(BINARY_SUPPORT_DLL)
4521 CF_PRIVATE Boolean
_CFBundleDLLLoad(CFBundleRef bundle
, CFErrorRef
*error
) {
4522 CFErrorRef localError
= NULL
;
4523 if (!bundle
->_isLoaded
) {
4524 CFURLRef executableURL
= CFBundleCopyExecutableURL(bundle
);
4525 wchar_t buff
[CFMaxPathSize
];
4527 if (executableURL
&& _CFURLGetWideFileSystemRepresentation(executableURL
, true, (wchar_t *)buff
, CFMaxPathSize
)) {
4528 bundle
->_hModule
= LoadLibraryW(buff
);
4529 if (bundle
->_hModule
) {
4530 bundle
->_isLoaded
= true;
4533 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableLinkError
);
4535 CFLog(__kCFLogBundle
, CFSTR("Failed to load bundle %@"), bundle
);
4540 localError
= _CFBundleCreateError(CFGetAllocator(bundle
), bundle
, CFBundleExecutableNotFoundError
);
4542 CFLog(__kCFLogBundle
, CFSTR("Cannot find executable for bundle %@"), bundle
);
4545 if (executableURL
) CFRelease(executableURL
);
4547 if (!bundle
->_isLoaded
&& error
) *error
= localError
;
4548 return bundle
->_isLoaded
;
4551 CF_PRIVATE
void _CFBundleDLLUnload(CFBundleRef bundle
) {
4552 if (bundle
->_isLoaded
) {
4553 FreeLibrary(bundle
->_hModule
);
4554 bundle
->_hModule
= NULL
;
4555 bundle
->_isLoaded
= false;
4559 CF_PRIVATE
void *_CFBundleDLLGetSymbolByName(CFBundleRef bundle
, CFStringRef symbolName
) {
4560 void *result
= NULL
;
4562 if (CFStringGetCString(symbolName
, buff
, 1024, kCFStringEncodingWindowsLatin1
)) result
= GetProcAddress(bundle
->_hModule
, buff
);
4566 #endif /* BINARY_SUPPORT_DLL */
4568 /* Workarounds to be applied in the presence of certain bundles can go here. This is called on every bundle creation.