/* * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Modification History * * June 1, 2001 Allan Nathanson * - public API conversion * * June 2, 2000 Allan Nathanson * - initial revision */ #include "configd.h" __private_extern__ CFMutableDictionaryRef sessionData = NULL; __private_extern__ CFMutableDictionaryRef storeData = NULL; __private_extern__ CFMutableDictionaryRef storeData_s = NULL; __private_extern__ CFMutableDictionaryRef patternData = NULL; __private_extern__ CFMutableDictionaryRef patternData_s = NULL; __private_extern__ CFMutableSetRef changedKeys = NULL; __private_extern__ CFMutableSetRef changedKeys_s = NULL; __private_extern__ CFMutableSetRef deferredRemovals = NULL; __private_extern__ CFMutableSetRef deferredRemovals_s = NULL; __private_extern__ CFMutableSetRef removedSessionKeys = NULL; __private_extern__ CFMutableSetRef removedSessionKeys_s = NULL; __private_extern__ CFMutableSetRef needsNotification = NULL; __private_extern__ int storeLocked = 0; /* > 0 if dynamic store locked */ __private_extern__ void _swapLockedStoreData() { void *temp; temp = storeData; storeData = storeData_s; storeData_s = temp; temp = patternData; patternData = patternData_s; patternData_s = temp; temp = changedKeys; changedKeys = changedKeys_s; changedKeys_s = temp; temp = deferredRemovals; deferredRemovals = deferredRemovals_s; deferredRemovals_s = temp; temp = removedSessionKeys; removedSessionKeys = removedSessionKeys_s; removedSessionKeys_s = temp; return; } __private_extern__ void _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) { CFDictionaryRef dict; CFMutableDictionaryRef newDict; CFArrayRef watchers; CFMutableArrayRef newWatchers; CFArrayRef watcherRefs; CFMutableArrayRef newWatcherRefs; CFIndex i; int refCnt; CFNumberRef refNum; /* * Get the dictionary associated with this key out of the store */ dict = CFDictionaryGetValue(storeData, watchedKey); if (dict) { newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); } else { newDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } /* * Get the set of watchers out of the keys dictionary */ watchers = CFDictionaryGetValue(newDict, kSCDWatchers); watcherRefs = CFDictionaryGetValue(newDict, kSCDWatcherRefs); if (watchers) { newWatchers = CFArrayCreateMutableCopy(NULL, 0, watchers); newWatcherRefs = CFArrayCreateMutableCopy(NULL, 0, watcherRefs); } else { newWatchers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); newWatcherRefs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } /* * Add my session to the set of watchers */ i = CFArrayGetFirstIndexOfValue(newWatchers, CFRangeMake(0, CFArrayGetCount(newWatchers)), sessionNum); if (i == -1) { /* if this is the first instance of this session watching this key */ CFArrayAppendValue(newWatchers, sessionNum); refCnt = 1; refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt); CFArrayAppendValue(newWatcherRefs, refNum); CFRelease(refNum); } else { /* if this is another instance of this session watching this key */ refNum = CFArrayGetValueAtIndex(newWatcherRefs, i); CFNumberGetValue(refNum, kCFNumberIntType, &refCnt); refCnt++; refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt); CFArraySetValueAtIndex(newWatcherRefs, i, refNum); CFRelease(refNum); } /* * Update the keys dictionary */ CFDictionarySetValue(newDict, kSCDWatchers, newWatchers); CFRelease(newWatchers); CFDictionarySetValue(newDict, kSCDWatcherRefs, newWatcherRefs); CFRelease(newWatcherRefs); /* * Update the store for this key */ CFDictionarySetValue(storeData, watchedKey, newDict); CFRelease(newDict); SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _addWatcher: %@, %@"), sessionNum, watchedKey); return; } __private_extern__ void _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey) { CFDictionaryRef dict; CFMutableDictionaryRef newDict; CFArrayRef watchers; CFMutableArrayRef newWatchers; CFArrayRef watcherRefs; CFMutableArrayRef newWatcherRefs; CFIndex i; int refCnt; CFNumberRef refNum; /* * Get the dictionary associated with this key out of the store */ dict = CFDictionaryGetValue(storeData, watchedKey); if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) { /* key doesn't exist (isn't this really fatal?) */ SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, key not watched"), sessionNum, watchedKey); return; } newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); /* * Get the set of watchers out of the keys dictionary and * remove this session from the list. */ watchers = CFDictionaryGetValue(newDict, kSCDWatchers); newWatchers = CFArrayCreateMutableCopy(NULL, 0, watchers); watcherRefs = CFDictionaryGetValue(newDict, kSCDWatcherRefs); newWatcherRefs = CFArrayCreateMutableCopy(NULL, 0, watcherRefs); /* locate the session reference */ i = CFArrayGetFirstIndexOfValue(newWatchers, CFRangeMake(0, CFArrayGetCount(newWatchers)), sessionNum); if (i == -1) { SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, session not watching"), sessionNum, watchedKey); CFRelease(newDict); CFRelease(newWatchers); CFRelease(newWatcherRefs); return; } /* remove one session reference */ refNum = CFArrayGetValueAtIndex(newWatcherRefs, i); CFNumberGetValue(refNum, kCFNumberIntType, &refCnt); if (--refCnt > 0) { refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt); CFArraySetValueAtIndex(newWatcherRefs, i, refNum); CFRelease(refNum); } else { /* if this was the last reference */ CFArrayRemoveValueAtIndex(newWatchers, i); CFArrayRemoveValueAtIndex(newWatcherRefs, i); } if (CFArrayGetCount(newWatchers) > 0) { /* if this key is still being "watched" */ CFDictionarySetValue(newDict, kSCDWatchers, newWatchers); CFDictionarySetValue(newDict, kSCDWatcherRefs, newWatcherRefs); } else { /* no watchers left, remove the empty set */ CFDictionaryRemoveValue(newDict, kSCDWatchers); CFDictionaryRemoveValue(newDict, kSCDWatcherRefs); } CFRelease(newWatchers); CFRelease(newWatcherRefs); if (CFDictionaryGetCount(newDict) > 0) { /* if this key is still active */ CFDictionarySetValue(storeData, watchedKey, newDict); } else { /* no information left, remove the empty dictionary */ CFDictionaryRemoveValue(storeData, watchedKey); } CFRelease(newDict); SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@"), sessionNum, watchedKey); return; }