/ CFBundle.c
CFBundle.c
   1  /*
   2   * Copyright (c) 2015 Apple Inc. All rights reserved.
   3   *
   4   * @APPLE_LICENSE_HEADER_START@
   5   *
   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
  11   * file.
  12   *
  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.
  20   *
  21   * @APPLE_LICENSE_HEADER_END@
  22   */
  23  
  24  /*      CFBundle.c
  25          Copyright (c) 1999-2014, Apple Inc.  All rights reserved.
  26          Responsibility: Tony Parker
  27  */
  28  
  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>
  35  #include <string.h>
  36  #include <CoreFoundation/CFPriv.h>
  37  #include "CFInternal.h"
  38  #include <CoreFoundation/CFByteOrder.h>
  39  #include "CFBundle_BinaryTypes.h"
  40  #include <ctype.h>
  41  #include <sys/stat.h>
  42  #include <stdlib.h>
  43  #include <stdio.h>
  44  
  45  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI || DEPLOYMENT_TARGET_WINDOWS
  46  #else
  47  #error Unknown deployment target
  48  #endif
  49  
  50  #define AVOID_WEAK_COLLECTIONS 1
  51  
  52  #if !AVOID_WEAK_COLLECTIONS
  53  #include "CFHashTable.h"
  54  #include "CFMapTable.h"
  55  #include "CFPointerArray.h"
  56  #endif /* !AVOID_WEAK_COLLECTIONS */
  57  
  58  #if defined(BINARY_SUPPORT_DYLD)
  59  #include <unistd.h>
  60  #include <fcntl.h>
  61  #include <sys/mman.h>
  62  #include <crt_externs.h>
  63  #endif /* BINARY_SUPPORT_DYLD */
  64  
  65  #if defined(BINARY_SUPPORT_DLFCN)
  66  #include <dlfcn.h>
  67  #endif /* BINARY_SUPPORT_DLFCN */
  68  
  69  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
  70  #include <fcntl.h>
  71  #elif DEPLOYMENT_TARGET_WINDOWS
  72  #include <fcntl.h>
  73  #include <io.h>
  74  #endif
  75  
  76  
  77  static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean alreadyLocked);
  78  
  79  #define LOG_BUNDLE_LOAD 0
  80  
  81  // Public CFBundle Info plist keys
  82  CONST_STRING_DECL(kCFBundleInfoDictionaryVersionKey, "CFBundleInfoDictionaryVersion")
  83  CONST_STRING_DECL(kCFBundleExecutableKey, "CFBundleExecutable")
  84  CONST_STRING_DECL(kCFBundleIdentifierKey, "CFBundleIdentifier")
  85  CONST_STRING_DECL(kCFBundleVersionKey, "CFBundleVersion")
  86  CONST_STRING_DECL(kCFBundleDevelopmentRegionKey, "CFBundleDevelopmentRegion")
  87  CONST_STRING_DECL(kCFBundleLocalizationsKey, "CFBundleLocalizations")
  88  
  89  // Private CFBundle Info plist keys, possible candidates for public constants
  90  CONST_STRING_DECL(_kCFBundleAllowMixedLocalizationsKey, "CFBundleAllowMixedLocalizations")
  91  CONST_STRING_DECL(_kCFBundleSupportedPlatformsKey, "CFBundleSupportedPlatforms")
  92  CONST_STRING_DECL(_kCFBundleResourceSpecificationKey, "CFBundleResourceSpecification")
  93  
  94  // Finder stuff
  95  CONST_STRING_DECL(_kCFBundlePackageTypeKey, "CFBundlePackageType")
  96  CONST_STRING_DECL(_kCFBundleSignatureKey, "CFBundleSignature")
  97  CONST_STRING_DECL(_kCFBundleIconFileKey, "CFBundleIconFile")
  98  CONST_STRING_DECL(_kCFBundleDocumentTypesKey, "CFBundleDocumentTypes")
  99  CONST_STRING_DECL(_kCFBundleURLTypesKey, "CFBundleURLTypes")
 100  
 101  // Keys that are usually localized in InfoPlist.strings
 102  CONST_STRING_DECL(kCFBundleNameKey, "CFBundleName")
 103  CONST_STRING_DECL(_kCFBundleDisplayNameKey, "CFBundleDisplayName")
 104  CONST_STRING_DECL(_kCFBundleShortVersionStringKey, "CFBundleShortVersionString")
 105  CONST_STRING_DECL(_kCFBundleGetInfoStringKey, "CFBundleGetInfoString")
 106  CONST_STRING_DECL(_kCFBundleGetInfoHTMLKey, "CFBundleGetInfoHTML")
 107  
 108  // Sub-keys for CFBundleDocumentTypes dictionaries
 109  CONST_STRING_DECL(_kCFBundleTypeNameKey, "CFBundleTypeName")
 110  CONST_STRING_DECL(_kCFBundleTypeRoleKey, "CFBundleTypeRole")
 111  CONST_STRING_DECL(_kCFBundleTypeIconFileKey, "CFBundleTypeIconFile")
 112  CONST_STRING_DECL(_kCFBundleTypeOSTypesKey, "CFBundleTypeOSTypes")
 113  CONST_STRING_DECL(_kCFBundleTypeExtensionsKey, "CFBundleTypeExtensions")
 114  CONST_STRING_DECL(_kCFBundleTypeMIMETypesKey, "CFBundleTypeMIMETypes")
 115  
 116  // Sub-keys for CFBundleURLTypes dictionaries
 117  CONST_STRING_DECL(_kCFBundleURLNameKey, "CFBundleURLName")
 118  CONST_STRING_DECL(_kCFBundleURLIconFileKey, "CFBundleURLIconFile")
 119  CONST_STRING_DECL(_kCFBundleURLSchemesKey, "CFBundleURLSchemes")
 120  
 121  // Compatibility key names
 122  CONST_STRING_DECL(_kCFBundleOldExecutableKey, "NSExecutable")
 123  CONST_STRING_DECL(_kCFBundleOldInfoDictionaryVersionKey, "NSInfoPlistVersion")
 124  CONST_STRING_DECL(_kCFBundleOldNameKey, "NSHumanReadableName")
 125  CONST_STRING_DECL(_kCFBundleOldIconFileKey, "NSIcon")
 126  CONST_STRING_DECL(_kCFBundleOldDocumentTypesKey, "NSTypes")
 127  CONST_STRING_DECL(_kCFBundleOldShortVersionStringKey, "NSAppVersion")
 128  
 129  // Compatibility CFBundleDocumentTypes key names
 130  CONST_STRING_DECL(_kCFBundleOldTypeNameKey, "NSName")
 131  CONST_STRING_DECL(_kCFBundleOldTypeRoleKey, "NSRole")
 132  CONST_STRING_DECL(_kCFBundleOldTypeIconFileKey, "NSIcon")
 133  CONST_STRING_DECL(_kCFBundleOldTypeExtensions1Key, "NSUnixExtensions")
 134  CONST_STRING_DECL(_kCFBundleOldTypeExtensions2Key, "NSDOSExtensions")
 135  CONST_STRING_DECL(_kCFBundleOldTypeOSTypesKey, "NSMacOSType")
 136  
 137  // Internally used keys for loaded Info plists.
 138  CONST_STRING_DECL(_kCFBundleInfoPlistURLKey, "CFBundleInfoPlistURL")
 139  CONST_STRING_DECL(_kCFBundleRawInfoPlistURLKey, "CFBundleRawInfoPlistURL")
 140  CONST_STRING_DECL(_kCFBundleNumericVersionKey, "CFBundleNumericVersion")
 141  CONST_STRING_DECL(_kCFBundleExecutablePathKey, "CFBundleExecutablePath")
 142  CONST_STRING_DECL(_kCFBundleResourcesFileMappedKey, "CSResourcesFileMapped")
 143  CONST_STRING_DECL(_kCFBundleCFMLoadAsBundleKey, "CFBundleCFMLoadAsBundle")
 144  
 145  // Keys used by NSBundle for loaded Info plists.
 146  CONST_STRING_DECL(_kCFBundlePrincipalClassKey, "NSPrincipalClass")
 147  
 148  static char __CFBundleMainID__[1026] = {0};
 149  CF_PRIVATE char *__CFBundleMainID = __CFBundleMainID__;
 150  
 151  static CFTypeID __kCFBundleTypeID = _kCFRuntimeNotATypeID;
 152  
 153  static pthread_mutex_t CFBundleGlobalDataLock = PTHREAD_MUTEX_INITIALIZER;
 154  
 155  static CFMutableDictionaryRef _bundlesByIdentifier = NULL;
 156  #if AVOID_WEAK_COLLECTIONS
 157  static CFMutableDictionaryRef _bundlesByURL = NULL;
 158  static CFMutableArrayRef _allBundles = NULL;
 159  static CFMutableSetRef _bundlesToUnload = NULL;
 160  #else /* AVOID_WEAK_COLLECTIONS */
 161  static __CFHashTable *_allBundles = nil;
 162  static __CFHashTable *_bundlesToUnload = nil;
 163  #endif /* AVOID_WEAK_COLLECTIONS */
 164  static Boolean _scheduledBundlesAreUnloading = false;
 165  
 166  static Boolean _initedMainBundle = false;
 167  static CFBundleRef _mainBundle = NULL;
 168  
 169  // Forward declares functions.
 170  static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, Boolean alreadyLocked, Boolean doFinalProcessing, Boolean noCaches);
 171  static CFURLRef _CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle);
 172  static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint);
 173  static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void);
 174  static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath);
 175  static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths);
 176  
 177  #pragma mark -
 178  
 179  
 180  
 181  
 182  #if AVOID_WEAK_COLLECTIONS
 183  
 184  static void _CFBundleAddToTables(CFBundleRef bundle, Boolean alreadyLocked) {
 185      CFStringRef bundleID = CFBundleGetIdentifier(bundle);
 186  
 187      if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
 188      
 189      // Add to the _allBundles list
 190      if (!_allBundles) {
 191          CFArrayCallBacks nonRetainingArrayCallbacks = kCFTypeArrayCallBacks;
 192          nonRetainingArrayCallbacks.retain = NULL;
 193          nonRetainingArrayCallbacks.release = NULL;
 194          _allBundles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &nonRetainingArrayCallbacks);
 195      }
 196      CFArrayAppendValue(_allBundles, bundle);
 197      
 198      // Add to the table that maps urls to bundles
 199      if (!_bundlesByURL) {
 200          CFDictionaryValueCallBacks nonRetainingDictionaryValueCallbacks = kCFTypeDictionaryValueCallBacks;
 201          nonRetainingDictionaryValueCallbacks.retain = NULL;
 202          nonRetainingDictionaryValueCallbacks.release = NULL;
 203          _bundlesByURL = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &nonRetainingDictionaryValueCallbacks);
 204      }
 205      CFDictionarySetValue(_bundlesByURL, bundle->_url, bundle);
 206  
 207      // Add to the table that maps identifiers to bundles
 208      if (bundleID) {
 209          CFMutableArrayRef bundlesWithThisID = NULL;
 210          CFBundleRef existingBundle = NULL;
 211          if (!_bundlesByIdentifier) {
 212              _bundlesByIdentifier = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 213          }
 214          bundlesWithThisID = (CFMutableArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
 215          if (bundlesWithThisID) {
 216              CFIndex i, count = CFArrayGetCount(bundlesWithThisID);
 217              UInt32 existingVersion, newVersion = CFBundleGetVersionNumber(bundle);
 218              for (i = 0; i < count; i++) {
 219                  existingBundle = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, i);
 220                  existingVersion = CFBundleGetVersionNumber(existingBundle);
 221                  // If you load two bundles with the same identifier and the same version, the last one wins.
 222                  if (newVersion >= existingVersion) break;
 223              }
 224              CFArrayInsertValueAtIndex(bundlesWithThisID, i, bundle);
 225          } else {
 226              CFArrayCallBacks nonRetainingArrayCallbacks = kCFTypeArrayCallBacks;
 227              nonRetainingArrayCallbacks.retain = NULL;
 228              nonRetainingArrayCallbacks.release = NULL;
 229              bundlesWithThisID = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &nonRetainingArrayCallbacks);
 230              CFArrayAppendValue(bundlesWithThisID, bundle);
 231              CFDictionarySetValue(_bundlesByIdentifier, bundleID, bundlesWithThisID);
 232              CFRelease(bundlesWithThisID);
 233          }
 234      }
 235      if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
 236  }
 237  
 238  static void _CFBundleRemoveFromTables(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef bundleID) {
 239      pthread_mutex_lock(&CFBundleGlobalDataLock);
 240      // Remove from the various lists
 241      if (_allBundles) {
 242          CFIndex i = CFArrayGetFirstIndexOfValue(_allBundles, CFRangeMake(0, CFArrayGetCount(_allBundles)), bundle);
 243          if (i >= 0) CFArrayRemoveValueAtIndex(_allBundles, i);
 244      }
 245  
 246      // Remove from the table that maps urls to bundles
 247      if (bundleURL && _bundlesByURL) {
 248          CFBundleRef bundleForURL = (CFBundleRef)CFDictionaryGetValue(_bundlesByURL, bundleURL);
 249          if (bundleForURL == bundle) CFDictionaryRemoveValue(_bundlesByURL, bundleURL);
 250      }
 251      
 252      // Remove from the table that maps identifiers to bundles
 253      if (bundleID && _bundlesByIdentifier) {
 254          CFMutableArrayRef bundlesWithThisID = (CFMutableArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
 255          if (bundlesWithThisID) {
 256              CFIndex count = CFArrayGetCount(bundlesWithThisID);
 257              while (count-- > 0) if (bundle == (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, count)) CFArrayRemoveValueAtIndex(bundlesWithThisID, count);
 258              if (0 == CFArrayGetCount(bundlesWithThisID)) CFDictionaryRemoveValue(_bundlesByIdentifier, bundleID);
 259          }
 260      }
 261      pthread_mutex_unlock(&CFBundleGlobalDataLock);
 262  }
 263  
 264  static CFBundleRef _CFBundleCopyBundleForURL(CFURLRef url, Boolean alreadyLocked) {
 265      CFBundleRef result = NULL;
 266      if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
 267      if (_bundlesByURL) result = (CFBundleRef)CFDictionaryGetValue(_bundlesByURL, url);
 268      if (result && !result->_url) {
 269          result = NULL;
 270          CFDictionaryRemoveValue(_bundlesByURL, url);
 271      }
 272      if (result) CFRetain(result);
 273      if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
 274      return result;
 275  }
 276  
 277  static CFBundleRef _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID) {
 278      CFBundleRef result = NULL, bundle;
 279      if (_bundlesByIdentifier && bundleID) {
 280          // Note that this array is maintained in descending order by version number
 281          CFArrayRef bundlesWithThisID = (CFArrayRef)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
 282          if (bundlesWithThisID) {
 283              CFIndex i, count = CFArrayGetCount(bundlesWithThisID);
 284              if (count > 0) {
 285                  // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
 286                  for (i = 0; !result && i < count; i++) {
 287                      bundle = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, i);
 288                      if (CFBundleIsExecutableLoaded(bundle)) result = bundle;
 289                  }
 290                  // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
 291                  if (!result) result = (CFBundleRef)CFArrayGetValueAtIndex(bundlesWithThisID, 0);
 292              }
 293          }
 294      }
 295      return result;
 296  }
 297  
 298  #else /* AVOID_WEAK_COLLECTIONS */
 299  
 300  /*
 301   An explanation of what I'm doing here is probably in order.
 302   8029300 has cast suspicion on the correctness of __CFMapTable with strong keys and weak values, at least under non-GC. 
 303   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
 304   This indicates that it's not an overrelease in securityd, since AVOID_WEAK_COLLECTIONS wouldn't help in that case.
 305   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.
 306   */
 307  static inline id _getBundlesByURL() {
 308      static id _bundles = nil;
 309      static dispatch_once_t onceToken;
 310      dispatch_once(&onceToken, ^{
 311          if (CF_USING_COLLECTABLE_MEMORY) {
 312              _bundles = [[__CFMapTable alloc] initWithKeyOptions:CFPointerFunctionsStrongMemory valueOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
 313          } else {
 314              CFDictionaryValueCallBacks nonRetainingDictionaryValueCallbacks = kCFTypeDictionaryValueCallBacks;
 315              nonRetainingDictionaryValueCallbacks.retain = NULL;
 316              nonRetainingDictionaryValueCallbacks.release = NULL;
 317              _bundles = (id)CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &nonRetainingDictionaryValueCallbacks);
 318          }
 319      });
 320      return _bundles;
 321  }
 322  
 323  #define _bundlesByURL _getBundlesByURL()
 324  
 325  static void _setInBundlesByURL(CFURLRef key, CFBundleRef bundle) {
 326      if (CF_USING_COLLECTABLE_MEMORY) {
 327          [(__CFMapTable *)_bundlesByURL setObject:(id)bundle forKey:(id)key];
 328      } else {
 329          CFDictionarySetValue((CFMutableDictionaryRef)_bundlesByURL, key, bundle);
 330      }
 331  }
 332  
 333  static void _removeFromBundlesByURL(CFURLRef key) {
 334      if (CF_USING_COLLECTABLE_MEMORY) {
 335          [(__CFMapTable *)_bundlesByURL removeObjectForKey:(id)key];
 336      } else {
 337          CFDictionaryRemoveValue((CFMutableDictionaryRef)_bundlesByURL, key);
 338      }
 339  }
 340  
 341  static CFBundleRef _getFromBundlesByURL(CFURLRef key) {
 342      if (CF_USING_COLLECTABLE_MEMORY) {
 343          return (CFBundleRef)[(__CFMapTable *)_bundlesByURL objectForKey:(id)key];
 344      } else {
 345          return (CFBundleRef)CFDictionaryGetValue((CFMutableDictionaryRef)_bundlesByURL, key);
 346      }
 347  }
 348  
 349  static void _CFBundleAddToTables(CFBundleRef bundle, Boolean alreadyLocked) {
 350      CFStringRef bundleID = CFBundleGetIdentifier(bundle);
 351  
 352      if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
 353      
 354      // Add to the _allBundles list
 355      if (!_allBundles) _allBundles = [[__CFHashTable alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
 356      [_allBundles addObject:(id)bundle];
 357      
 358      // Add to the table that maps urls to bundles
 359      _setInBundlesByURL(bundle->_url, bundle);
 360  
 361      // Add to the table that maps identifiers to bundles
 362      if (bundleID) {
 363          __CFPointerArray *bundlesWithThisID = nil;
 364          CFBundleRef existingBundle = NULL;
 365          if (!_bundlesByIdentifier) {
 366              _bundlesByIdentifier = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 367          }
 368          bundlesWithThisID = (__CFPointerArray *)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
 369          if (bundlesWithThisID) {
 370              CFIndex i, count = (CFIndex)[bundlesWithThisID count];
 371              UInt32 existingVersion, newVersion = CFBundleGetVersionNumber(bundle);
 372              for (i = 0; i < count; i++) {
 373                  existingBundle = (CFBundleRef)[bundlesWithThisID pointerAtIndex:i];
 374                  if (!existingBundle) continue;
 375                  existingVersion = CFBundleGetVersionNumber(existingBundle);
 376                  // If you load two bundles with the same identifier and the same version, the last one wins.
 377                  if (newVersion >= existingVersion) break;
 378              }
 379              if (i < count) {
 380                  [bundlesWithThisID insertPointer:bundle atIndex:i];
 381              } else {
 382                  [bundlesWithThisID addPointer:bundle];
 383              }
 384          } else {
 385              bundlesWithThisID = [[__CFPointerArray alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory];
 386              [bundlesWithThisID addPointer:bundle];
 387              CFDictionarySetValue(_bundlesByIdentifier, bundleID, bundlesWithThisID);
 388              [bundlesWithThisID release];
 389          }
 390      }
 391      if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
 392  }
 393  
 394  static void _CFBundleRemoveFromTables(CFBundleRef bundle, CFURLRef bundleURL, CFStringRef bundleID) {
 395      pthread_mutex_lock(&CFBundleGlobalDataLock);
 396      // Remove from the various lists
 397      if (_allBundles && [_allBundles member:(id)bundle]) [_allBundles removeObject:(id)bundle];
 398  
 399      // Remove from the table that maps urls to bundles
 400      if (bundleURL) {
 401          _removeFromBundlesByURL(bundleURL);
 402      }
 403      
 404      // Remove from the table that maps identifiers to bundles
 405      if (bundleID && _bundlesByIdentifier) {
 406          __CFPointerArray *bundlesWithThisID = (__CFPointerArray *)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
 407          if (bundlesWithThisID) {
 408              CFIndex count = (CFIndex)[bundlesWithThisID count];
 409              while (count-- > 0) if (bundle == (CFBundleRef)[bundlesWithThisID pointerAtIndex:count]) [bundlesWithThisID removePointerAtIndex:count];
 410              [bundlesWithThisID compact];
 411              if (0 == [bundlesWithThisID count]) CFDictionaryRemoveValue(_bundlesByIdentifier, bundleID);
 412          }
 413      }
 414      pthread_mutex_unlock(&CFBundleGlobalDataLock);
 415  }
 416  
 417  static CFBundleRef _CFBundleCopyBundleForURL(CFURLRef url, Boolean alreadyLocked) {
 418      CFBundleRef result = NULL;
 419      if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
 420      result = _getFromBundlesByURL(url);
 421      if (result && !result->_url) {
 422          result = NULL;
 423          _removeFromBundlesByURL(url);
 424      }
 425      if (result) CFRetain(result);
 426      if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
 427      return result;
 428  }
 429  
 430  static CFBundleRef _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(CFStringRef bundleID) {
 431      CFBundleRef result = NULL;
 432      if (_bundlesByIdentifier && bundleID) {
 433          // Note that this array is maintained in descending order by version number
 434          __CFPointerArray *bundlesWithThisID = (__CFPointerArray *)CFDictionaryGetValue(_bundlesByIdentifier, bundleID);
 435          if (bundlesWithThisID && [bundlesWithThisID count] > 0) {
 436              // First check for loaded bundles so we will always prefer a loaded to an unloaded bundle
 437              for (id bundle in bundlesWithThisID) {
 438                  if (bundle && CFBundleIsExecutableLoaded((CFBundleRef)bundle)) {
 439                      result = (CFBundleRef)bundle;
 440                      break;
 441                  }
 442              }
 443              // If no loaded bundle, simply take the first item in the array, i.e. the one with the latest version number
 444              if (!result) {
 445                  for (id bundle in bundlesWithThisID) {
 446                      if (bundle) {
 447                          result = (CFBundleRef)bundle;
 448                          break;
 449                      }
 450                  }
 451              }
 452          }
 453      }
 454      return result;
 455  }
 456  
 457  #endif /* AVOID_WEAK_COLLECTIONS */
 458  
 459  static CFURLRef _CFBundleCopyBundleURLForExecutablePath(CFStringRef str) {
 460      //!!! need to handle frameworks, NT; need to integrate with NSBundle - drd
 461      UniChar buff[CFMaxPathSize];
 462      CFIndex buffLen;
 463      CFURLRef url = NULL;
 464      CFStringRef outstr;
 465      
 466      buffLen = CFStringGetLength(str);
 467      if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
 468      CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff);
 469  
 470  #if DEPLOYMENT_TARGET_WINDOWS
 471      // Is this a .dll or .exe?
 472      if (buffLen >= 5 && (_wcsnicmp((wchar_t *)&(buff[buffLen-4]), L".dll", 4) == 0 || _wcsnicmp((wchar_t *)&(buff[buffLen-4]), L".exe", 4) == 0)) {
 473          CFIndex extensionLength = CFStringGetLength(_CFBundleWindowsResourceDirectoryExtension);
 474          buffLen -= 4;
 475          // If this is an _debug, we should strip that before looking for the bundle
 476          if (buffLen >= 7 && (_wcsnicmp((wchar_t *)&buff[buffLen-6], L"_debug", 6) == 0)) buffLen -= 6;
 477  
 478          if (buffLen + 1 + extensionLength < CFMaxPathSize) {
 479              buff[buffLen] = '.';
 480              buffLen ++;
 481              CFStringGetCharacters(_CFBundleWindowsResourceDirectoryExtension, CFRangeMake(0, extensionLength), buff + buffLen);
 482              buffLen += extensionLength;
 483              outstr = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, buff, buffLen, kCFAllocatorNull);
 484              url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, outstr, PLATFORM_PATH_STYLE, true);
 485              CFRelease(outstr);
 486          }
 487      }
 488  #endif
 489  
 490      if (!url) {
 491          buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);  // Remove exe name
 492  
 493          if (buffLen > 0) {
 494              // See if this is a new bundle.  If it is, we have to remove more path components.
 495              CFIndex startOfLastDir = _CFStartOfLastPathComponent(buff, buffLen);
 496              if (startOfLastDir > 0 && startOfLastDir < buffLen) {
 497                  CFStringRef lastDirName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfLastDir]), buffLen - startOfLastDir);
 498  
 499                  if (CFEqual(lastDirName, _CFBundleGetPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetAlternatePlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetOtherPlatformExecutablesSubdirectoryName()) || CFEqual(lastDirName, _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName())) {
 500                      // This is a new bundle.  Back off a few more levels
 501                      if (buffLen > 0) {
 502                          // Remove platform folder
 503                          buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
 504                      }
 505                      if (buffLen > 0) {
 506                          // Remove executables folder (if present)
 507                          CFIndex startOfNextDir = _CFStartOfLastPathComponent(buff, buffLen);
 508                          if (startOfNextDir > 0 && startOfNextDir < buffLen) {
 509                              CFStringRef nextDirName = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfNextDir]), buffLen - startOfNextDir);
 510                              if (CFEqual(nextDirName, _CFBundleExecutablesDirectoryName)) buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
 511                              CFRelease(nextDirName);
 512                          }
 513                      }
 514                      if (buffLen > 0) {
 515                          // Remove support files folder
 516                          buffLen = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
 517                      }
 518                  }
 519                  CFRelease(lastDirName);
 520              }
 521          }
 522  
 523          if (buffLen > 0) {
 524              outstr = CFStringCreateWithCharactersNoCopy(kCFAllocatorSystemDefault, buff, buffLen, kCFAllocatorNull);
 525              url = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, outstr, PLATFORM_PATH_STYLE, true);
 526              CFRelease(outstr);
 527          }
 528      }
 529      return url;
 530  }
 531  
 532  static CFURLRef _CFBundleCopyResolvedURLForExecutableURL(CFURLRef url) {
 533      // this is necessary so that we match any sanitization CFURL may perform on the result of _CFBundleCopyBundleURLForExecutableURL()
 534      CFURLRef absoluteURL, url1, url2, outURL = NULL;
 535      CFStringRef str, str1, str2;
 536      absoluteURL = CFURLCopyAbsoluteURL(url);
 537      str = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
 538      if (str) {
 539          UniChar buff[CFMaxPathSize];
 540          CFIndex buffLen = CFStringGetLength(str), len1;
 541          if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
 542          CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff);
 543          len1 = _CFLengthAfterDeletingLastPathComponent(buff, buffLen);
 544          if (len1 > 0 && len1 + 1 < buffLen) {          
 545              str1 = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, buff, len1);
 546              CFIndex skipSlashCount = 1;
 547  #if DEPLOYMENT_TARGET_WINDOWS
 548              // 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
 549              if (len1 == 3 && buff[1] == ':' && buff[2] == '\\') {
 550                  skipSlashCount = 0;
 551              }
 552  #endif
 553              str2 = CFStringCreateWithCharacters(kCFAllocatorSystemDefault, buff + len1 + skipSlashCount, buffLen - len1 - skipSlashCount);
 554              if (str1 && str2) {
 555                  url1 = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str1, PLATFORM_PATH_STYLE, true);
 556                  if (url1) {
 557                      url2 = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, str2, PLATFORM_PATH_STYLE, false, url1);
 558                      if (url2) {
 559                          outURL = CFURLCopyAbsoluteURL(url2);
 560                          CFRelease(url2);
 561                      }
 562                      CFRelease(url1);
 563                  }
 564              }
 565              if (str1) CFRelease(str1);
 566              if (str2) CFRelease(str2);
 567          }
 568          CFRelease(str);
 569      }
 570      if (!outURL) {
 571          outURL = absoluteURL;
 572      } else {
 573          CFRelease(absoluteURL);
 574      }
 575      return outURL;
 576  }
 577  
 578  CFURLRef _CFBundleCopyBundleURLForExecutableURL(CFURLRef url) {
 579      CFURLRef resolvedURL, outurl = NULL;
 580      CFStringRef str;
 581      resolvedURL = _CFBundleCopyResolvedURLForExecutableURL(url);
 582      str = CFURLCopyFileSystemPath(resolvedURL, PLATFORM_PATH_STYLE);
 583      if (str) {
 584          outurl = _CFBundleCopyBundleURLForExecutablePath(str);
 585          CFRelease(str);
 586      }
 587      CFRelease(resolvedURL);
 588      return outurl;
 589  }
 590  
 591  static uint8_t _CFBundleEffectiveLayoutVersion(CFBundleRef bundle) {
 592      uint8_t localVersion = bundle->_version;
 593      // exclude type 0 bundles with no binary (or CFM binary) and no Info.plist, since they give too many false positives
 594      if (0 == localVersion) {
 595          CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
 596          if (!infoDict || 0 == CFDictionaryGetCount(infoDict)) {
 597  #if defined(BINARY_SUPPORT_DYLD)
 598              CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
 599              if (executableURL) {
 600                  if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
 601                  if (bundle->_binaryType == __CFBundleCFMBinary || bundle->_binaryType == __CFBundleUnreadableBinary) {
 602                      localVersion = 4;
 603                  } else {
 604                      bundle->_resourceData._executableLacksResourceFork = true;
 605                  }
 606                  CFRelease(executableURL);
 607              } else {
 608                  localVersion = 4;
 609              }
 610  #else 
 611              CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
 612              if (executableURL) {
 613                  CFRelease(executableURL);
 614              } else {
 615                  localVersion = 4;
 616              }
 617  #endif /* BINARY_SUPPORT_DYLD */
 618          }
 619      }
 620      return localVersion;
 621  }
 622  
 623  CFBundleRef _CFBundleCreateIfLooksLikeBundle(CFAllocatorRef allocator, CFURLRef url) {
 624      CFBundleRef bundle = CFBundleCreate(allocator, url);
 625      if (bundle) {
 626          uint8_t localVersion = _CFBundleEffectiveLayoutVersion(bundle);
 627          if (3 == localVersion || 4 == localVersion) {
 628              CFRelease(bundle);
 629              bundle = NULL;
 630          }
 631      }
 632      return bundle;
 633  }
 634  
 635  CF_EXPORT Boolean _CFBundleURLLooksLikeBundle(CFURLRef url) {
 636      Boolean result = false;
 637      CFBundleRef bundle = _CFBundleCreateIfLooksLikeBundle(kCFAllocatorSystemDefault, url);
 638      if (bundle) {
 639          result = true;
 640          CFRelease(bundle);
 641      }
 642      return result;
 643  }
 644  
 645  CFBundleRef _CFBundleGetMainBundleIfLooksLikeBundle(void) {
 646      CFBundleRef mainBundle = CFBundleGetMainBundle();
 647      if (mainBundle && (3 == mainBundle->_version || 4 == mainBundle->_version)) mainBundle = NULL;
 648      return mainBundle;
 649  }
 650  
 651  Boolean _CFBundleMainBundleInfoDictionaryComesFromResourceFork(void) {
 652      CFBundleRef mainBundle = CFBundleGetMainBundle();
 653      return (mainBundle && mainBundle->_resourceData._infoDictionaryFromResourceFork);
 654  }
 655  
 656  CFBundleRef _CFBundleCreateWithExecutableURLIfLooksLikeBundle(CFAllocatorRef allocator, CFURLRef url) {
 657      CFBundleRef bundle = NULL;
 658      CFURLRef bundleURL = _CFBundleCopyBundleURLForExecutableURL(url), resolvedURL = _CFBundleCopyResolvedURLForExecutableURL(url);
 659      if (bundleURL && resolvedURL) {
 660          // We used to call _CFBundleCreateIfLooksLikeBundle here, but switched to the regular CFBundleCreate because we want this to return a result for certain flat bundles as well.
 661          bundle = CFBundleCreate(allocator, bundleURL);
 662          if (bundle) {
 663              CFURLRef executableURL = _CFBundleCopyExecutableURLIgnoringCache(bundle);
 664              char buff1[CFMaxPathSize], buff2[CFMaxPathSize];
 665              if (!executableURL || !CFURLGetFileSystemRepresentation(resolvedURL, true, (uint8_t *)buff1, CFMaxPathSize) || !CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff2, CFMaxPathSize) || 0 != strcmp(buff1, buff2)) {
 666                  CFRelease(bundle);
 667                  bundle = NULL;
 668              }
 669              if (executableURL) CFRelease(executableURL);
 670          }
 671      }
 672      if (bundleURL) CFRelease(bundleURL);
 673      if (resolvedURL) CFRelease(resolvedURL);
 674      return bundle;
 675  }
 676  
 677  CFBundleRef _CFBundleCreateIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url) {
 678      // This function is obsolete
 679      CFBundleRef bundle = CFBundleCreate(allocator, url);
 680      return bundle;
 681  }
 682  
 683  CFBundleRef _CFBundleCreateWithExecutableURLIfMightBeBundle(CFAllocatorRef allocator, CFURLRef url) {
 684      CFBundleRef result = _CFBundleCreateWithExecutableURLIfLooksLikeBundle(allocator, url);
 685      
 686      // This function applies additional requirements on a bundle to return a result
 687      // The above makes sure that:
 688      //  0. CFBundleCreate must succeed using a URL derived from the executable URL
 689      //  1. The bundle must have an executableURL, and it must match the passed in executable URL
 690      
 691      // This function additionally requires that
 692      //  2. If flat, the bundle must have a non-empty Info.plist. (15663535)
 693      if (result) {
 694          uint8_t localVersion = _CFBundleEffectiveLayoutVersion(result);
 695          if (3 == localVersion || 4 == localVersion) {
 696              CFDictionaryRef infoPlist = CFBundleGetInfoDictionary(result);
 697              if (!infoPlist || (infoPlist && CFDictionaryGetCount(infoPlist) == 0)) {
 698                  CFRelease(result);
 699                  result = NULL;
 700              }
 701          }
 702      }
 703      return result;
 704  }
 705  
 706  CFURLRef _CFBundleCopyMainBundleExecutableURL(Boolean *looksLikeBundle) {
 707      // This function is for internal use only; _mainBundle is deliberately accessed outside of the lock to get around a reentrancy issue
 708      const char *processPath;
 709      CFStringRef str = NULL;
 710      CFURLRef executableURL = NULL;
 711      processPath = _CFProcessPath();
 712      if (processPath) {
 713          str = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, processPath);
 714          if (str) {
 715              executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, PLATFORM_PATH_STYLE, false);
 716              CFRelease(str);
 717          }
 718      }
 719      if (looksLikeBundle) {
 720          CFBundleRef mainBundle = _mainBundle;
 721          if (mainBundle && (3 == mainBundle->_version || 4 == mainBundle->_version)) mainBundle = NULL;
 722          *looksLikeBundle = (mainBundle ? true : false);
 723      }
 724      return executableURL;
 725  }
 726  
 727  static void _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(CFStringRef executablePath) {
 728      CFBundleGetInfoDictionary(_mainBundle);
 729      if (!_mainBundle->_infoDict || CFDictionaryGetCount(_mainBundle->_infoDict) == 0) {
 730          // if type 3 bundle and no Info.plist, treat as unbundled, since this gives too many false positives
 731          if (_mainBundle->_version == 3) _mainBundle->_version = 4;
 732          if (_mainBundle->_version == 0) {
 733              // if type 0 bundle and no Info.plist and not main executable for bundle, treat as unbundled, since this gives too many false positives
 734              CFStringRef executableName = _CFBundleCopyExecutableName(_mainBundle, NULL, NULL);
 735              if (!executableName || !executablePath || !CFStringHasSuffix(executablePath, executableName)) _mainBundle->_version = 4;
 736              if (executableName) CFRelease(executableName);
 737          }
 738  #if defined(BINARY_SUPPORT_DYLD)
 739          if (_mainBundle->_binaryType == __CFBundleDYLDExecutableBinary) {
 740              if (_mainBundle->_infoDict && !(0)) CFRelease(_mainBundle->_infoDict);
 741              _mainBundle->_infoDict = (CFDictionaryRef)_CFBundleCreateInfoDictFromMainExecutable();
 742          }
 743  #endif /* BINARY_SUPPORT_DYLD */
 744      } else {
 745  #if defined(BINARY_SUPPORT_DYLD)
 746          if (_mainBundle->_binaryType == __CFBundleDYLDExecutableBinary) {
 747              // if dyld and not main executable for bundle, prefer info dictionary from executable
 748              CFStringRef executableName = _CFBundleCopyExecutableName(_mainBundle, NULL, NULL);
 749              if (!executableName || !executablePath || !CFStringHasSuffix(executablePath, executableName)) {
 750                  CFDictionaryRef infoDictFromExecutable = (CFDictionaryRef)_CFBundleCreateInfoDictFromMainExecutable();
 751                  if (infoDictFromExecutable && CFDictionaryGetCount(infoDictFromExecutable) > 0) {
 752                      if (_mainBundle->_infoDict) CFRelease(_mainBundle->_infoDict);
 753                      _mainBundle->_infoDict = infoDictFromExecutable;
 754                  } else if (infoDictFromExecutable) {
 755                      CFRelease(infoDictFromExecutable);
 756                  }
 757              }
 758              if (executableName) CFRelease(executableName);
 759          }
 760  #endif /* BINARY_SUPPORT_DYLD */
 761      }
 762      if (!_mainBundle->_infoDict) _mainBundle->_infoDict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 763      if (!_mainBundle->_executablePath && executablePath) _mainBundle->_executablePath = (CFStringRef)CFRetain(executablePath);
 764      CFStringRef bundleID = (CFStringRef)CFDictionaryGetValue(_mainBundle->_infoDict, kCFBundleIdentifierKey);
 765      if (bundleID) {
 766          if (!CFStringGetCString(bundleID, __CFBundleMainID__, sizeof(__CFBundleMainID__) - 2, kCFStringEncodingUTF8)) {
 767              __CFBundleMainID__[0] = '\0';
 768          }
 769      }
 770  }
 771          
 772  static void _CFBundleFlushBundleCachesAlreadyLocked(CFBundleRef bundle, Boolean alreadyLocked) {
 773      CFDictionaryRef oldInfoDict = bundle->_infoDict;
 774      CFTypeRef val;
 775      
 776      bundle->_infoDict = NULL;
 777      if (bundle->_localInfoDict) {
 778          CFRelease(bundle->_localInfoDict);
 779          bundle->_localInfoDict = NULL;
 780      }
 781      if (bundle->_developmentRegion) {
 782          CFRelease(bundle->_developmentRegion);
 783          bundle->_developmentRegion = NULL;
 784      }
 785      if (bundle->_executablePath) {
 786          CFRelease(bundle->_executablePath);
 787          bundle->_executablePath = NULL;
 788      }
 789      if (bundle->_searchLanguages) {
 790          CFRelease(bundle->_searchLanguages);
 791          bundle->_searchLanguages = NULL;
 792      }
 793      if (bundle->_stringTable) {
 794          CFRelease(bundle->_stringTable);
 795          bundle->_stringTable = NULL;
 796      }
 797      if (bundle == _mainBundle) {
 798          CFStringRef executablePath = bundle->_executablePath;
 799          if (!alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
 800          _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(executablePath);
 801          if (!alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
 802      } else {
 803          CFBundleGetInfoDictionary(bundle);
 804      }
 805      if (oldInfoDict) {
 806          if (!bundle->_infoDict) bundle->_infoDict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
 807          val = CFDictionaryGetValue(oldInfoDict, _kCFBundlePrincipalClassKey);
 808          if (val) CFDictionarySetValue((CFMutableDictionaryRef)bundle->_infoDict, _kCFBundlePrincipalClassKey, val);
 809          CFRelease(oldInfoDict);
 810      }
 811      
 812      _CFBundleFlushQueryTableCache(bundle);
 813  }
 814  
 815  CF_EXPORT void _CFBundleFlushBundleCaches(CFBundleRef bundle) {
 816      _CFBundleFlushBundleCachesAlreadyLocked(bundle, false);
 817  }
 818  
 819  static CFBundleRef _CFBundleGetMainBundleAlreadyLocked(void) {
 820      if (!_initedMainBundle) {
 821          const char *processPath;
 822          CFStringRef str = NULL;
 823          CFURLRef executableURL = NULL, bundleURL = NULL;
 824          _initedMainBundle = true;
 825          processPath = _CFProcessPath();
 826          if (processPath) {
 827              str = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, processPath);
 828              if (!executableURL) executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, str, PLATFORM_PATH_STYLE, false);
 829          }
 830          if (executableURL) bundleURL = _CFBundleCopyBundleURLForExecutableURL(executableURL);
 831          if (bundleURL) {
 832              // make sure that main bundle has executable path
 833              //??? what if we are not the main executable in the bundle?
 834              // NB doFinalProcessing must be false here, see below
 835              _mainBundle = _CFBundleCreate(kCFAllocatorSystemDefault, bundleURL, true, false, false);
 836              if (_mainBundle) {
 837                  // make sure that the main bundle is listed as loaded, and mark it as executable
 838                  _mainBundle->_isLoaded = true;
 839  #if defined(BINARY_SUPPORT_DYLD)
 840                  if (_mainBundle->_binaryType == __CFBundleUnknownBinary) {
 841                      if (!executableURL) {
 842                          _mainBundle->_binaryType = __CFBundleNoBinary;
 843                      } else {
 844                          _mainBundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
 845                          if (_mainBundle->_binaryType != __CFBundleCFMBinary && _mainBundle->_binaryType != __CFBundleUnreadableBinary) _mainBundle->_resourceData._executableLacksResourceFork = true;
 846                      }
 847                  }                
 848  #endif /* BINARY_SUPPORT_DYLD */
 849                  // get cookie for already-loaded main bundle
 850  #if defined(BINARY_SUPPORT_DLFCN)
 851                  if (!_mainBundle->_handleCookie) {
 852                      _mainBundle->_handleCookie = dlopen(NULL, RTLD_NOLOAD | RTLD_FIRST);
 853  #if LOG_BUNDLE_LOAD
 854                      printf("main bundle %p getting handle %p\n", _mainBundle, _mainBundle->_handleCookie);
 855  #endif /* LOG_BUNDLE_LOAD */
 856                  }
 857  #elif defined(BINARY_SUPPORT_DYLD)
 858                  if (_mainBundle->_binaryType == __CFBundleDYLDExecutableBinary && !_mainBundle->_imageCookie) {
 859                      _mainBundle->_imageCookie = (void *)_dyld_get_image_header(0);
 860  #if LOG_BUNDLE_LOAD
 861                      printf("main bundle %p getting image %p\n", _mainBundle, _mainBundle->_imageCookie);
 862  #endif /* LOG_BUNDLE_LOAD */
 863                  }
 864  #endif /* BINARY_SUPPORT_DLFCN */
 865                  _CFBundleInitializeMainBundleInfoDictionaryAlreadyLocked(str);
 866                  // Perform delayed final processing steps.
 867                  // This must be done after _isLoaded has been set, for security reasons (3624341).
 868                  if (_CFBundleNeedsInitPlugIn(_mainBundle)) {
 869                      pthread_mutex_unlock(&CFBundleGlobalDataLock);
 870                      _CFBundleInitPlugIn(_mainBundle);
 871                      pthread_mutex_lock(&CFBundleGlobalDataLock);
 872                  }
 873              }
 874          }
 875          if (bundleURL) CFRelease(bundleURL);
 876          if (str) CFRelease(str);
 877          if (executableURL) CFRelease(executableURL);
 878      }
 879      return _mainBundle;
 880  }
 881  
 882  CFBundleRef CFBundleGetMainBundle(void) {
 883      CFBundleRef mainBundle;
 884      pthread_mutex_lock(&CFBundleGlobalDataLock);
 885      mainBundle = _CFBundleGetMainBundleAlreadyLocked();
 886      pthread_mutex_unlock(&CFBundleGlobalDataLock);
 887      return mainBundle;
 888  }
 889  
 890  CFBundleRef CFBundleGetBundleWithIdentifier(CFStringRef bundleID) {
 891      CFBundleRef result = NULL;
 892      if (bundleID) {
 893          pthread_mutex_lock(&CFBundleGlobalDataLock);
 894          (void)_CFBundleGetMainBundleAlreadyLocked();
 895          result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
 896  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
 897          if (!result) {
 898              // Try to create the bundle for the caller and try again
 899              void *p = __builtin_return_address(0);
 900              if (p) {
 901                  CFStringRef imagePath = _CFBundleCopyLoadedImagePathForPointer(p);
 902                  if (imagePath) {
 903                      _CFBundleEnsureBundleExistsForImagePath(imagePath);
 904                      CFRelease(imagePath);
 905                  }
 906                  result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
 907              }
 908          }
 909  #endif
 910          if (!result) {
 911              // Try to guess the bundle from the identifier and try again
 912              _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(bundleID);
 913              result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
 914          }
 915          if (!result) {
 916              // Make sure all bundles have been created and try again.
 917              _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
 918              result = _CFBundlePrimitiveGetBundleWithIdentifierAlreadyLocked(bundleID);
 919          }
 920          pthread_mutex_unlock(&CFBundleGlobalDataLock);
 921      }
 922      return result;
 923  }
 924  
 925  static CFStringRef __CFBundleCopyDescription(CFTypeRef cf) {
 926      char buff[CFMaxPathSize];
 927      CFStringRef path = NULL, binaryType = NULL, retval = NULL;
 928      if (((CFBundleRef)cf)->_url && CFURLGetFileSystemRepresentation(((CFBundleRef)cf)->_url, true, (uint8_t *)buff, CFMaxPathSize)) path = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, buff);
 929      switch (((CFBundleRef)cf)->_binaryType) {
 930          case __CFBundleCFMBinary:
 931              binaryType = CFSTR("");
 932              break;
 933          case __CFBundleDYLDExecutableBinary:
 934              binaryType = CFSTR("executable, ");
 935              break;
 936          case __CFBundleDYLDBundleBinary:
 937              binaryType = CFSTR("bundle, ");
 938              break;
 939          case __CFBundleDYLDFrameworkBinary:
 940              binaryType = CFSTR("framework, ");
 941              break;
 942          case __CFBundleDLLBinary:
 943              binaryType = CFSTR("DLL, ");
 944              break;
 945          case __CFBundleUnreadableBinary:
 946              binaryType = CFSTR("");
 947              break;
 948          default:
 949              binaryType = CFSTR("");
 950              break;
 951      }
 952      if (((CFBundleRef)cf)->_plugInData._isPlugIn) {
 953          retval = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFBundle/CFPlugIn %p <%@> (%@%@loaded)"), cf, path, binaryType, ((CFBundleRef)cf)->_isLoaded ? CFSTR("") : CFSTR("not "));
 954      } else {
 955          retval = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("CFBundle %p <%@> (%@%@loaded)"), cf, path, binaryType, ((CFBundleRef)cf)->_isLoaded ? CFSTR("") : CFSTR("not "));
 956      }
 957      if (path) CFRelease(path);
 958      return retval;
 959  }
 960  
 961  static void _CFBundleDeallocateGlue(const void *key, const void *value, void *context) {
 962      CFAllocatorRef allocator = (CFAllocatorRef)context;
 963      if (value) CFAllocatorDeallocate(allocator, (void *)value);
 964  }
 965  
 966  static void __CFBundleDeallocate(CFTypeRef cf) {
 967      CFBundleRef bundle = (CFBundleRef)cf;
 968      CFURLRef bundleURL;
 969      CFStringRef bundleID = NULL;
 970      
 971      __CFGenericValidateType(cf, CFBundleGetTypeID());
 972      bundleURL = bundle->_url;
 973      bundle->_url = NULL;
 974      if (bundle->_infoDict) bundleID = (CFStringRef)CFDictionaryGetValue(bundle->_infoDict, kCFBundleIdentifierKey);
 975      _CFBundleRemoveFromTables(bundle, bundleURL, bundleID);
 976      CFBundleUnloadExecutable(bundle);
 977      _CFBundleDeallocatePlugIn(bundle);    
 978      if (bundleURL) {
 979          CFRelease(bundleURL);
 980      }
 981      if (bundle->_infoDict && !(0)) CFRelease(bundle->_infoDict);
 982      if (bundle->_modDate) CFRelease(bundle->_modDate);
 983      if (bundle->_localInfoDict && !(0)) CFRelease(bundle->_localInfoDict);
 984      if (bundle->_searchLanguages) CFRelease(bundle->_searchLanguages);
 985      if (bundle->_executablePath) CFRelease(bundle->_executablePath);
 986      if (bundle->_developmentRegion) CFRelease(bundle->_developmentRegion);
 987      if (bundle->_glueDict) {
 988          CFDictionaryApplyFunction(bundle->_glueDict, _CFBundleDeallocateGlue, (void *)CFGetAllocator(bundle));
 989          CFRelease(bundle->_glueDict);
 990      }
 991      if (bundle->_stringTable) CFRelease(bundle->_stringTable);
 992      
 993      if (bundle->_bundleBasePath) CFRelease(bundle->_bundleBasePath);
 994      if (bundle->_queryTable) CFRelease(bundle->_queryTable);
 995      
 996      if (bundle->_localizations) CFRelease(bundle->_localizations);
 997      if (bundle->_resourceDirectoryContents) CFRelease(bundle->_resourceDirectoryContents);
 998      
 999      pthread_mutex_destroy(&(bundle->_bundleLoadingLock));
1000  }
1001  
1002  static const CFRuntimeClass __CFBundleClass = {
1003      _kCFRuntimeScannedObject,
1004      "CFBundle",
1005      NULL,      // init
1006      NULL,      // copy
1007      __CFBundleDeallocate,
1008      NULL,      // equal
1009      NULL,      // hash
1010      NULL,      // 
1011      __CFBundleCopyDescription
1012  };
1013  
1014  // From CFBundle_Resources.c
1015  CF_PRIVATE void _CFBundleResourcesInitialize();
1016  
1017  CFTypeID CFBundleGetTypeID(void) {
1018      static dispatch_once_t initOnce;
1019      dispatch_once(&initOnce, ^{ __kCFBundleTypeID = _CFRuntimeRegisterClass(&__CFBundleClass); _CFBundleResourcesInitialize(); });
1020      return __kCFBundleTypeID;
1021  }
1022  
1023  CFBundleRef _CFBundleGetExistingBundleWithBundleURL(CFURLRef bundleURL) {
1024      CFBundleRef bundle = NULL;
1025      char buff[CFMaxPathSize];
1026      CFURLRef newURL = NULL;
1027      
1028      if (!CFURLGetFileSystemRepresentation(bundleURL, true, (uint8_t *)buff, CFMaxPathSize)) return NULL;
1029      
1030      newURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorSystemDefault, (uint8_t *)buff, strlen(buff), true);
1031      if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL);
1032      bundle = _CFBundleCopyBundleForURL(newURL, false);
1033      if (bundle) CFRelease(bundle);
1034      CFRelease(newURL);
1035      return bundle;
1036  }
1037  
1038  static CFBundleRef _CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL, Boolean alreadyLocked, Boolean doFinalProcessing, Boolean noCaches) {
1039      CFBundleRef bundle = NULL;
1040      char buff[CFMaxPathSize];
1041      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
1042      Boolean exists = false;
1043      SInt32 mode = 0;
1044      CFURLRef newURL = NULL;
1045      uint8_t localVersion = 0;
1046      
1047      if (!CFURLGetFileSystemRepresentation(bundleURL, true, (uint8_t *)buff, CFMaxPathSize)) return NULL;
1048  
1049      newURL = CFURLCreateFromFileSystemRepresentation(allocator, (uint8_t *)buff, strlen(buff), true);
1050      if (!newURL) newURL = (CFURLRef)CFRetain(bundleURL);
1051  
1052      if (!noCaches) {
1053          bundle = _CFBundleCopyBundleForURL(newURL, alreadyLocked);
1054          if (bundle) {
1055              CFRelease(newURL);
1056              return bundle;
1057          }
1058      }
1059      
1060      localVersion = _CFBundleGetBundleVersionForURL(newURL);
1061      if (localVersion == 3) {
1062          SInt32 res = _CFGetPathProperties(allocator, (char *)buff, &exists, &mode, NULL, NULL, NULL, NULL);
1063  #if DEPLOYMENT_TARGET_WINDOWS
1064          if (!(res == 0 && exists && ((mode & S_IFMT) == S_IFDIR))) {
1065              // 2nd chance at finding a bundle path - remove the last path component (e.g., mybundle.resources) and try again
1066              if (modDate) {
1067                  CFRelease(modDate);
1068                  modDate = NULL;
1069              }
1070              CFURLRef shorterPath = CFURLCreateCopyDeletingLastPathComponent(allocator, newURL);
1071              CFRelease(newURL);
1072              newURL = shorterPath;
1073              res = _CFGetFileProperties(allocator, newURL, &exists, &mode, NULL, NULL, NULL, NULL);
1074          }
1075  #endif
1076          if (res == 0) {
1077              if (!exists || ((mode & S_IFMT) != S_IFDIR)) {
1078                  if (modDate) CFRelease(modDate);
1079                  CFRelease(newURL);
1080                  return NULL;
1081              }
1082          } else {
1083              CFRelease(newURL);
1084              return NULL;
1085          }
1086      }
1087  
1088      bundle = (CFBundleRef)_CFRuntimeCreateInstance(allocator, CFBundleGetTypeID(), sizeof(struct __CFBundle) - sizeof(CFRuntimeBase), NULL);
1089      if (!bundle) {
1090          CFRelease(newURL);
1091          return NULL;
1092      }
1093  
1094      bundle->_url = newURL;
1095  
1096      bundle->_modDate = modDate;
1097      bundle->_version = localVersion;
1098      bundle->_infoDict = NULL;
1099      bundle->_localInfoDict = NULL;
1100      bundle->_searchLanguages = NULL;
1101      bundle->_executablePath = NULL;
1102      bundle->_developmentRegion = NULL;
1103      bundle->_developmentRegionCalculated = 0;
1104  #if defined(BINARY_SUPPORT_DYLD)
1105      /* We'll have to figure it out later */
1106      bundle->_binaryType = __CFBundleUnknownBinary;
1107  #elif defined(BINARY_SUPPORT_DLL)
1108      /* We support DLL only */
1109      bundle->_binaryType = __CFBundleDLLBinary;
1110      bundle->_hModule = NULL;
1111  #else
1112      /* We'll have to figure it out later */
1113      bundle->_binaryType = __CFBundleUnknownBinary;
1114  #endif /* BINARY_SUPPORT_DYLD */
1115  
1116      bundle->_isLoaded = false;
1117      bundle->_sharesStringsFiles = false;
1118      
1119  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1120      if (!__CFgetenv("CFBundleDisableStringsSharing") && 
1121          (strncmp(buff, "/System/Library/Frameworks", 26) == 0) && 
1122          (strncmp(buff + strlen(buff) - 10, ".framework", 10) == 0)) bundle->_sharesStringsFiles = true;
1123  #endif
1124  
1125      bundle->_connectionCookie = NULL;
1126      bundle->_handleCookie = NULL;
1127      bundle->_imageCookie = NULL;
1128      bundle->_moduleCookie = NULL;
1129  
1130      bundle->_glueDict = NULL;
1131      
1132      bundle->_resourceData._executableLacksResourceFork = false;
1133      bundle->_resourceData._infoDictionaryFromResourceFork = false;
1134  
1135      bundle->_stringTable = NULL;
1136  
1137      bundle->_plugInData._isPlugIn = false;
1138      bundle->_plugInData._loadOnDemand = false;
1139      bundle->_plugInData._isDoingDynamicRegistration = false;
1140      bundle->_plugInData._instanceCount = 0;
1141      bundle->_plugInData._factories = NULL;
1142  
1143      pthread_mutexattr_t mattr;
1144      pthread_mutexattr_init(&mattr);
1145      pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_DEFAULT);
1146      int32_t mret = pthread_mutex_init(&(bundle->_bundleLoadingLock), &mattr);
1147      pthread_mutexattr_destroy(&mattr);
1148      if (0 != mret) {
1149          CFLog(4, CFSTR("%s: failed to initialize bundle loading lock for bundle %@."), __PRETTY_FUNCTION__, bundle);
1150      }
1151      
1152      bundle->_lock = CFLockInit;
1153      bundle->_resourceDirectoryContents = NULL;
1154      
1155      bundle->_localizations = NULL;
1156      bundle->_lookedForLocalizations = false;
1157      
1158      bundle->_queryLock = CFLockInit;
1159      bundle->_queryTable = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1160      CFURLRef absoURL = CFURLCopyAbsoluteURL(bundle->_url);
1161      bundle->_bundleBasePath = CFURLCopyFileSystemPath(absoURL, PLATFORM_PATH_STYLE);
1162      CFRelease(absoURL);
1163      
1164      CFBundleGetInfoDictionary(bundle);
1165      
1166      // Do this so that we can use the dispatch_once on the ivar of this bundle safely
1167      OSMemoryBarrier();
1168      
1169      if (!noCaches)
1170          _CFBundleAddToTables(bundle, alreadyLocked);
1171  
1172      if (doFinalProcessing) {
1173          if (_CFBundleNeedsInitPlugIn(bundle)) {
1174              if (alreadyLocked) pthread_mutex_unlock(&CFBundleGlobalDataLock);
1175              _CFBundleInitPlugIn(bundle);
1176              if (alreadyLocked) pthread_mutex_lock(&CFBundleGlobalDataLock);
1177          }
1178      }
1179      
1180      return bundle;
1181  }
1182  
1183  CFBundleRef CFBundleCreate(CFAllocatorRef allocator, CFURLRef bundleURL) {
1184      return _CFBundleCreate(allocator, bundleURL, false, true, false);
1185  }
1186  
1187  CFArrayRef CFBundleCreateBundlesFromDirectory(CFAllocatorRef alloc, CFURLRef directoryURL, CFStringRef bundleType) {
1188      CFMutableArrayRef bundles = CFArrayCreateMutable(alloc, 0, &kCFTypeArrayCallBacks);
1189      CFArrayRef URLs = _CFCreateContentsOfDirectory(alloc, NULL, NULL, directoryURL, bundleType);
1190      if (URLs) {
1191          CFIndex i, c = CFArrayGetCount(URLs);
1192          CFURLRef curURL;
1193          CFBundleRef curBundle;
1194  
1195          for (i = 0; i < c; i++) {
1196              curURL = (CFURLRef)CFArrayGetValueAtIndex(URLs, i);
1197              curBundle = CFBundleCreate(alloc, curURL);
1198              if (curBundle) CFArrayAppendValue(bundles, curBundle);
1199          }
1200          CFRelease(URLs);
1201      }
1202  
1203      return bundles;
1204  }
1205  
1206  CFURLRef CFBundleCopyBundleURL(CFBundleRef bundle) {
1207      if (bundle->_url) CFRetain(bundle->_url);
1208      return bundle->_url;
1209  }
1210  
1211  #define DEVELOPMENT_STAGE 0x20
1212  #define ALPHA_STAGE 0x40
1213  #define BETA_STAGE 0x60
1214  #define RELEASE_STAGE 0x80
1215  
1216  #define MAX_VERS_LEN 10
1217  
1218  CF_INLINE Boolean _isDigit(UniChar aChar) {return ((aChar >= (UniChar)'0' && aChar <= (UniChar)'9') ? true : false);}
1219  
1220  CF_PRIVATE CFStringRef _CFCreateStringFromVersionNumber(CFAllocatorRef alloc, UInt32 vers) {
1221      CFStringRef result = NULL;
1222      uint8_t major1, major2, minor1, minor2, stage, build;
1223  
1224      major1 = (vers & 0xF0000000) >> 28;
1225      major2 = (vers & 0x0F000000) >> 24;
1226      minor1 = (vers & 0x00F00000) >> 20;
1227      minor2 = (vers & 0x000F0000) >> 16;
1228      stage = (vers & 0x0000FF00) >> 8;
1229      build = (vers & 0x000000FF);
1230  
1231      if (stage == RELEASE_STAGE) {
1232          if (major1 > 0) {
1233              result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d%d.%d.%d"), major1, major2, minor1, minor2);
1234          } else {
1235              result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d.%d.%d"), major2, minor1, minor2);
1236          }
1237      } else {
1238          if (major1 > 0) {
1239              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);
1240          } else {
1241              result = CFStringCreateWithFormat(alloc, NULL, CFSTR("%d.%d.%d%c%d"), major2, minor1, minor2, ((stage == DEVELOPMENT_STAGE) ? 'd' : ((stage == ALPHA_STAGE) ? 'a' : 'b')), build);
1242          }
1243      }
1244      return result;
1245  }
1246  
1247  CF_PRIVATE UInt32 _CFVersionNumberFromString(CFStringRef versStr) {
1248      // Parse version number from string.
1249      // String can begin with "." for major version number 0.  String can end at any point, but elements within the string cannot be skipped.
1250      UInt32 major1 = 0, major2 = 0, minor1 = 0, minor2 = 0, stage = RELEASE_STAGE, build = 0;
1251      UniChar versChars[MAX_VERS_LEN];
1252      UniChar *chars = NULL;
1253      CFIndex len;
1254      UInt32 theVers;
1255      Boolean digitsDone = false;
1256  
1257      if (!versStr) return 0;
1258      len = CFStringGetLength(versStr);
1259      if (len <= 0 || len > MAX_VERS_LEN) return 0;
1260  
1261      CFStringGetCharacters(versStr, CFRangeMake(0, len), versChars);
1262      chars = versChars;
1263      
1264      // Get major version number.
1265      major1 = major2 = 0;
1266      if (_isDigit(*chars)) {
1267          major2 = *chars - (UniChar)'0';
1268          chars++;
1269          len--;
1270          if (len > 0) {
1271              if (_isDigit(*chars)) {
1272                  major1 = major2;
1273                  major2 = *chars - (UniChar)'0';
1274                  chars++;
1275                  len--;
1276                  if (len > 0) {
1277                      if (*chars == (UniChar)'.') {
1278                          chars++;
1279                          len--;
1280                      } else {
1281                          digitsDone = true;
1282                      }
1283                  }
1284              } else if (*chars == (UniChar)'.') {
1285                  chars++;
1286                  len--;
1287              } else {
1288                  digitsDone = true;
1289              }
1290          }
1291      } else if (*chars == (UniChar)'.') {
1292          chars++;
1293          len--;
1294      } else {
1295          digitsDone = true;
1296      }
1297  
1298      // Now major1 and major2 contain first and second digit of the major version number as ints.
1299      // Now either len is 0 or chars points at the first char beyond the first decimal point.
1300  
1301      // Get the first minor version number.  
1302      if (len > 0 && !digitsDone) {
1303          if (_isDigit(*chars)) {
1304              minor1 = *chars - (UniChar)'0';
1305              chars++;
1306              len--;
1307              if (len > 0) {
1308                  if (*chars == (UniChar)'.') {
1309                      chars++;
1310                      len--;
1311                  } else {
1312                      digitsDone = true;
1313                  }
1314              }
1315          } else {
1316              digitsDone = true;
1317          }
1318      }
1319  
1320      // Now minor1 contains the first minor version number as an int.
1321      // Now either len is 0 or chars points at the first char beyond the second decimal point.
1322  
1323      // Get the second minor version number. 
1324      if (len > 0 && !digitsDone) {
1325          if (_isDigit(*chars)) {
1326              minor2 = *chars - (UniChar)'0';
1327              chars++;
1328              len--;
1329          } else {
1330              digitsDone = true;
1331          }
1332      }
1333  
1334      // Now minor2 contains the second minor version number as an int.
1335      // Now either len is 0 or chars points at the build stage letter.
1336  
1337      // Get the build stage letter.  We must find 'd', 'a', 'b', or 'f' next, if there is anything next.
1338      if (len > 0) {
1339          if (*chars == (UniChar)'d') {
1340              stage = DEVELOPMENT_STAGE;
1341          } else if (*chars == (UniChar)'a') {
1342              stage = ALPHA_STAGE;
1343          } else if (*chars == (UniChar)'b') {
1344              stage = BETA_STAGE;
1345          } else if (*chars == (UniChar)'f') {
1346              stage = RELEASE_STAGE;
1347          } else {
1348              return 0;
1349          }
1350          chars++;
1351          len--;
1352      }
1353  
1354      // Now stage contains the release stage.
1355      // Now either len is 0 or chars points at the build number.
1356  
1357      // Get the first digit of the build number.
1358      if (len > 0) {
1359          if (_isDigit(*chars)) {
1360              build = *chars - (UniChar)'0';
1361              chars++;
1362              len--;
1363          } else {
1364              return 0;
1365          }
1366      }
1367      // Get the second digit of the build number.
1368      if (len > 0) {
1369          if (_isDigit(*chars)) {
1370              build *= 10;
1371              build += *chars - (UniChar)'0';
1372              chars++;
1373              len--;
1374          } else {
1375              return 0;
1376          }
1377      }
1378      // Get the third digit of the build number.
1379      if (len > 0) {
1380          if (_isDigit(*chars)) {
1381              build *= 10;
1382              build += *chars - (UniChar)'0';
1383              chars++;
1384              len--;
1385          } else {
1386              return 0;
1387          }
1388      }
1389  
1390      // Range check the build number and make sure we exhausted the string.
1391      if (build > 0xFF || len > 0) return 0;
1392  
1393      // Build the number
1394      theVers = major1 << 28;
1395      theVers += major2 << 24;
1396      theVers += minor1 << 20;
1397      theVers += minor2 << 16;
1398      theVers += stage << 8;
1399      theVers += build;
1400  
1401      return theVers;
1402  }
1403  
1404  UInt32 CFBundleGetVersionNumber(CFBundleRef bundle) {
1405      CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
1406      CFNumberRef versionValue = (CFNumberRef)CFDictionaryGetValue(infoDict, _kCFBundleNumericVersionKey);
1407      if (!versionValue || CFGetTypeID(versionValue) != CFNumberGetTypeID()) return 0;
1408      
1409      UInt32 vers = 0;
1410      CFNumberGetValue(versionValue, kCFNumberSInt32Type, &vers);
1411      return vers;
1412  }
1413  
1414  CFStringRef CFBundleGetDevelopmentRegion(CFBundleRef bundle) {
1415      dispatch_once(&bundle->_developmentRegionCalculated, ^{
1416          CFStringRef devRegion = NULL;
1417          CFDictionaryRef infoDict = CFBundleGetInfoDictionary(bundle);
1418          if (infoDict) {
1419              devRegion = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleDevelopmentRegionKey);
1420              if (devRegion && (CFGetTypeID(devRegion) != CFStringGetTypeID() || CFStringGetLength(devRegion) == 0)) {
1421                  devRegion = NULL;
1422              }
1423          }
1424          
1425          if (devRegion) bundle->_developmentRegion = (CFStringRef)CFRetain(devRegion);
1426      });
1427      return bundle->_developmentRegion;
1428  }
1429  
1430  Boolean _CFBundleGetHasChanged(CFBundleRef bundle) {
1431      CFDateRef modDate;
1432      Boolean result = false;
1433      Boolean exists = false;
1434      SInt32 mode = 0;
1435  
1436      if (_CFGetFileProperties(CFGetAllocator(bundle), bundle->_url, &exists, &mode, NULL, &modDate, NULL, NULL) == 0) {
1437          // If the bundle no longer exists or is not a folder, it must have "changed"
1438          if (!exists || ((mode & S_IFMT) != S_IFDIR)) result = true;
1439      } else {
1440          // Something is wrong.  The stat failed.
1441          result = true;
1442      }
1443      if (bundle->_modDate && !CFEqual(bundle->_modDate, modDate)) {
1444          // mod date is different from when we created.
1445          result = true;
1446      }
1447      CFRelease(modDate);
1448      return result;
1449  }
1450  
1451  void _CFBundleSetStringsFilesShared(CFBundleRef bundle, Boolean flag) {
1452      bundle->_sharesStringsFiles = flag;
1453  }
1454  
1455  Boolean _CFBundleGetStringsFilesShared(CFBundleRef bundle) {
1456      return bundle->_sharesStringsFiles;
1457  }
1458  
1459  static Boolean _urlExists(CFURLRef url) {
1460      Boolean exists;
1461      return url && (0 == _CFGetFileProperties(kCFAllocatorSystemDefault, url, &exists, NULL, NULL, NULL, NULL, NULL)) && exists;
1462  }
1463  
1464  // This is here because on iPhoneOS with the dyld shared cache, we remove binaries from their
1465  // original locations on disk, so checking whether a binary's path exists is no longer sufficient.
1466  // For performance reasons, we only call dlopen_preflight() after we've verified that the binary 
1467  // does not exist at its original path with _urlExists().
1468  // See <rdar://problem/6956670>
1469  static Boolean _binaryLoadable(CFURLRef url) {
1470      Boolean loadable = _urlExists(url);
1471  #if DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1472      if (!loadable) {
1473  	uint8_t path[PATH_MAX];
1474  	if (url && CFURLGetFileSystemRepresentation(url, true, path, sizeof(path))) {
1475  	    loadable = dlopen_preflight((char *)path);
1476  	}
1477      }
1478  #endif
1479      return loadable;
1480  }
1481  
1482  CF_PRIVATE CFURLRef _CFBundleCopySupportFilesDirectoryURLInDirectory(CFURLRef bundleURL, uint8_t version) {
1483      CFURLRef result = NULL;
1484      if (bundleURL) {
1485          if (1 == version) {
1486              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase1, bundleURL);
1487          } else if (2 == version) {
1488              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleSupportFilesURLFromBase2, bundleURL);
1489          } else {
1490              result = (CFURLRef)CFRetain(bundleURL);
1491          }
1492      }
1493      return result;
1494  }
1495  
1496  CF_EXPORT CFURLRef CFBundleCopySupportFilesDirectoryURL(CFBundleRef bundle) {
1497      return _CFBundleCopySupportFilesDirectoryURLInDirectory(bundle->_url, bundle->_version);
1498  }
1499  
1500  CF_PRIVATE CFURLRef _CFBundleCopyResourcesDirectoryURLInDirectory(CFURLRef bundleURL, uint8_t version) {
1501      CFURLRef result = NULL;
1502      if (bundleURL) {
1503          if (0 == version) {
1504              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleResourcesURLFromBase0, bundleURL);
1505          } else if (1 == version) {
1506              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleResourcesURLFromBase1, bundleURL);
1507          } else if (2 == version) {
1508              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleResourcesURLFromBase2, bundleURL);
1509          } else {
1510              result = (CFURLRef)CFRetain(bundleURL);
1511          }
1512      }
1513      return result;
1514  }
1515  
1516  CF_EXPORT CFURLRef CFBundleCopyResourcesDirectoryURL(CFBundleRef bundle) {
1517      return _CFBundleCopyResourcesDirectoryURLInDirectory(bundle->_url, bundle->_version);
1518  }
1519  
1520  CF_PRIVATE CFURLRef _CFBundleCopyAppStoreReceiptURLInDirectory(CFURLRef bundleURL, uint8_t version) {
1521      CFURLRef result = NULL;
1522      if (bundleURL) {
1523          if (0 == version) {
1524              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleAppStoreReceiptURLFromBase0, bundleURL);
1525          } else if (1 == version) {
1526              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleAppStoreReceiptURLFromBase1, bundleURL);
1527          } else if (2 == version) {
1528              result = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleAppStoreReceiptURLFromBase2, bundleURL);
1529          }
1530      }
1531      return result;
1532  }
1533  
1534  CFURLRef _CFBundleCopyAppStoreReceiptURL(CFBundleRef bundle) {
1535      return _CFBundleCopyAppStoreReceiptURLInDirectory(bundle->_url, bundle->_version);
1536  }
1537          
1538  static CFURLRef _CFBundleCopyExecutableURLRaw(CFURLRef urlPath, CFStringRef exeName) {
1539      // 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.
1540      CFURLRef executableURL = NULL;
1541      if (!urlPath || !exeName) return NULL;
1542      
1543  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1544      const uint8_t *image_suffix = (uint8_t *)__CFgetenv("DYLD_IMAGE_SUFFIX");
1545      if (image_suffix) {
1546          CFStringRef newExeName, imageSuffix;
1547          imageSuffix = CFStringCreateWithCString(kCFAllocatorSystemDefault, (char *)image_suffix, kCFStringEncodingUTF8);
1548          if (CFStringHasSuffix(exeName, CFSTR(".dylib"))) {
1549              CFStringRef bareExeName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, exeName, CFRangeMake(0, CFStringGetLength(exeName)-6));
1550              newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@.dylib"), exeName, imageSuffix);
1551              CFRelease(bareExeName);
1552          } else {
1553              newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@"), exeName, imageSuffix);
1554          }
1555          executableURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, newExeName, kCFURLPOSIXPathStyle, false, urlPath);
1556          if (executableURL && !_binaryLoadable(executableURL)) {
1557              CFRelease(executableURL);
1558              executableURL = NULL;
1559          }
1560          CFRelease(newExeName);
1561          CFRelease(imageSuffix);
1562      }
1563      if (!executableURL) {
1564          executableURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, exeName, kCFURLPOSIXPathStyle, false, urlPath);
1565          if (executableURL && !_binaryLoadable(executableURL)) {
1566              CFRelease(executableURL);
1567              executableURL = NULL;
1568          }
1569      }
1570  #elif DEPLOYMENT_TARGET_WINDOWS
1571      if (!executableURL) {
1572          executableURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, exeName, kCFURLWindowsPathStyle, false, urlPath);
1573          if (executableURL && !_urlExists(executableURL)) {
1574              CFRelease(executableURL);
1575              executableURL = NULL;
1576          }
1577      }
1578      if (!executableURL) {
1579          if (!CFStringFindWithOptions(exeName, CFSTR(".dll"), CFRangeMake(0, CFStringGetLength(exeName)), kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL)) {
1580  #if defined(DEBUG)
1581              CFStringRef extension = CFSTR("_debug.dll");
1582  #else
1583              CFStringRef extension = CFSTR(".dll");
1584  #endif
1585              CFStringRef newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@"), exeName, extension);
1586              executableURL = CFURLCreateWithString(kCFAllocatorSystemDefault, newExeName, urlPath);
1587              if (executableURL && !_binaryLoadable(executableURL)) {
1588                  CFRelease(executableURL);
1589                  executableURL = NULL;
1590              }
1591              CFRelease(newExeName);
1592          }
1593      }
1594      if (!executableURL) {
1595          if (!CFStringFindWithOptions(exeName, CFSTR(".exe"), CFRangeMake(0, CFStringGetLength(exeName)), kCFCompareAnchored|kCFCompareBackwards|kCFCompareCaseInsensitive, NULL)) {
1596  #if defined(DEBUG)
1597              CFStringRef extension = CFSTR("_debug.exe");
1598  #else
1599              CFStringRef extension = CFSTR(".exe");
1600  #endif
1601              CFStringRef newExeName = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("%@%@"), exeName, extension);
1602              executableURL = CFURLCreateWithString(kCFAllocatorSystemDefault, newExeName, urlPath);
1603              if (executableURL && !_binaryLoadable(executableURL)) {
1604                  CFRelease(executableURL);
1605                  executableURL = NULL;
1606              }
1607              CFRelease(newExeName);
1608          }
1609      }
1610  #endif
1611      return executableURL;
1612  }
1613  
1614  CF_PRIVATE CFStringRef _CFBundleCopyExecutableName(CFBundleRef bundle, CFURLRef url, CFDictionaryRef infoDict) {
1615      CFStringRef executableName = NULL;
1616      
1617      if (!infoDict && bundle) infoDict = CFBundleGetInfoDictionary(bundle);
1618      if (!url && bundle) url = bundle->_url;
1619      
1620      if (infoDict) {
1621          // Figure out the name of the executable.
1622          // First try for the new key in the plist.
1623          executableName = (CFStringRef)CFDictionaryGetValue(infoDict, kCFBundleExecutableKey);
1624          // Second try for the old key in the plist.
1625          if (!executableName) executableName = (CFStringRef)CFDictionaryGetValue(infoDict, _kCFBundleOldExecutableKey);
1626          if (executableName && CFGetTypeID(executableName) == CFStringGetTypeID() && CFStringGetLength(executableName) > 0) {
1627              CFRetain(executableName);
1628          } else {
1629              executableName = NULL;
1630          }
1631      }
1632      if (!executableName && url) {
1633          // Third, take the name of the bundle itself (with path extension stripped)
1634          CFURLRef absoluteURL = CFURLCopyAbsoluteURL(url);
1635          CFStringRef bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE);
1636          CFRelease(absoluteURL);
1637          if (bundlePath) {
1638              CFIndex len = CFStringGetLength(bundlePath);
1639              CFIndex startOfBundleName = _CFStartOfLastPathComponent2(bundlePath);
1640              CFIndex endOfBundleName = _CFLengthAfterDeletingPathExtension2(bundlePath);
1641              
1642              if (startOfBundleName <= len && endOfBundleName <= len && startOfBundleName < endOfBundleName) {
1643                  executableName = CFStringCreateWithSubstring(kCFAllocatorSystemDefault, bundlePath, CFRangeMake(startOfBundleName, endOfBundleName - startOfBundleName));
1644              }
1645              CFRelease(bundlePath);
1646          }
1647      }
1648      
1649      return executableName;
1650  }
1651  
1652  static CFURLRef _CFBundleCopyExecutableURLInDirectory2(CFBundleRef bundle, CFURLRef url, CFStringRef executableName, Boolean ignoreCache, Boolean useOtherPlatform) {
1653      uint8_t version = 0;
1654      CFDictionaryRef infoDict = NULL;
1655      CFStringRef executablePath = NULL;
1656      CFURLRef executableURL = NULL;
1657      Boolean foundIt = false;
1658      Boolean lookupMainExe = (executableName ? false : true);
1659      
1660      if (bundle) {
1661          infoDict = CFBundleGetInfoDictionary(bundle);
1662          version = bundle->_version;
1663      } else {
1664          infoDict = _CFBundleCopyInfoDictionaryInDirectory(kCFAllocatorSystemDefault, url, &version);
1665      }
1666      
1667      // If we have a bundle instance and an info dict, see if we have already cached the path
1668      if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && bundle->_executablePath) {
1669          __CFLock(&bundle->_lock);
1670          executablePath = bundle->_executablePath;
1671          if (executablePath) CFRetain(executablePath);
1672          __CFUnlock(&bundle->_lock);
1673          if (executablePath) {
1674  #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1675              executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, executablePath, kCFURLPOSIXPathStyle, false);
1676  #elif DEPLOYMENT_TARGET_WINDOWS
1677              executableURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, executablePath, kCFURLWindowsPathStyle, false);
1678  #endif
1679              if (executableURL) {
1680                  foundIt = true;
1681              }
1682              CFRelease(executablePath);
1683          }
1684      }
1685      
1686      if (!foundIt) {
1687          if (lookupMainExe) executableName = _CFBundleCopyExecutableName(bundle, url, infoDict);
1688          if (executableName) {
1689  #if (DEPLOYMENT_TARGET_EMBEDDED && !TARGET_IPHONE_SIMULATOR)
1690              Boolean doExecSearch = false;
1691  #else
1692              Boolean doExecSearch = true;
1693  #endif
1694              // Now, look for the executable inside the bundle.
1695              if (doExecSearch && 0 != version) {
1696                  CFURLRef exeDirURL = NULL;
1697                  CFURLRef exeSubdirURL;
1698                  
1699                  if (1 == version) {
1700                      exeDirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleExecutablesURLFromBase1, url);
1701                  } else if (2 == version) {
1702                      exeDirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, _CFBundleExecutablesURLFromBase2, url);
1703                  } else {
1704  #if DEPLOYMENT_TARGET_WINDOWS
1705                      // On Windows, if the bundle URL is foo.resources, then the executable is at the same level as the .resources directory
1706                      CFStringRef extension = CFURLCopyPathExtension(url);
1707                      if (extension && CFEqual(extension, _CFBundleWindowsResourceDirectoryExtension)) {
1708                          exeDirURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault, url);
1709                      } else {
1710                          exeDirURL = (CFURLRef)CFRetain(url);
1711                      }
1712  #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1713                      exeDirURL = (CFURLRef)CFRetain(url);
1714  #endif
1715                  }
1716                  CFStringRef platformSubDir = useOtherPlatform ? _CFBundleGetOtherPlatformExecutablesSubdirectoryName() : _CFBundleGetPlatformExecutablesSubdirectoryName();
1717                  exeSubdirURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, platformSubDir, kCFURLPOSIXPathStyle, true, exeDirURL);
1718                  executableURL = _CFBundleCopyExecutableURLRaw(exeSubdirURL, executableName);
1719                  if (!executableURL) {
1720                      CFRelease(exeSubdirURL);
1721                      platformSubDir = useOtherPlatform ? _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetAlternatePlatformExecutablesSubdirectoryName();
1722                      exeSubdirURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, platformSubDir, kCFURLPOSIXPathStyle, true, exeDirURL);
1723                      executableURL = _CFBundleCopyExecutableURLRaw(exeSubdirURL, executableName);
1724                  }
1725                  if (!executableURL) {
1726                      CFRelease(exeSubdirURL);
1727                      platformSubDir = useOtherPlatform ? _CFBundleGetPlatformExecutablesSubdirectoryName() : _CFBundleGetOtherPlatformExecutablesSubdirectoryName();
1728                      exeSubdirURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, platformSubDir, kCFURLPOSIXPathStyle, true, exeDirURL);
1729                      executableURL = _CFBundleCopyExecutableURLRaw(exeSubdirURL, executableName);
1730                  }
1731                  if (!executableURL) {
1732                      CFRelease(exeSubdirURL);
1733                      platformSubDir = useOtherPlatform ? _CFBundleGetAlternatePlatformExecutablesSubdirectoryName() : _CFBundleGetOtherAlternatePlatformExecutablesSubdirectoryName();
1734                      exeSubdirURL = CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorSystemDefault, platformSubDir, kCFURLPOSIXPathStyle, true, exeDirURL);
1735                      executableURL = _CFBundleCopyExecutableURLRaw(exeSubdirURL, executableName);
1736                  }
1737                  if (!executableURL) executableURL = _CFBundleCopyExecutableURLRaw(exeDirURL, executableName);
1738                  CFRelease(exeDirURL);
1739                  CFRelease(exeSubdirURL);
1740              }
1741              
1742              // If this was an old bundle, or we did not find the executable in the Executables subdirectory, look directly in the bundle wrapper.
1743              if (!executableURL) executableURL = _CFBundleCopyExecutableURLRaw(url, executableName);
1744              
1745  #if DEPLOYMENT_TARGET_WINDOWS
1746              // Windows only: If we still haven't found the exe, look in the Executables folder.
1747              // But only for the main bundle exe
1748              if (lookupMainExe && !executableURL) {
1749                  CFURLRef exeDirURL = CFURLCreateWithString(kCFAllocatorSystemDefault, CFSTR("../../Executables"), url);
1750                  executableURL = _CFBundleCopyExecutableURLRaw(exeDirURL, executableName);
1751                  CFRelease(exeDirURL);
1752              }
1753  #endif
1754              
1755              if (lookupMainExe && !ignoreCache && !useOtherPlatform && bundle && executableURL) {
1756                  // We found it.  Cache the path.
1757                  CFURLRef absURL = CFURLCopyAbsoluteURL(executableURL);
1758  #if DEPLOYMENT_TARGET_WINDOWS
1759                  executablePath = CFURLCopyFileSystemPath(absURL, kCFURLWindowsPathStyle);
1760  #elif DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
1761                  executablePath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle);
1762  #endif
1763                  CFRelease(absURL);
1764                  __CFLock(&bundle->_lock);
1765                  bundle->_executablePath = (CFStringRef)CFRetain(executablePath);
1766                  __CFUnlock(&bundle->_lock);
1767                  CFRelease(executablePath);
1768              }
1769              if (lookupMainExe && !useOtherPlatform && bundle && !executableURL) bundle->_binaryType = __CFBundleNoBinary;
1770              if (lookupMainExe) CFRelease(executableName);
1771          }
1772      }
1773      if (!bundle && infoDict && !(0)) CFRelease(infoDict);
1774      return executableURL;
1775  }
1776  
1777  
1778  CFURLRef _CFBundleCopyExecutableURLInDirectory(CFURLRef url) {
1779      return _CFBundleCopyExecutableURLInDirectory2(NULL, url, NULL, true, false);
1780  }
1781  
1782  CFURLRef _CFBundleCopyOtherExecutableURLInDirectory(CFURLRef url) {
1783      return _CFBundleCopyExecutableURLInDirectory2(NULL, url, NULL, true, true);
1784  }
1785  
1786  CFURLRef CFBundleCopyExecutableURL(CFBundleRef bundle) {
1787      return _CFBundleCopyExecutableURLInDirectory2(bundle, bundle->_url, NULL, false, false);
1788  }
1789  
1790  static CFURLRef _CFBundleCopyExecutableURLIgnoringCache(CFBundleRef bundle) {
1791      return _CFBundleCopyExecutableURLInDirectory2(bundle, bundle->_url, NULL, true, false);
1792  }
1793  
1794  CFURLRef CFBundleCopyAuxiliaryExecutableURL(CFBundleRef bundle, CFStringRef executableName) {
1795      return _CFBundleCopyExecutableURLInDirectory2(bundle, bundle->_url, executableName, true, false);
1796  }
1797  
1798  Boolean CFBundleIsExecutableLoaded(CFBundleRef bundle) {
1799      return bundle->_isLoaded;
1800  }
1801  
1802  CFBundleExecutableType CFBundleGetExecutableType(CFBundleRef bundle) {
1803      CFBundleExecutableType result = kCFBundleOtherExecutableType;
1804      CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
1805  
1806      if (!executableURL) bundle->_binaryType = __CFBundleNoBinary;
1807  #if defined(BINARY_SUPPORT_DYLD)
1808      if (bundle->_binaryType == __CFBundleUnknownBinary) {
1809          bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
1810          if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
1811      }
1812  #endif /* BINARY_SUPPORT_DYLD */
1813      if (executableURL) CFRelease(executableURL);
1814  
1815      if (bundle->_binaryType == __CFBundleCFMBinary) {
1816          result = kCFBundlePEFExecutableType;
1817      } else if (bundle->_binaryType == __CFBundleDYLDExecutableBinary || bundle->_binaryType == __CFBundleDYLDBundleBinary || bundle->_binaryType == __CFBundleDYLDFrameworkBinary) {
1818          result = kCFBundleMachOExecutableType;
1819      } else if (bundle->_binaryType == __CFBundleDLLBinary) {
1820          result = kCFBundleDLLExecutableType;
1821      } else if (bundle->_binaryType == __CFBundleELFBinary) {
1822          result = kCFBundleELFExecutableType;    
1823      }
1824      return result;
1825  }
1826  
1827  void _CFBundleSetCFMConnectionID(CFBundleRef bundle, void *connectionID) {
1828      bundle->_connectionCookie = connectionID;
1829      bundle->_isLoaded = true;
1830  }
1831  
1832  static CFStringRef _CFBundleCopyLastPathComponent(CFBundleRef bundle) {
1833      CFURLRef bundleURL = CFBundleCopyBundleURL(bundle);
1834      if (!bundleURL) {
1835          return CFSTR("<unknown>");
1836      }
1837      CFStringRef str = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
1838      UniChar buff[CFMaxPathSize];
1839      CFIndex buffLen = CFStringGetLength(str), startOfLastDir = 0;
1840  
1841      CFRelease(bundleURL);
1842      if (buffLen > CFMaxPathSize) buffLen = CFMaxPathSize;
1843      CFStringGetCharacters(str, CFRangeMake(0, buffLen), buff);
1844      CFRelease(str);
1845      if (buffLen > 0) startOfLastDir = _CFStartOfLastPathComponent(buff, buffLen);
1846      return CFStringCreateWithCharacters(kCFAllocatorSystemDefault, &(buff[startOfLastDir]), buffLen - startOfLastDir);
1847  }
1848  
1849  #pragma mark -
1850  
1851  CF_PRIVATE CFErrorRef _CFBundleCreateErrorDebug(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code, CFStringRef debugString) {
1852      const void *userInfoKeys[6], *userInfoValues[6];
1853      CFIndex numKeys = 0;
1854      CFURLRef bundleURL = CFBundleCopyBundleURL(bundle), absoluteURL = CFURLCopyAbsoluteURL(bundleURL), executableURL = CFBundleCopyExecutableURL(bundle);
1855      CFBundleRef bdl = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreFoundation"));
1856      CFStringRef bundlePath = CFURLCopyFileSystemPath(absoluteURL, PLATFORM_PATH_STYLE), executablePath = executableURL ? CFURLCopyFileSystemPath(executableURL, PLATFORM_PATH_STYLE) : NULL, descFormat = NULL, desc = NULL, reason = NULL, suggestion = NULL;
1857      CFErrorRef error;
1858      if (bdl) {
1859          CFStringRef name = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleNameKey);
1860          name = name ? (CFStringRef)CFRetain(name) : _CFBundleCopyLastPathComponent(bundle);
1861          if (CFBundleExecutableNotFoundError == code) {
1862              descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
1863              reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable couldn\\U2019t be located."), "NSFileNoSuchFileError");
1864              suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr4-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSFileNoSuchFileError");
1865          } else if (CFBundleExecutableNotLoadableError == code) {
1866              descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded because its executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
1867              reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-C"), CFSTR("Error"), bdl, CFSTR("The bundle\\U2019s executable isn\\U2019t loadable."), "NSExecutableNotLoadableError");
1868              suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3584-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableNotLoadableError");
1869          } else if (CFBundleExecutableArchitectureMismatchError == code) {
1870              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");
1871              reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-C"), CFSTR("Error"), bdl, CFSTR("The bundle doesn\\U2019t contain a version for the current architecture."), "NSExecutableArchitectureMismatchError");
1872              suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3585-R"), CFSTR("Error"), bdl, CFSTR("Try installing a universal version of the bundle."), "NSExecutableArchitectureMismatchError");
1873          } else if (CFBundleExecutableRuntimeMismatchError == code) {
1874              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");
1875              reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-C"), CFSTR("Error"), bdl, CFSTR("The bundle isn\\U2019t compatible with this application."), "NSExecutableRuntimeMismatchError");
1876              suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3586-R"), CFSTR("Error"), bdl, CFSTR("Try installing a newer version of the bundle."), "NSExecutableRuntimeMismatchError");
1877          } else if (CFBundleExecutableLoadError == code) {
1878              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");
1879              reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-C"), CFSTR("Error"), bdl, CFSTR("The bundle is damaged or missing necessary resources."), "NSExecutableLoadError");
1880              suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3587-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLoadError");
1881          } else if (CFBundleExecutableLinkError == code) {
1882              descFormat = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588"), CFSTR("Error"), bdl, CFSTR("The bundle \\U201c%@\\U201d couldn\\U2019t be loaded."), "NSExecutableLinkError");
1883              reason = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-C"), CFSTR("Error"), bdl, CFSTR("The bundle couldn\\U2019t be loaded."), "NSExecutableLinkError");
1884              suggestion = CFCopyLocalizedStringWithDefaultValue(CFSTR("BundleErr3588-R"), CFSTR("Error"), bdl, CFSTR("Try reinstalling the bundle."), "NSExecutableLinkError");
1885          }
1886          if (descFormat) {
1887              desc = CFStringCreateWithFormat(allocator, NULL, descFormat, name);
1888              CFRelease(descFormat);
1889          }
1890          CFRelease(name);
1891      }
1892      if (bundlePath) {
1893          userInfoKeys[numKeys] = CFSTR("NSBundlePath");
1894          userInfoValues[numKeys] = bundlePath;
1895          numKeys++;
1896      }
1897      if (executablePath) {
1898          userInfoKeys[numKeys] = CFSTR("NSFilePath");
1899          userInfoValues[numKeys] = executablePath;
1900          numKeys++;
1901      }
1902      if (desc) {
1903          userInfoKeys[numKeys] = kCFErrorLocalizedDescriptionKey;
1904          userInfoValues[numKeys] = desc;
1905          numKeys++;
1906      }
1907      if (reason) {
1908          userInfoKeys[numKeys] = kCFErrorLocalizedFailureReasonKey;
1909          userInfoValues[numKeys] = reason;
1910          numKeys++;
1911      }
1912      if (suggestion) {
1913          userInfoKeys[numKeys] = kCFErrorLocalizedRecoverySuggestionKey;
1914          userInfoValues[numKeys] = suggestion;
1915          numKeys++;
1916      }
1917      if (debugString) {
1918          userInfoKeys[numKeys] = CFSTR("NSDebugDescription");
1919          userInfoValues[numKeys] = debugString;
1920          numKeys++;
1921      }
1922      error = CFErrorCreateWithUserInfoKeysAndValues(allocator, kCFErrorDomainCocoa, code, userInfoKeys, userInfoValues, numKeys);
1923      if (bundleURL) CFRelease(bundleURL);
1924      if (absoluteURL) CFRelease(absoluteURL);
1925      if (executableURL) CFRelease(executableURL);
1926      if (bundlePath) CFRelease(bundlePath);
1927      if (executablePath) CFRelease(executablePath);
1928      if (desc) CFRelease(desc);
1929      if (reason) CFRelease(reason);
1930      if (suggestion) CFRelease(suggestion);
1931      return error;
1932  }
1933  
1934  CFErrorRef _CFBundleCreateError(CFAllocatorRef allocator, CFBundleRef bundle, CFIndex code) {
1935      return _CFBundleCreateErrorDebug(allocator, bundle, code, NULL);
1936  }
1937  
1938  #pragma mark -
1939  
1940  Boolean _CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) {
1941      Boolean result = false;
1942      CFErrorRef localError = NULL, *subError = (error ? &localError : NULL);
1943      CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
1944  
1945  
1946      pthread_mutex_lock(&(bundle->_bundleLoadingLock));
1947      if (!executableURL) bundle->_binaryType = __CFBundleNoBinary;
1948      // make sure we know whether bundle is already loaded or not
1949  #if defined(BINARY_SUPPORT_DLFCN)
1950      if (!bundle->_isLoaded) _CFBundleDlfcnCheckLoaded(bundle);
1951  #elif defined(BINARY_SUPPORT_DYLD)
1952      if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
1953  #endif /* BINARY_SUPPORT_DLFCN */
1954  #if defined(BINARY_SUPPORT_DYLD)
1955      // We might need to figure out what it is
1956      if (bundle->_binaryType == __CFBundleUnknownBinary) {
1957          bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
1958          if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
1959      }
1960  #endif /* BINARY_SUPPORT_DYLD */
1961      if (executableURL) CFRelease(executableURL);
1962      
1963      if (bundle->_isLoaded) {
1964          pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
1965          // Remove from the scheduled unload set if we are there.
1966          pthread_mutex_lock(&CFBundleGlobalDataLock);
1967  #if AVOID_WEAK_COLLECTIONS
1968          if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
1969  #else /* AVOID_WEAK_COLLECTIONS */
1970          if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
1971  #endif /* AVOID_WEAK_COLLECTIONS */
1972          pthread_mutex_unlock(&CFBundleGlobalDataLock);
1973          return true;
1974      }
1975  
1976      // Unload bundles scheduled for unloading
1977      if (!_scheduledBundlesAreUnloading) {
1978          pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
1979          _CFBundleUnloadScheduledBundles();
1980          pthread_mutex_lock(&(bundle->_bundleLoadingLock));
1981      }
1982      
1983      if (bundle->_isLoaded) {
1984          pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
1985          // Remove from the scheduled unload set if we are there.
1986          pthread_mutex_lock(&CFBundleGlobalDataLock);
1987  #if AVOID_WEAK_COLLECTIONS
1988          if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
1989  #else /* AVOID_WEAK_COLLECTIONS */
1990          if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
1991  #endif /* AVOID_WEAK_COLLECTIONS */
1992          pthread_mutex_unlock(&CFBundleGlobalDataLock);
1993          return true;
1994      }
1995      pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
1996  
1997      switch (bundle->_binaryType) {
1998  #if defined(BINARY_SUPPORT_DLFCN)
1999          case __CFBundleUnreadableBinary:
2000              result = _CFBundleDlfcnLoadBundle(bundle, forceGlobal, subError);
2001              break;
2002  #endif /* BINARY_SUPPORT_DLFCN */
2003  #if defined(BINARY_SUPPORT_DYLD)
2004          case __CFBundleDYLDBundleBinary:
2005  #if defined(BINARY_SUPPORT_DLFCN)
2006              result = _CFBundleDlfcnLoadBundle(bundle, forceGlobal, subError);
2007  #else /* BINARY_SUPPORT_DLFCN */
2008              result = _CFBundleDYLDLoadBundle(bundle, forceGlobal, subError);
2009  #endif /* BINARY_SUPPORT_DLFCN */
2010              break;
2011          case __CFBundleDYLDFrameworkBinary:
2012  #if defined(BINARY_SUPPORT_DLFCN)
2013              result = _CFBundleDlfcnLoadFramework(bundle, subError);
2014  #else /* BINARY_SUPPORT_DLFCN */
2015              result = _CFBundleDYLDLoadFramework(bundle, subError);
2016  #endif /* BINARY_SUPPORT_DLFCN */
2017              break;
2018          case __CFBundleDYLDExecutableBinary:
2019              if (error) {
2020                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
2021              } else {
2022                  CFLog(__kCFLogBundle, CFSTR("Attempt to load executable of a type that cannot be dynamically loaded for %@"), bundle);
2023              }
2024              break;
2025  #endif /* BINARY_SUPPORT_DYLD */
2026  #if defined(BINARY_SUPPORT_DLFCN)
2027          case __CFBundleUnknownBinary:
2028          case __CFBundleELFBinary:
2029              result = _CFBundleDlfcnLoadBundle(bundle, forceGlobal, subError);
2030              break;
2031  #endif /* BINARY_SUPPORT_DLFCN */
2032  #if defined(BINARY_SUPPORT_DLL)
2033          case __CFBundleDLLBinary:
2034              result = _CFBundleDLLLoad(bundle, subError);
2035              break;
2036  #endif /* BINARY_SUPPORT_DLL */
2037          case __CFBundleNoBinary:
2038              if (error) {
2039                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
2040              } else {
2041                  CFLog(__kCFLogBundle, CFSTR("Cannot find executable for %@"), bundle);
2042              }
2043              break;     
2044          default:
2045              if (error) {
2046                  localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
2047              } else {
2048                  CFLog(__kCFLogBundle, CFSTR("Cannot recognize type of executable for %@"), bundle);
2049              }
2050              break;
2051      }
2052      if (result && bundle->_plugInData._isPlugIn) _CFBundlePlugInLoaded(bundle);
2053      if (!result && error) *error = localError;
2054      return result;
2055  }
2056  
2057  Boolean CFBundleLoadExecutableAndReturnError(CFBundleRef bundle, CFErrorRef *error) {
2058      return _CFBundleLoadExecutableAndReturnError(bundle, false, error);
2059  }
2060  
2061  Boolean CFBundleLoadExecutable(CFBundleRef bundle) {
2062      return _CFBundleLoadExecutableAndReturnError(bundle, false, NULL);
2063  }
2064  
2065  Boolean CFBundlePreflightExecutable(CFBundleRef bundle, CFErrorRef *error) {
2066      Boolean result = false;
2067      CFErrorRef localError = NULL;
2068  #if defined(BINARY_SUPPORT_DLFCN)
2069      CFErrorRef *subError = (error ? &localError : NULL);
2070  #endif
2071      CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
2072  
2073      pthread_mutex_lock(&(bundle->_bundleLoadingLock));
2074      if (!executableURL) bundle->_binaryType = __CFBundleNoBinary;
2075      // make sure we know whether bundle is already loaded or not
2076  #if defined(BINARY_SUPPORT_DLFCN)
2077      if (!bundle->_isLoaded) _CFBundleDlfcnCheckLoaded(bundle);
2078  #elif defined(BINARY_SUPPORT_DYLD)
2079      if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
2080  #endif /* BINARY_SUPPORT_DLFCN */
2081  #if defined(BINARY_SUPPORT_DYLD)
2082      // We might need to figure out what it is
2083      if (bundle->_binaryType == __CFBundleUnknownBinary) {
2084          bundle->_binaryType = _CFBundleGrokBinaryType(executableURL);
2085          if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
2086      }
2087  #endif /* BINARY_SUPPORT_DYLD */
2088      if (executableURL) CFRelease(executableURL);
2089      
2090      if (bundle->_isLoaded) {
2091          pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
2092          return true;
2093      }
2094      pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
2095      
2096      switch (bundle->_binaryType) {
2097  #if defined(BINARY_SUPPORT_DLFCN)
2098          case __CFBundleUnreadableBinary:
2099              result = _CFBundleDlfcnPreflight(bundle, subError);
2100              break;
2101  #endif /* BINARY_SUPPORT_DLFCN */
2102  #if defined(BINARY_SUPPORT_DYLD)
2103          case __CFBundleDYLDBundleBinary:
2104              result = true;
2105  #if defined(BINARY_SUPPORT_DLFCN)
2106              result = _CFBundleDlfcnPreflight(bundle, subError);
2107  #endif /* BINARY_SUPPORT_DLFCN */
2108              break;
2109          case __CFBundleDYLDFrameworkBinary:
2110              result = true;
2111  #if defined(BINARY_SUPPORT_DLFCN)
2112              result = _CFBundleDlfcnPreflight(bundle, subError);
2113  #endif /* BINARY_SUPPORT_DLFCN */
2114              break;
2115          case __CFBundleDYLDExecutableBinary:
2116              if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
2117              break;
2118  #endif /* BINARY_SUPPORT_DYLD */
2119  #if defined(BINARY_SUPPORT_DLFCN)
2120          case __CFBundleUnknownBinary:
2121          case __CFBundleELFBinary:
2122              result = _CFBundleDlfcnPreflight(bundle, subError);
2123              break;
2124  #endif /* BINARY_SUPPORT_DLFCN */
2125  #if defined(BINARY_SUPPORT_DLL)
2126          case __CFBundleDLLBinary:
2127              result = true;
2128              break;
2129  #endif /* BINARY_SUPPORT_DLL */
2130          case __CFBundleNoBinary:
2131              if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError);
2132              break;     
2133          default:
2134              if (error) localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError);
2135              break;
2136      }
2137      if (!result && error) *error = localError;
2138      return result;
2139  }
2140  
2141  CFArrayRef CFBundleCopyExecutableArchitectures(CFBundleRef bundle) {
2142      CFArrayRef result = NULL;
2143      CFURLRef executableURL = CFBundleCopyExecutableURL(bundle);
2144      if (executableURL) {
2145          result = _CFBundleCopyArchitecturesForExecutable(executableURL);
2146          CFRelease(executableURL);
2147      }
2148      return result;
2149  }
2150  
2151  void CFBundleUnloadExecutable(CFBundleRef bundle) {
2152      // First unload bundles scheduled for unloading (if that's not what we are already doing.)
2153      if (!_scheduledBundlesAreUnloading) _CFBundleUnloadScheduledBundles();
2154      
2155      if (!bundle->_isLoaded) return;
2156  
2157      // Remove from the scheduled unload set if we are there.
2158      if (!_scheduledBundlesAreUnloading) pthread_mutex_lock(&CFBundleGlobalDataLock);
2159  #if AVOID_WEAK_COLLECTIONS
2160      if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
2161  #else /* AVOID_WEAK_COLLECTIONS */
2162      if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
2163  #endif /* AVOID_WEAK_COLLECTIONS */
2164      if (!_scheduledBundlesAreUnloading) pthread_mutex_unlock(&CFBundleGlobalDataLock);
2165      
2166      // Give the plugIn code a chance to realize this...
2167      _CFPlugInWillUnload(bundle);
2168  
2169      pthread_mutex_lock(&(bundle->_bundleLoadingLock));
2170      if (!bundle->_isLoaded) {
2171          pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
2172          return;
2173      }
2174      pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
2175  
2176      switch (bundle->_binaryType) {
2177  #if defined(BINARY_SUPPORT_DYLD)
2178          case __CFBundleDYLDBundleBinary:
2179  #if defined(BINARY_SUPPORT_DLFCN)
2180              if (bundle->_handleCookie) _CFBundleDlfcnUnload(bundle);
2181  #else /* BINARY_SUPPORT_DLFCN */
2182              _CFBundleDYLDUnloadBundle(bundle);
2183  #endif /* BINARY_SUPPORT_DLFCN */
2184              break;
2185          case __CFBundleDYLDFrameworkBinary:
2186  #if defined(BINARY_SUPPORT_DLFCN)
2187              if (bundle->_handleCookie && _CFExecutableLinkedOnOrAfter(CFSystemVersionLeopard)) _CFBundleDlfcnUnload(bundle);
2188  #endif /* BINARY_SUPPORT_DLFCN */
2189              break;
2190  #endif /* BINARY_SUPPORT_DYLD */
2191  #if defined(BINARY_SUPPORT_DLL)
2192          case __CFBundleDLLBinary:
2193              _CFBundleDLLUnload(bundle);
2194              break;
2195  #endif /* BINARY_SUPPORT_DLL */
2196          default:
2197  #if defined(BINARY_SUPPORT_DLFCN)
2198              if (bundle->_handleCookie) _CFBundleDlfcnUnload(bundle);
2199  #endif /* BINARY_SUPPORT_DLFCN */
2200              break;
2201      }
2202      if (!bundle->_isLoaded && bundle->_glueDict) {
2203          CFDictionaryApplyFunction(bundle->_glueDict, _CFBundleDeallocateGlue, (void *)CFGetAllocator(bundle));
2204          CFRelease(bundle->_glueDict);
2205          bundle->_glueDict = NULL;
2206      }
2207  }
2208  
2209  #if AVOID_WEAK_COLLECTIONS
2210  
2211  CF_PRIVATE void _CFBundleScheduleForUnloading(CFBundleRef bundle) {
2212      pthread_mutex_lock(&CFBundleGlobalDataLock);
2213      if (!_bundlesToUnload) {
2214          CFSetCallBacks nonRetainingCallbacks = kCFTypeSetCallBacks;
2215          nonRetainingCallbacks.retain = NULL;
2216          nonRetainingCallbacks.release = NULL;
2217          _bundlesToUnload = CFSetCreateMutable(kCFAllocatorSystemDefault, 0, &nonRetainingCallbacks);
2218      }
2219      CFSetAddValue(_bundlesToUnload, bundle);
2220      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2221  }
2222  
2223  CF_PRIVATE void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) {
2224      pthread_mutex_lock(&CFBundleGlobalDataLock);
2225      if (_bundlesToUnload) CFSetRemoveValue(_bundlesToUnload, bundle);
2226      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2227  }
2228  
2229  CF_PRIVATE void _CFBundleUnloadScheduledBundles(void) {
2230      pthread_mutex_lock(&CFBundleGlobalDataLock);
2231      if (_bundlesToUnload) {
2232          CFIndex i, c = CFSetGetCount(_bundlesToUnload);
2233          if (c > 0) {
2234              CFBundleRef *unloadThese = (CFBundleRef *)CFAllocatorAllocate(kCFAllocatorSystemDefault, sizeof(CFBundleRef) * c, 0);
2235              CFSetGetValues(_bundlesToUnload, (const void **)unloadThese);
2236              _scheduledBundlesAreUnloading = true;
2237              for (i = 0; i < c; i++) {
2238                  // This will cause them to be removed from the set.  (Which is why we copied all the values out of the set up front.)
2239                  CFBundleUnloadExecutable(unloadThese[i]);
2240              }
2241              _scheduledBundlesAreUnloading = false;
2242              CFAllocatorDeallocate(kCFAllocatorSystemDefault, unloadThese);
2243          }
2244      }
2245      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2246  }
2247  
2248  #else /* AVOID_WEAK_COLLECTIONS */
2249  
2250  CF_PRIVATE void _CFBundleScheduleForUnloading(CFBundleRef bundle) {
2251      pthread_mutex_lock(&CFBundleGlobalDataLock);
2252      if (!_bundlesToUnload) _bundlesToUnload = [[__CFHashTable alloc] initWithOptions:CFPointerFunctionsZeroingWeakMemory capacity:0];
2253      [_bundlesToUnload addObject:(id)bundle];
2254      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2255  }
2256  
2257  CF_PRIVATE void _CFBundleUnscheduleForUnloading(CFBundleRef bundle) {
2258      pthread_mutex_lock(&CFBundleGlobalDataLock);
2259      if (_bundlesToUnload) [_bundlesToUnload removeObject:(id)bundle];
2260      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2261  }
2262  
2263  CF_PRIVATE void _CFBundleUnloadScheduledBundles(void) {
2264      pthread_mutex_lock(&CFBundleGlobalDataLock);
2265      if (_bundlesToUnload && [_bundlesToUnload count] > 0) {
2266          CFIndex i, c;
2267          CFMutableArrayRef unloadThese = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
2268          for (id value in _bundlesToUnload) CFArrayAppendValue(unloadThese, value);
2269          c = CFArrayGetCount(unloadThese);
2270          if (c > 0) {
2271              _scheduledBundlesAreUnloading = true;
2272              for (i = 0; i < c; i++) {
2273                  // This will cause them to be removed from the set.  (Which is why we copied all the values out of the set up front.)
2274                  CFBundleUnloadExecutable((CFBundleRef)CFArrayGetValueAtIndex(unloadThese, i));
2275              }
2276              _scheduledBundlesAreUnloading = false;
2277          }
2278          CFRelease(unloadThese);
2279      }
2280      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2281  }
2282  
2283  #endif /* AVOID_WEAK_COLLECTIONS */
2284  
2285  #pragma mark -
2286  
2287  CF_PRIVATE _CFResourceData *__CFBundleGetResourceData(CFBundleRef bundle) {
2288      return &(bundle->_resourceData);
2289  }
2290  
2291  CFPlugInRef CFBundleGetPlugIn(CFBundleRef bundle) {
2292      return (bundle->_plugInData._isPlugIn) ? (CFPlugInRef)bundle : NULL;
2293  }
2294  
2295  CF_PRIVATE _CFPlugInData *__CFBundleGetPlugInData(CFBundleRef bundle) {
2296      return &(bundle->_plugInData);
2297  }
2298  
2299  CF_PRIVATE Boolean _CFBundleCouldBeBundle(CFURLRef url) {
2300      Boolean result = false;
2301      Boolean exists;
2302      SInt32 mode;
2303      if (_CFGetFileProperties(kCFAllocatorSystemDefault, url, &exists, &mode, NULL, NULL, NULL, NULL) == 0) result = (exists && (mode & S_IFMT) == S_IFDIR && (mode & 0444) != 0);
2304      return result;
2305  }
2306  
2307  #define LENGTH_OF(A) (sizeof(A) / sizeof(A[0]))
2308          
2309  //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/
2310  static CFURLRef __CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath, Boolean permissive) {
2311      // 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.
2312  #if DEPLOYMENT_TARGET_WINDOWS
2313      UniChar executablesToFrameworksPathBuff[] = {'.', '.', '\\', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
2314      UniChar executablesToPrivateFrameworksPathBuff[] = {'.', '.', '\\', 'P', 'r', 'i', 'v', 'a', 't', 'e', 'F', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k', 's'};
2315      UniChar frameworksExtension[] = {'f', 'r', 'a', 'm', 'e', 'w', 'o', 'r', 'k'};
2316  #endif
2317      UniChar pathBuff[CFMaxPathSize] = {0};
2318      UniChar nameBuff[CFMaxPathSize] = {0};
2319      CFIndex length, nameStart, nameLength, savedLength;
2320      CFMutableStringRef cheapStr = CFStringCreateMutableWithExternalCharactersNoCopy(kCFAllocatorSystemDefault, NULL, 0, 0, NULL);
2321      CFURLRef bundleURL = NULL;
2322  
2323      length = CFStringGetLength(executablePath);
2324      if (length > CFMaxPathSize) length = CFMaxPathSize;
2325      CFStringGetCharacters(executablePath, CFRangeMake(0, length), pathBuff);
2326  
2327      // Save the name in nameBuff
2328      length = _CFLengthAfterDeletingPathExtension(pathBuff, length);
2329      nameStart = _CFStartOfLastPathComponent(pathBuff, length);
2330      nameLength = length - nameStart;
2331      memmove(nameBuff, &(pathBuff[nameStart]), nameLength * sizeof(UniChar));
2332  
2333      // Strip the name from pathBuff
2334      length = _CFLengthAfterDeletingLastPathComponent(pathBuff, length);
2335      savedLength = length;
2336  
2337  #if DEPLOYMENT_TARGET_WINDOWS
2338      // * (Windows-only) First check the "Executables" directory parallel to the "Frameworks" directory case.
2339      if (_CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, executablesToFrameworksPathBuff, LENGTH_OF(executablesToFrameworksPathBuff)) && _CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, nameBuff, nameLength) && _CFAppendPathExtension(pathBuff, &length, CFMaxPathSize, frameworksExtension, LENGTH_OF(frameworksExtension))) {
2340          CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
2341          bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, cheapStr, PLATFORM_PATH_STYLE, true);
2342          if (!_CFBundleCouldBeBundle(bundleURL)) {
2343              CFRelease(bundleURL);
2344              bundleURL = NULL;
2345          }
2346      }
2347      // * (Windows-only) Next check the "Executables" directory parallel to the "PrivateFrameworks" directory case.
2348      if (!bundleURL) {
2349          length = savedLength;
2350          if (_CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, executablesToPrivateFrameworksPathBuff, LENGTH_OF(executablesToPrivateFrameworksPathBuff)) && _CFAppendPathComponent(pathBuff, &length, CFMaxPathSize, nameBuff, nameLength) && _CFAppendPathExtension(pathBuff, &length, CFMaxPathSize, frameworksExtension, LENGTH_OF(frameworksExtension))) {
2351              CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
2352              bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, cheapStr, PLATFORM_PATH_STYLE, true);
2353              if (!_CFBundleCouldBeBundle(bundleURL)) {
2354                  CFRelease(bundleURL);
2355                  bundleURL = NULL;
2356              }
2357          }
2358      }
2359  #endif
2360      // * Finally check the executable inside the framework case.
2361      if (!bundleURL) {        
2362          length = savedLength;
2363          // To catch all the cases, we just peel off level looking for one ending in .framework or one called "Supporting Files".
2364          
2365          CFStringRef name = permissive ? CFSTR("") : CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, (const char *)nameBuff);
2366          
2367          while (length > 0) {
2368              CFIndex curStart = _CFStartOfLastPathComponent(pathBuff, length);
2369              if (curStart >= length) break;
2370              CFStringSetExternalCharactersNoCopy(cheapStr, &(pathBuff[curStart]), length - curStart, CFMaxPathSize - curStart);
2371              if (!permissive && CFEqual(cheapStr, _CFBundleResourcesDirectoryName)) break;
2372              if (CFEqual(cheapStr, _CFBundleSupportFilesDirectoryName1) || CFEqual(cheapStr, _CFBundleSupportFilesDirectoryName2)) {
2373                  if (!permissive) {
2374                      CFIndex fmwkStart = _CFStartOfLastPathComponent(pathBuff, length);
2375                      CFStringSetExternalCharactersNoCopy(cheapStr, &(pathBuff[fmwkStart]), length - fmwkStart, CFMaxPathSize - fmwkStart);
2376                  }
2377                  if (permissive || CFStringHasPrefix(cheapStr, name)) {
2378                      length = _CFLengthAfterDeletingLastPathComponent(pathBuff, length);
2379                      CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
2380                      
2381                      bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, cheapStr, PLATFORM_PATH_STYLE, true);
2382                      if (!_CFBundleCouldBeBundle(bundleURL)) {
2383                          CFRelease(bundleURL);
2384                          bundleURL = NULL;
2385                      }
2386                      break;
2387                  }
2388              } else if (CFStringHasSuffix(cheapStr, CFSTR(".framework")) && (permissive || CFStringHasPrefix(cheapStr, name))) {
2389                  CFStringSetExternalCharactersNoCopy(cheapStr, pathBuff, length, CFMaxPathSize);
2390                  bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorSystemDefault, cheapStr, PLATFORM_PATH_STYLE, true);
2391                  if (!_CFBundleCouldBeBundle(bundleURL)) {
2392                      CFRelease(bundleURL);
2393                      bundleURL = NULL;
2394                  }
2395                  break;
2396              }
2397              length = _CFLengthAfterDeletingLastPathComponent(pathBuff, length);
2398          }
2399          if (!permissive) CFRelease(name);
2400      }
2401      CFStringSetExternalCharactersNoCopy(cheapStr, NULL, 0, 0);
2402      CFRelease(cheapStr);
2403  
2404      return bundleURL;
2405  }
2406          
2407  //SPI version; separated out to minimize linkage changes
2408  CFURLRef _CFBundleCopyFrameworkURLForExecutablePath(CFStringRef executablePath) {
2409      return __CFBundleCopyFrameworkURLForExecutablePath(executablePath, false);
2410  }
2411  
2412  static void _CFBundleEnsureBundleExistsForImagePath(CFStringRef imagePath) {
2413      // This finds the bundle for the given path.
2414      // 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.
2415      CFBundleRef bundle;
2416      CFURLRef curURL = __CFBundleCopyFrameworkURLForExecutablePath(imagePath, true);
2417      Boolean createdBundle = false;
2418  
2419      if (curURL) {
2420          bundle = _CFBundleCopyBundleForURL(curURL, true);
2421          if (!bundle) {
2422              // Ensure bundle exists by creating it if necessary
2423              // NB doFinalProcessing must be false here, see below
2424              bundle = _CFBundleCreate(kCFAllocatorSystemDefault, curURL, true, false, false);
2425              createdBundle = true;
2426          }
2427          if (bundle) {
2428              pthread_mutex_lock(&(bundle->_bundleLoadingLock));
2429              if (!bundle->_isLoaded) {
2430                  // 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)
2431      #if defined(BINARY_SUPPORT_DLFCN)
2432                  if (!bundle->_isLoaded) _CFBundleDlfcnCheckLoaded(bundle);
2433      #elif defined(BINARY_SUPPORT_DYLD)
2434                  if (!bundle->_isLoaded) _CFBundleDYLDCheckLoaded(bundle);
2435      #endif /* BINARY_SUPPORT_DLFCN */
2436      #if defined(BINARY_SUPPORT_DYLD)
2437                  if (bundle->_binaryType == __CFBundleUnknownBinary) bundle->_binaryType = __CFBundleDYLDFrameworkBinary;
2438                  if (bundle->_binaryType != __CFBundleCFMBinary && bundle->_binaryType != __CFBundleUnreadableBinary) bundle->_resourceData._executableLacksResourceFork = true;
2439      #endif /* BINARY_SUPPORT_DYLD */
2440      #if LOG_BUNDLE_LOAD
2441                  if (!bundle->_isLoaded) printf("ensure bundle %p set loaded fallback, handle %p image %p conn %p\n", bundle, bundle->_handleCookie, bundle->_imageCookie, bundle->_connectionCookie);
2442      #endif /* LOG_BUNDLE_LOAD */
2443                  bundle->_isLoaded = true;
2444              }
2445              pthread_mutex_unlock(&(bundle->_bundleLoadingLock));
2446              if (createdBundle) {
2447                  // Perform delayed final processing steps.
2448                  // This must be done after _isLoaded has been set, for security reasons (3624341).
2449                  if (_CFBundleNeedsInitPlugIn(bundle)) {
2450                      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2451                      _CFBundleInitPlugIn(bundle);
2452                      pthread_mutex_lock(&CFBundleGlobalDataLock);
2453                  }
2454              } else {
2455                  // Release the bundle if we did not create it here
2456                  CFRelease(bundle);
2457              }
2458          }
2459          CFRelease(curURL);
2460      }
2461  }
2462  
2463  static void _CFBundleEnsureBundlesExistForImagePaths(CFArrayRef imagePaths) {
2464      // This finds the bundles for the given paths.
2465      // 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).
2466      CFIndex i, imagePathCount = CFArrayGetCount(imagePaths);
2467      for (i = 0; i < imagePathCount; i++) _CFBundleEnsureBundleExistsForImagePath((CFStringRef)CFArrayGetValueAtIndex(imagePaths, i));
2468  }
2469  
2470  static void _CFBundleEnsureBundlesUpToDateWithHintAlreadyLocked(CFStringRef hint) {
2471      CFArrayRef imagePaths = NULL;
2472      // Tickle the main bundle into existence
2473      (void)_CFBundleGetMainBundleAlreadyLocked();
2474  #if defined(BINARY_SUPPORT_DYLD)
2475      imagePaths = _CFBundleDYLDCopyLoadedImagePathsForHint(hint);
2476  #endif /* BINARY_SUPPORT_DYLD */
2477      if (imagePaths) {
2478          _CFBundleEnsureBundlesExistForImagePaths(imagePaths);
2479          CFRelease(imagePaths);
2480      }
2481  }
2482  
2483  static void _CFBundleEnsureAllBundlesUpToDateAlreadyLocked(void) {
2484      // 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.
2485      CFArrayRef imagePaths = NULL;
2486      // Tickle the main bundle into existence
2487      (void)_CFBundleGetMainBundleAlreadyLocked();
2488  
2489  #if defined(BINARY_SUPPORT_DLL)
2490  // Dont know how to find static bundles for DLLs
2491  #endif /* BINARY_SUPPORT_DLL */
2492  
2493  #if defined(BINARY_SUPPORT_DYLD)
2494      imagePaths = _CFBundleDYLDCopyLoadedImagePathsIfChanged();
2495  #endif /* BINARY_SUPPORT_DYLD */
2496      if (imagePaths) {
2497          _CFBundleEnsureBundlesExistForImagePaths(imagePaths);
2498          CFRelease(imagePaths);
2499      }
2500  }
2501  
2502  CFArrayRef CFBundleGetAllBundles(void) {
2503      // To answer this properly, we have to have created the static bundles!
2504  #if !AVOID_WEAK_COLLECTIONS
2505      static CFMutableArrayRef externalAllBundles = NULL;
2506  #endif /* AVOID_WEAK_COLLECTIONS */
2507      CFArrayRef bundles;
2508      pthread_mutex_lock(&CFBundleGlobalDataLock);
2509      _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
2510  #if AVOID_WEAK_COLLECTIONS
2511      bundles = _allBundles;
2512  #else /* AVOID_WEAK_COLLECTIONS */
2513      if (!externalAllBundles) {
2514          CFArrayCallBacks nonRetainingArrayCallbacks = kCFTypeArrayCallBacks;
2515          nonRetainingArrayCallbacks.retain = NULL;
2516          nonRetainingArrayCallbacks.release = NULL;
2517          externalAllBundles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &nonRetainingArrayCallbacks);
2518      }
2519      CFArrayRemoveAllValues(externalAllBundles);
2520      for (id value in _allBundles) CFArrayAppendValue(externalAllBundles, value);
2521      bundles = externalAllBundles;
2522  #endif /* AVOID_WEAK_COLLECTIONS */
2523      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2524      return bundles;
2525  }
2526          
2527  CF_EXPORT CFArrayRef _CFBundleCopyAllBundles(void) {
2528      // To answer this properly, we have to have created the static bundles!
2529      pthread_mutex_lock(&CFBundleGlobalDataLock);
2530      _CFBundleEnsureAllBundlesUpToDateAlreadyLocked();
2531  #if AVOID_WEAK_COLLECTIONS
2532      CFArrayRef bundles = CFArrayCreateCopy(kCFAllocatorSystemDefault, _allBundles);
2533  #else /* AVOID_WEAK_COLLECTIONS */
2534      CFMutableArrayRef bundles = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
2535      for (id value in _allBundles) CFArrayAppendValue(bundles, value);
2536  #endif /* AVOID_WEAK_COLLECTIONS */
2537      pthread_mutex_unlock(&CFBundleGlobalDataLock);
2538      return bundles;
2539  }
2540  
2541  CF_PRIVATE uint8_t _CFBundleLayoutVersion(CFBundleRef bundle) {
2542      return bundle->_version;
2543  }
2544       
2545  CF_EXPORT CFURLRef _CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) {
2546      return CFBundleCopyPrivateFrameworksURL(bundle);
2547  }
2548  
2549  CF_EXPORT CFURLRef CFBundleCopyPrivateFrameworksURL(CFBundleRef bundle) {
2550      CFURLRef result = NULL;
2551  
2552      if (1 == bundle->_version) {
2553          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundlePrivateFrameworksURLFromBase1, bundle->_url);
2554      } else if (2 == bundle->_version) {
2555          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundlePrivateFrameworksURLFromBase2, bundle->_url);
2556      } else {
2557          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundlePrivateFrameworksURLFromBase0, bundle->_url);
2558      }
2559      return result;
2560  }
2561  
2562  CF_EXPORT CFURLRef _CFBundleCopySharedFrameworksURL(CFBundleRef bundle) {
2563      return CFBundleCopySharedFrameworksURL(bundle);
2564  }
2565  
2566  CF_EXPORT CFURLRef CFBundleCopySharedFrameworksURL(CFBundleRef bundle) {
2567      CFURLRef result = NULL;
2568  
2569      if (1 == bundle->_version) {
2570          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundleSharedFrameworksURLFromBase1, bundle->_url);
2571      } else if (2 == bundle->_version) {
2572          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundleSharedFrameworksURLFromBase2, bundle->_url);
2573      } else {
2574          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundleSharedFrameworksURLFromBase0, bundle->_url);
2575      }
2576      return result;
2577  }
2578  
2579  CF_EXPORT CFURLRef _CFBundleCopySharedSupportURL(CFBundleRef bundle) {
2580      return CFBundleCopySharedSupportURL(bundle);
2581  }
2582  
2583  CF_EXPORT CFURLRef CFBundleCopySharedSupportURL(CFBundleRef bundle) {
2584      CFURLRef result = NULL;
2585  
2586      if (1 == bundle->_version) {
2587          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundleSharedSupportURLFromBase1, bundle->_url);
2588      } else if (2 == bundle->_version) {
2589          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundleSharedSupportURLFromBase2, bundle->_url);
2590      } else {
2591          result = CFURLCreateWithString(CFGetAllocator(bundle), _CFBundleSharedSupportURLFromBase0, bundle->_url);
2592      }
2593      return result;
2594  }
2595  
2596  CF_PRIVATE CFURLRef _CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) {
2597      return CFBundleCopyBuiltInPlugInsURL(bundle);
2598  }
2599  
2600  CF_EXPORT CFURLRef CFBundleCopyBuiltInPlugInsURL(CFBundleRef bundle) {
2601      CFURLRef result = NULL, alternateResult = NULL;
2602  
2603      CFAllocatorRef alloc = CFGetAllocator(bundle);
2604      if (1 == bundle->_version) {
2605          result = CFURLCreateWithString(alloc, _CFBundleBuiltInPlugInsURLFromBase1, bundle->_url);
2606      } else if (2 == bundle->_version) {
2607          result = CFURLCreateWithString(alloc, _CFBundleBuiltInPlugInsURLFromBase2, bundle->_url);
2608      } else {
2609          result = CFURLCreateWithString(alloc, _CFBundleBuiltInPlugInsURLFromBase0, bundle->_url);
2610      }
2611      if (!result || !_urlExists(result)) {
2612          if (1 == bundle->_version) {
2613              alternateResult = CFURLCreateWithString(alloc, _CFBundleAlternateBuiltInPlugInsURLFromBase1, bundle->_url);
2614          } else if (2 == bundle->_version) {
2615              alternateResult = CFURLCreateWithString(alloc, _CFBundleAlternateBuiltInPlugInsURLFromBase2, bundle->_url);
2616          } else {
2617              alternateResult = CFURLCreateWithString(alloc, _CFBundleAlternateBuiltInPlugInsURLFromBase0, bundle->_url);
2618          }
2619          if (alternateResult && _urlExists(alternateResult)) {
2620              if (result) CFRelease(result);
2621              result = alternateResult;
2622          } else {
2623              if (alternateResult) CFRelease(alternateResult);
2624          }
2625      }
2626      return result;
2627  }
2628  
2629  CF_EXPORT CFBundleRef _CFBundleCreateUnique(CFAllocatorRef allocator, CFURLRef bundleURL) {
2630      return _CFBundleCreate(allocator, bundleURL, false, true, true);
2631  }