void CFPreferencesFlushCaches(void) { CFAllocatorRef alloc = __CFPreferencesAllocator(); __CFLock(&__CFApplicationPreferencesLock); if (__CFStandardUserPreferences) { _CFApplicationPreferences **prefsArray, *prefsBuf[32]; CFIndex idx, count = CFDictionaryGetCount(__CFStandardUserPreferences); if (count < 32) { prefsArray = prefsBuf; } else { prefsArray = (_CFApplicationPreferences **)CFAllocatorAllocate(alloc, count * sizeof(_CFApplicationPreferences *), 0); } CFDictionaryGetKeysAndValues(__CFStandardUserPreferences, NULL, (const void **)prefsArray); __CFUnlock(&__CFApplicationPreferencesLock); // DeallocateApplicationPreferences needs the lock for (idx = 0; idx < count; idx ++) { _CFApplicationPreferences *appPrefs = prefsArray[idx]; _CFApplicationPreferencesSynchronize(appPrefs); _CFDeallocateApplicationPreferences(appPrefs); } __CFLock(&__CFApplicationPreferencesLock); CFRelease(__CFStandardUserPreferences); __CFStandardUserPreferences = NULL; if(prefsArray != prefsBuf) CFAllocatorDeallocate(alloc, prefsArray); } __CFUnlock(&__CFApplicationPreferencesLock); _CFPreferencesPurgeDomainCache(); }
CF_PRIVATE CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamError *streamError) { CFErrorRef result; Boolean canUpCall; __CFLock(&(CFNetworkSupport.lock)); if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport(); canUpCall = (CFNetworkSupport._CFErrorCreateWithStreamError != NULL); __CFUnlock(&(CFNetworkSupport.lock)); if (canUpCall) { result = CFNETWORK_CALL(_CFErrorCreateWithStreamError, (alloc, streamError)); } else { if (streamError->domain == kCFStreamErrorDomainPOSIX) { return CFErrorCreate(alloc, kCFErrorDomainPOSIX, streamError->error, NULL); } else if (streamError->domain == kCFStreamErrorDomainMacOSStatus) { return CFErrorCreate(alloc, kCFErrorDomainOSStatus, streamError->error, NULL); } else { CFStringRef key = CFSTR("CFStreamErrorDomainKey"); CFNumberRef value = CFNumberCreate(alloc, kCFNumberCFIndexType, &streamError->domain); CFDictionaryRef dict = CFDictionaryCreate(alloc, (const void **)(&key), (const void **)(&value), 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); result = CFErrorCreate(alloc, CFSTR("BogusCFStreamErrorCompatibilityDomain"), streamError->error, dict); CFRelease(value); CFRelease(dict); } } return result; }
CF_PRIVATE CFStreamError _CFStreamErrorFromError(CFErrorRef error) { CFStreamError result; Boolean canUpCall; __CFLock(&(CFNetworkSupport.lock)); if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport(); canUpCall = (CFNetworkSupport._CFStreamErrorFromCFError != NULL); __CFUnlock(&(CFNetworkSupport.lock)); if (canUpCall) { result = CFNETWORK_CALL(_CFStreamErrorFromCFError, (error)); } else { CFStringRef domain = CFErrorGetDomain(error); if (CFEqual(domain, kCFErrorDomainPOSIX)) { result.domain = kCFStreamErrorDomainPOSIX; } else if (CFEqual(domain, kCFErrorDomainOSStatus)) { result.domain = kCFStreamErrorDomainMacOSStatus; } else if (CFEqual(domain, kCFErrorDomainMach)) { result.domain = 11; // kCFStreamErrorDomainMach, but that symbol is in CFNetwork } else { result.domain = kCFStreamErrorDomainCustom; } result.error = CFErrorGetCode(error); } return result; }
Boolean _CFApplicationPreferencesSynchronize(_CFApplicationPreferences *self) { Boolean result; __CFLock(&__CFApplicationPreferencesLock); result = _CFApplicationPreferencesSynchronizeNoLock(self); __CFUnlock(&__CFApplicationPreferencesLock); return result; }
CF_PRIVATE Boolean _CFSynchronizeDomainCache(void) { Boolean result = true; __CFLock(&domainCacheLock); if (domainCache) { CFDictionaryApplyFunction(domainCache, __CFPreferencesPerformSynchronize, &result); } __CFUnlock(&domainCacheLock); return result; }
CF_PRIVATE void _CFPreferencesPurgeDomainCache(void) { _CFSynchronizeDomainCache(); __CFLock(&domainCacheLock); if (domainCache) { CFRelease(domainCache); domainCache = NULL; } __CFUnlock(&domainCacheLock); }
CFPreferencesDomainRef _CFPreferencesStandardDomain(CFStringRef domainName, CFStringRef userName, CFStringRef hostName) { CFPreferencesDomainRef domain; CFStringRef domainKey; Boolean shouldReleaseDomain = true; domainKey = _CFPreferencesStandardDomainCacheKey(domainName, userName, hostName); __CFLock(&domainCacheLock); if (!domainCache) { CFAllocatorRef alloc = __CFPreferencesAllocator(); domainCache = CFDictionaryCreateMutable(alloc, 0, & kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } domain = (CFPreferencesDomainRef)CFDictionaryGetValue(domainCache, domainKey); __CFUnlock(&domainCacheLock); if (!domain) { // Domain's not in the cache; load from permanent storage CFURLRef theURL = _CFPreferencesURLForStandardDomain(domainName, userName, hostName); if (theURL) { domain = _CFPreferencesDomainCreate(theURL, &__kCFXMLPropertyListDomainCallBacks); if (userName == kCFPreferencesAnyUser) { _CFPreferencesDomainSetIsWorldReadable(domain, true); } CFRelease(theURL); } __CFLock(&domainCacheLock); if (domain && domainCache) { // We've just synthesized a domain & we're about to throw it in the domain cache. The problem is that someone else might have gotten in here behind our backs, so we can't just blindly set the domain (3021920). We'll need to check to see if this happened, and compensate. CFPreferencesDomainRef checkDomain = (CFPreferencesDomainRef)CFDictionaryGetValue(domainCache, domainKey); if(checkDomain) { // Someone got in here ahead of us, so we shouldn't smash the domain we're given. checkDomain is the current version, we should use that. // checkDomain was retrieved with a Get, so we don't want to over-release. shouldReleaseDomain = false; CFRelease(domain); // release the domain we synthesized earlier. domain = checkDomain; // repoint it at the domain picked up out of the cache. } else { // We must not have found the domain in the cache, so it's ok for us to put this in. CFDictionarySetValue(domainCache, domainKey, domain); } if(shouldReleaseDomain) CFRelease(domain); } __CFUnlock(&domainCacheLock); } CFRelease(domainKey); return domain; }
void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain, Boolean addAtTop) { __CFLock(&__CFApplicationPreferencesLock); if (addAtTop) { CFArrayInsertValueAtIndex(self->_search, 0, domain); } else { CFArrayAppendValue(self->_search, domain); } updateDictRep(self); __CFUnlock(&__CFApplicationPreferencesLock); }
static void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences *self, CFArrayRef newSearchList) { CFIndex idx, count; __CFLock(&__CFApplicationPreferencesLock); CFArrayRemoveAllValues(self->_search); count = CFArrayGetCount(newSearchList); for (idx = 0; idx < count; idx ++) { CFArrayAppendValue(self->_search, CFArrayGetValueAtIndex(newSearchList, idx)); } updateDictRep(self); __CFUnlock(&__CFApplicationPreferencesLock); }
CF_INLINE CFDictionaryRef URLPropertyDictForPOSIXMode(SInt32 mode) { static CFMutableDictionaryRef _propertyDict = NULL; CFNumberRef num = CFNumberCreate(__CFPreferencesAllocator(), kCFNumberSInt32Type, &mode); __CFLock(&_propDictLock); if (!_propertyDict) { _propertyDict = CFDictionaryCreateMutable(__CFPreferencesAllocator(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } CFDictionarySetValue(_propertyDict, kCFURLFilePOSIXMode, num); CFRelease(num); return _propertyDict; }
Boolean _CFApplicationPreferencesContainsDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) { Boolean result; if (!domain) { return false; } __CFLock(&__CFApplicationPreferencesLock); result = CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), domain); __CFUnlock(&__CFApplicationPreferencesLock); return result; }
static CFTypeRef fetchXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFTypeRef result; // Never reload if we've looked at the file system within the last 5 seconds. __CFLock(&domain->_lock); if (domain->_domainDict == NULL) _loadXMLDomainIfStale((CFURLRef )context, domain); result = CFDictionaryGetValue(domain->_domainDict, key); if (result) CFRetain(result); __CFUnlock(&domain->_lock); return result; }
// CACHING here - we will only return a value as current as the last time computeDictRep() was called static CFTypeRef _CFApplicationPreferencesCreateValueForKey2(_CFApplicationPreferences *self, CFStringRef defaultName) { CFTypeRef result; __CFLock(&__CFApplicationPreferencesLock); if (!self->_dictRep) { self->_dictRep = computeDictRep(self, true); } result = (self->_dictRep) ? (CFTypeRef )CFDictionaryGetValue(self->_dictRep, defaultName) : NULL; if (result) { CFRetain(result); } __CFUnlock(&__CFApplicationPreferencesLock); return result; }
CF_EXPORT CFDictionaryRef _CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences *self) { CFDictionaryRef dict; __CFLock(&__CFApplicationPreferencesLock); if (!self->_dictRep) { self->_dictRep = computeDictRep(self, true); } if (self->_dictRep) { CFRetain(self->_dictRep); } dict = self->_dictRep; __CFUnlock(&__CFApplicationPreferencesLock); return dict; }
void _CFApplicationPreferencesRemove(_CFApplicationPreferences *self, CFStringRef defaultName) { CFPreferencesDomainRef appDomain; __CFLock(&__CFApplicationPreferencesLock); appDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if(appDomain) { _CFPreferencesDomainSet(appDomain, defaultName, NULL); if (CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), appDomain)) { // If key exists, it will be in the _dictRep (but possibly overridden) updateDictRep(self); } } __CFUnlock(&__CFApplicationPreferencesLock); }
void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences *self, CFPreferencesDomainRef domain) { CFIndex idx; CFRange range; __CFLock(&__CFApplicationPreferencesLock); range.location = 0; range.length = CFArrayGetCount(self->_search); while ((idx = CFArrayGetFirstIndexOfValue(self->_search, range, domain)) != kCFNotFound) { CFArrayRemoveValueAtIndex(self->_search, idx); range.location = idx; range.length = range.length - idx - 1; } updateDictRep(self); __CFUnlock(&__CFApplicationPreferencesLock); }
static CFDictionaryRef copyXMLDomainDictionary(CFTypeRef context, void *xmlDomain) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFDictionaryRef result; __CFLock(&domain->_lock); if(!domain->_domainDict) { _loadXMLDomainIfStale((CFURLRef)context, domain); } result = (CFDictionaryRef)CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), domain->_domainDict, kCFPropertyListImmutable); __CFUnlock(&domain->_lock); return result; }
void _CFApplicationPreferencesSet(_CFApplicationPreferences *self, CFStringRef defaultName, CFTypeRef value) { CFPreferencesDomainRef applicationDomain; __CFLock(&__CFApplicationPreferencesLock); applicationDomain = _CFPreferencesStandardDomain(self->_appName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if(applicationDomain) { _CFPreferencesDomainSet(applicationDomain, defaultName, value); if (CFArrayContainsValue(self->_search, CFRangeMake(0, CFArrayGetCount(self->_search)), applicationDomain)) { // Expensive; can't we just check the relevant value throughout the appropriate sets of domains? -- REW, 7/19/99 updateDictRep(self); } } __CFUnlock(&__CFApplicationPreferencesLock); }
void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences *appPrefs, CFStringRef suiteName) { CFPreferencesDomainRef domain; __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesAnyHost); __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); __CFLock(&__CFApplicationPreferencesLock); domain = _CFPreferencesStandardDomain(suiteName, kCFPreferencesAnyUser, kCFPreferencesCurrentHost); __CFUnlock(&__CFApplicationPreferencesLock); if (domain) _CFApplicationPreferencesRemoveDomain(appPrefs, domain); }
// Exclusively for Foundation's use void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences *appPrefs, CFStringRef appName) { __CFLock(&__CFApplicationPreferencesLock); if (!__CFStandardUserPreferences) { __CFStandardUserPreferences = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeDictionaryKeyCallBacks, NULL); CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs); __CFUnlock(&__CFApplicationPreferencesLock); } else { _CFApplicationPreferences *oldPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName); CFDictionarySetValue(__CFStandardUserPreferences, appName, appPrefs); __CFUnlock(&__CFApplicationPreferencesLock); if (oldPrefs) { _CFDeallocateApplicationPreferences(oldPrefs); } } }
static void createPair(CFAllocatorRef alloc, CFStringRef host, UInt32 port, CFSocketNativeHandle sock, const CFSocketSignature* sig, CFReadStreamRef *readStream, CFWriteStreamRef *writeStream) { if (readStream) *readStream = NULL; if (writeStream) *writeStream = NULL; __CFLock(&(CFNetworkSupport.lock)); if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport(); __CFUnlock(&(CFNetworkSupport.lock)); CFNETWORK_CALL(_CFSocketStreamCreatePair, (alloc, host, port, sock, sig, readStream, writeStream)); }
static void __CFMessagePortDeallocate(CFTypeRef cf) { CFMessagePortRef ms = (CFMessagePortRef)cf; __CFMessagePortSetIsDeallocing(ms); CFMessagePortInvalidate(ms); // Delay cleanup of _replies until here so that invalidation during // SendRequest does not cause _replies to disappear out from under that function. if (NULL != ms->_replies) { CFRelease(ms->_replies); } if (NULL != ms->_name) { CFRelease(ms->_name); } if (NULL != ms->_port) { if (__CFMessagePortExtraMachRef(ms)) { mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_SEND, -1); mach_port_mod_refs(mach_task_self(), CFMachPortGetPort(ms->_port), MACH_PORT_RIGHT_RECEIVE, -1); } CFMachPortInvalidate(ms->_port); CFRelease(ms->_port); } // A remote message port for a local message port in the same process will get the // same mach port, and the remote port will keep the mach port from being torn down, // thus keeping the remote port from getting any sort of death notification and // auto-invalidating; so we manually implement the 'auto-invalidation' here by // tickling each remote port to check its state after any message port is destroyed, // but most importantly after local message ports are destroyed. __CFLock(&__CFAllMessagePortsLock); CFMessagePortRef *remotePorts = NULL; CFIndex cnt = 0; if (NULL != __CFAllRemoteMessagePorts) { cnt = CFDictionaryGetCount(__CFAllRemoteMessagePorts); remotePorts = CFAllocatorAllocate(kCFAllocatorSystemDefault, cnt * sizeof(CFMessagePortRef), __kCFAllocatorGCScannedMemory); CFDictionaryGetKeysAndValues(__CFAllRemoteMessagePorts, NULL, (const void **)remotePorts); for (CFIndex idx = 0; idx < cnt; idx++) { CFRetain(remotePorts[idx]); } } __CFUnlock(&__CFAllMessagePortsLock); if (remotePorts) { for (CFIndex idx = 0; idx < cnt; idx++) { // as a side-effect, this will auto-invalidate the CFMessagePort if the CFMachPort is invalid CFMessagePortIsValid(remotePorts[idx]); CFRelease(remotePorts[idx]); } CFAllocatorDeallocate(kCFAllocatorSystemDefault, remotePorts); } }
static Boolean synchronizeXMLDomain(CFTypeRef context, void *xmlDomain) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFMutableDictionaryRef cachedDict; CFMutableArrayRef changedKeys; SInt32 idx, count; Boolean success, tryAgain; __CFLock(&domain->_lock); cachedDict = domain->_domainDict; changedKeys = domain->_dirtyKeys; count = CFArrayGetCount(changedKeys); if (count == 0) { // no changes were made to this domain; just remove it from the cache to guarantee it will be taken from disk next access if (cachedDict) { CFRelease(cachedDict); domain->_domainDict = NULL; } __CFUnlock(&domain->_lock); return true; } domain->_domainDict = NULL; // This forces a reload. Note that we now have a retain on cachedDict do { _loadXMLDomainIfStale((CFURLRef )context, domain); // now cachedDict holds our changes; domain->_domainDict has the latest version from the disk for (idx = 0; idx < count; idx ++) { CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(changedKeys, idx); CFTypeRef value = CFDictionaryGetValue(cachedDict, key); if (value) CFDictionarySetValue(domain->_domainDict, key, value); else CFDictionaryRemoveValue(domain->_domainDict, key); } success = _writeXMLFile((CFURLRef )context, domain->_domainDict, domain->_isWorldReadable, &tryAgain); if (tryAgain) { __CFMilliSleep(50); } } while (tryAgain); CFRelease(cachedDict); if (success) { CFArrayRemoveAllValues(domain->_dirtyKeys); } domain->_lastReadTime = CFAbsoluteTimeGetCurrent(); __CFUnlock(&domain->_lock); return success; }
Boolean CFPreferencesAppSynchronize(CFStringRef appName) { _CFApplicationPreferences *standardPrefs; Boolean result; CFAssert1(appName != NULL, __kCFLogAssertion, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__); // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize __CFLock(&__CFApplicationPreferencesLock); if (__CFStandardUserPreferences) { standardPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName); } else { standardPrefs = NULL; } result = standardPrefs ? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs) : _CFSynchronizeDomainCache(); __CFUnlock(&__CFApplicationPreferencesLock); return result; }
void _CFDeallocateApplicationPreferences(_CFApplicationPreferences *self) { CFAllocatorRef alloc = __CFPreferencesAllocator(); _CFApplicationPreferences *cachedPrefs = NULL; __CFLock(&__CFApplicationPreferencesLock); // Get us out of the cache before destroying! if (__CFStandardUserPreferences) { cachedPrefs = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, self->_appName); } if (cachedPrefs == self) { CFDictionaryRemoveValue(__CFStandardUserPreferences, self->_appName); } if (self->_dictRep) CFRelease(self->_dictRep); CFRelease(self->_search); CFRelease(self->_appName); CFAllocatorDeallocate(alloc, self); __CFUnlock(&__CFApplicationPreferencesLock); }
static void writeXMLValue(CFTypeRef context, void *xmlDomain, CFStringRef key, CFTypeRef value) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; const void *existing = NULL; __CFLock(&domain->_lock); if (domain->_domainDict == NULL) { _loadXMLDomainIfStale((CFURLRef )context, domain); } // check to see if the value is the same // if (1) the key is present AND value is !NULL and equal to existing, do nothing, or // if (2) the key is not present AND value is NULL, do nothing // these things are no-ops, and should not dirty the domain if (CFDictionaryGetValueIfPresent(domain->_domainDict, key, &existing)) { if (NULL != value && (existing == value || CFEqual(existing, value))) { __CFUnlock(&domain->_lock); return; } } else { if (NULL == value) { __CFUnlock(&domain->_lock); return; } } // We must append first so key gets another retain (in case we're // about to remove it from the dictionary, and that's the sole reference) // This should be a set not an array. if (!CFArrayContainsValue(domain->_dirtyKeys, CFRangeMake(0, CFArrayGetCount(domain->_dirtyKeys)), key)) { CFArrayAppendValue(domain->_dirtyKeys, key); } if (value) { // Must copy for two reasons - we don't want mutable objects in the cache, and we don't want objects allocated from a different allocator in the cache. CFTypeRef newValue = CFPropertyListCreateDeepCopy(__CFPreferencesAllocator(), value, kCFPropertyListImmutable); CFDictionarySetValue(domain->_domainDict, key, newValue); CFRelease(newValue); } else { CFDictionaryRemoveValue(domain->_domainDict, key); } __CFUnlock(&domain->_lock); }
CF_PRIVATE _CFApplicationPreferences *_CFStandardApplicationPreferences(CFStringRef appName) { _CFApplicationPreferences *appPreferences; // CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication"); __CFLock(&__CFApplicationPreferencesLock); if (!__CFStandardUserPreferences) { __CFStandardUserPreferences = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, & kCFTypeDictionaryKeyCallBacks, NULL); } if (!__CFStandardUserPreferences) { // Couldn't create __CFUnlock(&__CFApplicationPreferencesLock); return NULL; } if ((appPreferences = (_CFApplicationPreferences *)CFDictionaryGetValue(__CFStandardUserPreferences, appName)) == NULL ) { appPreferences = _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser, appName); CFDictionarySetValue(__CFStandardUserPreferences, appName, appPreferences); __CFUnlock(&__CFApplicationPreferencesLock); _CFApplicationPreferencesSetStandardSearchList(appPreferences); } else { __CFUnlock(&__CFApplicationPreferencesLock); } return appPreferences; }
// quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain. void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain) { CFAllocatorRef alloc = __CFPreferencesAllocator(); __CFLock(&__CFApplicationPreferencesLock); if(__CFStandardUserPreferences) { // only grovel over the prefs if there's something there to grovel _CFApplicationPreferences **prefsArray, *prefsBuf[32]; CFIndex idx, count = CFDictionaryGetCount(__CFStandardUserPreferences); if(count < 32) { prefsArray = prefsBuf; } else { prefsArray = (_CFApplicationPreferences **)CFAllocatorAllocate(alloc, count * sizeof(_CFApplicationPreferences *), 0); } CFDictionaryGetKeysAndValues(__CFStandardUserPreferences, NULL, (const void **)prefsArray); // For this operation, giving up the lock is the last thing we want to do, so use the modified flavor of _CFApplicationPreferencesContainsDomain for(idx = 0; idx < count; idx++) { _CFApplicationPreferences *appPrefs = prefsArray[idx]; if(_CFApplicationPreferencesContainsDomainNoLock(appPrefs, changedDomain)) { updateDictRep(appPrefs); } } if(prefsArray != prefsBuf) CFAllocatorDeallocate(alloc, prefsArray); } __CFUnlock(&__CFApplicationPreferencesLock); }
static void getXMLKeysAndValues(CFAllocatorRef alloc, CFTypeRef context, void *xmlDomain, void **buf[], CFIndex *numKeyValuePairs) { _CFXMLPreferencesDomain *domain = (_CFXMLPreferencesDomain *)xmlDomain; CFIndex count; __CFLock(&domain->_lock); if (!domain->_domainDict) { _loadXMLDomainIfStale((CFURLRef )context, domain); } count = CFDictionaryGetCount(domain->_domainDict); if (buf) { void **values; if (count <= *numKeyValuePairs) { values = *buf + count; CFDictionaryGetKeysAndValues(domain->_domainDict, (const void **)*buf, (const void **)values); } else if (alloc != kCFAllocatorNull) { *buf = (void**) CFAllocatorReallocate(alloc, (*buf ? *buf : NULL), count * 2 * sizeof(void *), 0); if (*buf) { values = *buf + count; CFDictionaryGetKeysAndValues(domain->_domainDict, (const void **)*buf, (const void **)values); } } } *numKeyValuePairs = count; __CFUnlock(&domain->_lock); }
CF_PRIVATE CFArrayRef _CFPreferencesCreateDomainList(CFStringRef userName, CFStringRef hostName) { CFAllocatorRef prefAlloc = __CFPreferencesAllocator(); CFArrayRef domains; CFMutableArrayRef marray; CFStringRef *cachedDomainKeys; CFPreferencesDomainRef *cachedDomains; SInt32 idx, cnt; CFStringRef suffix; UInt32 suffixLen; CFURLRef prefDir = _preferencesDirectoryForUserHost(userName, hostName); if (!prefDir) { return NULL; } if (hostName == kCFPreferencesAnyHost) { suffix = CFStringCreateWithCString(prefAlloc, ".plist", kCFStringEncodingASCII); } else if (hostName == kCFPreferencesCurrentHost) { CFStringRef hostID = _CFPreferencesGetByHostIdentifierString(); suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostID); } else { suffix = CFStringCreateWithFormat(prefAlloc, NULL, CFSTR(".%@.plist"), hostName); // sketchy - this allows someone to create a domain list for an arbitrary hostname. } suffixLen = CFStringGetLength(suffix); domains = (CFArrayRef)CFURLCreatePropertyFromResource(prefAlloc, prefDir, kCFURLFileDirectoryContents, NULL); CFRelease(prefDir); if (domains){ marray = CFArrayCreateMutableCopy(prefAlloc, 0, domains); CFRelease(domains); } else { marray = CFArrayCreateMutable(prefAlloc, 0, & kCFTypeArrayCallBacks); } for (idx = CFArrayGetCount(marray)-1; idx >= 0; idx --) { CFURLRef url = (CFURLRef)CFArrayGetValueAtIndex(marray, idx); CFStringRef string = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); if (!CFStringHasSuffix(string, suffix)) { CFArrayRemoveValueAtIndex(marray, idx); } else { CFStringRef dom = CFStringCreateWithSubstring(prefAlloc, string, CFRangeMake(0, CFStringGetLength(string) - suffixLen)); if (CFEqual(dom, CFSTR(".GlobalPreferences"))) { CFArraySetValueAtIndex(marray, idx, kCFPreferencesAnyApplication); } else { CFArraySetValueAtIndex(marray, idx, dom); } CFRelease(dom); } CFRelease(string); } CFRelease(suffix); // Now add any domains added in the cache; delete any that have been deleted in the cache __CFLock(&domainCacheLock); if (!domainCache) { __CFUnlock(&domainCacheLock); return marray; } cnt = CFDictionaryGetCount(domainCache); cachedDomainKeys = (CFStringRef *)CFAllocatorAllocate(prefAlloc, 2 * cnt * sizeof(CFStringRef), 0); cachedDomains = (CFPreferencesDomainRef *)(cachedDomainKeys + cnt); CFDictionaryGetKeysAndValues(domainCache, (const void **)cachedDomainKeys, (const void **)cachedDomains); __CFUnlock(&domainCacheLock); suffix = _CFPreferencesCachePrefixForUserHost(userName, hostName); suffixLen = CFStringGetLength(suffix); for (idx = 0; idx < cnt; idx ++) { CFStringRef domainKey = cachedDomainKeys[idx]; CFPreferencesDomainRef domain = cachedDomains[idx]; CFStringRef domainName; CFIndex keyCount = 0; if (!CFStringHasPrefix(domainKey, suffix)) continue; domainName = CFStringCreateWithSubstring(prefAlloc, domainKey, CFRangeMake(suffixLen, CFStringGetLength(domainKey) - suffixLen)); if (CFEqual(domainName, CFSTR("*"))) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(kCFPreferencesAnyApplication); } else if (CFEqual(domainName, kCFPreferencesCurrentApplication)) { CFRelease(domainName); domainName = (CFStringRef)CFRetain(_CFProcessNameString()); } CFDictionaryRef d = _CFPreferencesDomainDeepCopyDictionary(domain); keyCount = d ? CFDictionaryGetCount(d) : 0; if (keyCount) CFRelease(d); if (keyCount == 0) { // Domain was deleted SInt32 firstIndexOfValue = CFArrayGetFirstIndexOfValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName); if (0 <= firstIndexOfValue) { CFArrayRemoveValueAtIndex(marray, firstIndexOfValue); } } else if (!CFArrayContainsValue(marray, CFRangeMake(0, CFArrayGetCount(marray)), domainName)) { CFArrayAppendValue(marray, domainName); } CFRelease(domainName); } CFRelease(suffix); CFAllocatorDeallocate(prefAlloc, cachedDomainKeys); return marray; }