/* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #define SYSTEMCONFIGURATION_NEW_API #include #define USE_FLAT_FILES "UseFlatFiles" SCDSessionRef session = NULL; CFMutableSetRef curCacheKeys = NULL; /* previous cache keys */ CFMutableSetRef newCacheKeys = NULL; /* cache keys which reflect current config */ CFIndex keyCnt; static void updateCache(const void *key, const void *value, void *context) { CFStringRef configKey = (CFStringRef)key; CFPropertyListRef configData = (CFDictionaryRef)value; SCDStatus scd_status; SCDHandleRef handle; CFPropertyListRef cacheData; scd_status = SCDGet(session, configKey, &handle); switch (scd_status) { case SCD_OK : /* key exists, compare old & new dictionaries */ cacheData = SCDHandleGetData(handle); if (!CFEqual(cacheData, configData)) { /* data has changed */ SCDHandleSetData(handle, configData); scd_status = SCDSet(session, configKey, handle); if (scd_status != SCD_OK) { SCDLog(LOG_ERR, CFSTR("SCDSet(): %s"), SCDError(scd_status)); } } SCDHandleRelease(handle); break; case SCD_NOKEY : /* key does not exist, this is a new interface or domain */ handle = SCDHandleInit(); SCDHandleSetData(handle, configData); scd_status = SCDAdd(session, configKey, handle); SCDHandleRelease(handle); if (scd_status != SCD_OK) { SCDLog(LOG_ERR, CFSTR("SCDSet(): %s"), SCDError(scd_status)); } break; default : /* some other error */ SCDLog(LOG_ERR, CFSTR("SCDGet(): %s"), SCDError(scd_status)); break; } CFSetRemoveValue(curCacheKeys, configKey); CFSetAddValue (newCacheKeys, configKey); return; } void removeCacheKey(const void *value, void *context) { SCDStatus scd_status; CFStringRef configKey = (CFStringRef)value; scd_status = SCDRemove(session, configKey); if ((scd_status != SCD_OK) && (scd_status != SCD_NOKEY)) { SCDLog(LOG_ERR, CFSTR("SCDRemove() failed: %s"), SCDError(scd_status)); } return; } static void flatten(SCPSessionRef pSession, CFStringRef key, CFDictionaryRef base, CFMutableDictionaryRef newPreferences) { CFDictionaryRef subset; CFStringRef link; CFMutableDictionaryRef myDict; CFStringRef myKey; CFIndex i; CFIndex nKeys; void **keys; void **vals; if (!CFDictionaryGetValueIfPresent(base, kSCResvLink, (void **)&link)) { /* if this dictionary is not linked */ subset = base; } else { /* if __LINK__ key is present */ SCPStatus scp_status; scp_status = SCPPathGetValue(pSession, link, &subset); if (scp_status != SCP_OK) { /* if error with link */ SCDLog(LOG_ERR, CFSTR("SCPPathGetValue(,%@,) failed: %s"), link, SCPError(scp_status)); return; } } if (CFDictionaryContainsKey(subset, kSCResvInactive)) { /* if __INACTIVE__ key is present */ return; } myKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), kSCCacheDomainSetup, key); myDict = (CFMutableDictionaryRef)CFDictionaryGetValue(newPreferences, myKey); if (myDict == NULL) { myDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } else { myDict = CFDictionaryCreateMutableCopy(NULL, 0, (CFDictionaryRef)myDict); } nKeys = CFDictionaryGetCount(subset); keys = CFAllocatorAllocate(NULL, nKeys * sizeof(CFStringRef) , 0); vals = CFAllocatorAllocate(NULL, nKeys * sizeof(CFPropertyListRef), 0); CFDictionaryGetKeysAndValues(subset, keys, vals); for (i=0; i 0) { /* add this dictionary to the new preferences */ CFDictionarySetValue(newPreferences, myKey, myDict); } CFRelease(myDict); CFRelease(myKey); return; } static boolean_t updateConfiguration(SCDSessionRef session, void *arg) { CFArrayRef changedKeys; boolean_t cleanupKeys = TRUE; CFStringRef current = NULL; CFArrayRef currentKeys; CFDateRef date; CFMutableDictionaryRef dict; CFDictionaryRef global = NULL; boolean_t haveLock = FALSE; CFIndex i; CFMutableDictionaryRef newPreferences = NULL; /* new configuration preferences */ SCPSessionRef pSession = NULL; SCPStatus scp_status; CFDictionaryRef set = NULL; SCDStatus scd_status; SCDLog(LOG_DEBUG, CFSTR("updating configuration")); /* * Fetched the changed keys */ scd_status = SCDNotifierGetChanges(session, &changedKeys); if (scd_status == SCD_OK) { CFRelease(changedKeys); } else { SCDLog(LOG_ERR, CFSTR("SCDNotifierGetChanges() failed: %s"), SCDError(scd_status)); /* XXX need to do something more with this FATAL error XXXX */ } /* * initialize old/new configuration, ensure that we clean up any * existing cache keys */ curCacheKeys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); newCacheKeys = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks); scd_status = SCDList(session, kSCCacheDomainSetup, 0, ¤tKeys); if (scd_status != SCD_OK) { SCDLog(LOG_ERR, CFSTR("SCDList() failed: %s"), SCDError(scd_status)); goto error; } for (i=0; i