#include "configd.h"
CFMutableDictionaryRef sessionData = NULL;
CFMutableDictionaryRef storeData = NULL;
CFMutableDictionaryRef storeData_s = NULL;
CFMutableSetRef changedKeys = NULL;
CFMutableSetRef changedKeys_s = NULL;
CFMutableSetRef deferredRemovals = NULL;
CFMutableSetRef deferredRemovals_s = NULL;
CFMutableSetRef removedSessionKeys = NULL;
CFMutableSetRef removedSessionKeys_s = NULL;
CFMutableSetRef needsNotification = NULL;
int storeLocked = 0;
void
_swapLockedStoreData()
{
void *temp;
temp = storeData;
storeData = storeData_s;
storeData_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;
}
void
_addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
{
CFDictionaryRef dict;
CFMutableDictionaryRef newDict;
CFArrayRef watchers;
CFMutableArrayRef newWatchers;
CFArrayRef watcherRefs;
CFMutableArrayRef newWatcherRefs;
CFIndex i;
int refCnt;
CFNumberRef refNum;
dict = CFDictionaryGetValue(storeData, watchedKey);
if (dict) {
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
} else {
newDict = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
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);
}
i = CFArrayGetFirstIndexOfValue(newWatchers,
CFRangeMake(0, CFArrayGetCount(newWatchers)),
sessionNum);
if (i == -1) {
CFArrayAppendValue(newWatchers, sessionNum);
refCnt = 1;
refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt);
CFArrayAppendValue(newWatcherRefs, refNum);
CFRelease(refNum);
} else {
refNum = CFArrayGetValueAtIndex(newWatcherRefs, i);
CFNumberGetValue(refNum, kCFNumberIntType, &refCnt);
refCnt++;
refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt);
CFArraySetValueAtIndex(newWatcherRefs, i, refNum);
CFRelease(refNum);
}
CFDictionarySetValue(newDict, kSCDWatchers, newWatchers);
CFRelease(newWatchers);
CFDictionarySetValue(newDict, kSCDWatcherRefs, newWatcherRefs);
CFRelease(newWatcherRefs);
CFDictionarySetValue(storeData, watchedKey, newDict);
CFRelease(newDict);
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _addWatcher: %@, %@"), sessionNum, watchedKey);
return;
}
void
_addRegexWatcherByKey(const void *key, void *val, void *context)
{
CFStringRef storeStr = key;
CFDictionaryRef info = val;
mach_port_t sessionID = ((addContextRef)context)->store->server;
regex_t *preg = ((addContextRef)context)->preg;
int storeKeyLen;
char *storeKey;
CFNumberRef sessionNum;
int reError;
char reErrBuf[256];
int reErrStrLen;
if (!CFDictionaryContainsKey(info, kSCDData)) {
return;
}
storeKeyLen = CFStringGetLength(storeStr) + 1;
storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0);
if (!CFStringGetCString(storeStr, storeKey, storeKeyLen, kCFStringEncodingMacRoman)) {
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert store key to C string"));
CFAllocatorDeallocate(NULL, storeKey);
return;
}
reError = regexec(preg, storeKey, 0, NULL, 0);
switch (reError) {
case 0 :
sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionID);
_addWatcher(sessionNum, storeStr);
CFRelease(sessionNum);
break;
case REG_NOMATCH :
break;
default :
reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
break;
}
CFAllocatorDeallocate(NULL, storeKey);
}
void
_addRegexWatchersBySession(const void *key, void *val, void *context)
{
CFStringRef sessionKey = key;
CFDictionaryRef info = val;
CFStringRef addedKey = context;
CFIndex newKeyLen;
char *newKeyStr;
CFArrayRef rKeys;
CFArrayRef rData;
CFIndex i;
rKeys = CFDictionaryGetValue(info, kSCDRegexKeys);
if (rKeys == NULL) {
return;
}
rData = CFDictionaryGetValue(info, kSCDRegexData);
newKeyLen = CFStringGetLength(addedKey) + 1;
newKeyStr = CFAllocatorAllocate(NULL, newKeyLen, 0);
if (!CFStringGetCString(addedKey, newKeyStr, newKeyLen, kCFStringEncodingMacRoman)) {
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert new key to C string"));
CFAllocatorDeallocate(NULL, newKeyStr);
return;
}
for (i=0; i<CFArrayGetCount(rKeys); i++) {
CFDataRef regexData = CFArrayGetValueAtIndex(rData, i);
regex_t *preg = (regex_t *)CFDataGetBytePtr(regexData);
int reError;
char reErrBuf[256];
int reErrStrLen;
SInt32 sessionInt;
CFNumberRef sessionNum;
reError = regexec(preg, newKeyStr, 0, NULL, 0);
switch (reError) {
case 0 :
sessionInt = CFStringGetIntValue(sessionKey);
sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionInt);
_addWatcher(sessionNum, addedKey);
CFRelease(sessionNum);
break;
case REG_NOMATCH :
break;
default :
reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
break;
}
}
CFAllocatorDeallocate(NULL, newKeyStr);
return;
}
void
_removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
{
CFDictionaryRef dict;
CFMutableDictionaryRef newDict;
CFArrayRef watchers;
CFMutableArrayRef newWatchers;
CFArrayRef watcherRefs;
CFMutableArrayRef newWatcherRefs;
CFIndex i;
int refCnt;
CFNumberRef refNum;
dict = CFDictionaryGetValue(storeData, watchedKey);
if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) {
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, key not watched"), sessionNum, watchedKey);
return;
}
newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
watchers = CFDictionaryGetValue(newDict, kSCDWatchers);
newWatchers = CFArrayCreateMutableCopy(NULL, 0, watchers);
watcherRefs = CFDictionaryGetValue(newDict, kSCDWatcherRefs);
newWatcherRefs = CFArrayCreateMutableCopy(NULL, 0, watcherRefs);
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;
}
refNum = CFArrayGetValueAtIndex(newWatcherRefs, i);
CFNumberGetValue(refNum, kCFNumberIntType, &refCnt);
if (--refCnt > 0) {
refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt);
CFArraySetValueAtIndex(newWatcherRefs, i, refNum);
CFRelease(refNum);
} else {
CFArrayRemoveValueAtIndex(newWatchers, i);
CFArrayRemoveValueAtIndex(newWatcherRefs, i);
}
if (CFArrayGetCount(newWatchers) > 0) {
CFDictionarySetValue(newDict, kSCDWatchers, newWatchers);
CFDictionarySetValue(newDict, kSCDWatcherRefs, newWatcherRefs);
} else {
CFDictionaryRemoveValue(newDict, kSCDWatchers);
CFDictionaryRemoveValue(newDict, kSCDWatcherRefs);
}
CFRelease(newWatchers);
CFRelease(newWatcherRefs);
if (CFDictionaryGetCount(newDict) > 0) {
CFDictionarySetValue(storeData, watchedKey, newDict);
} else {
CFDictionaryRemoveValue(storeData, watchedKey);
}
CFRelease(newDict);
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@"), sessionNum, watchedKey);
return;
}
void
_removeRegexWatcherByKey(const void *key, void *val, void *context)
{
CFStringRef storeStr = key;
CFDictionaryRef info = val;
mach_port_t sessionID = ((removeContextRef)context)->store->server;
regex_t *preg = ((removeContextRef)context)->preg;
CFNumberRef sessionNum;
CFArrayRef watchers;
int storeKeyLen;
char *storeKey;
int reError;
char reErrBuf[256];
int reErrStrLen;
if (CFDictionaryContainsKey(info, kSCDWatchers) == FALSE) {
return;
}
sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionID);
watchers = CFDictionaryGetValue(info, kSCDWatchers);
if (CFArrayContainsValue(watchers,
CFRangeMake(0, CFArrayGetCount(watchers)),
sessionNum) == FALSE) {
CFRelease(sessionNum);
return;
}
storeKeyLen = CFStringGetLength(storeStr) + 1;
storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0);
if (!CFStringGetCString(storeStr, storeKey, storeKeyLen, kCFStringEncodingMacRoman)) {
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert key to C string"));
CFAllocatorDeallocate(NULL, storeKey);
CFRelease(sessionNum);
return;
}
reError = regexec(preg, storeKey, 0, NULL, 0);
switch (reError) {
case 0 :
_removeWatcher(sessionNum, storeStr);
break;
case REG_NOMATCH :
break;
default :
reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
break;
}
CFAllocatorDeallocate(NULL, storeKey);
CFRelease(sessionNum);
}
void
_removeRegexWatchersBySession(const void *key, void *val, void *context)
{
CFStringRef sessionKey = key;
CFDictionaryRef info = val;
CFStringRef removedKey = context;
CFIndex oldKeyLen;
char *oldKeyStr;
CFArrayRef rKeys;
CFArrayRef rData;
CFIndex i;
rKeys = CFDictionaryGetValue(info, kSCDRegexKeys);
if (rKeys == NULL) {
return;
}
rData = CFDictionaryGetValue(info, kSCDRegexData);
oldKeyLen = CFStringGetLength(removedKey) + 1;
oldKeyStr = CFAllocatorAllocate(NULL, oldKeyLen, 0);
if (!CFStringGetCString(removedKey, oldKeyStr, oldKeyLen, kCFStringEncodingMacRoman)) {
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert old key to C string"));
CFAllocatorDeallocate(NULL, oldKeyStr);
return;
}
for (i=0; i<CFArrayGetCount(rKeys); i++) {
CFDataRef regexData = CFArrayGetValueAtIndex(rData, i);
regex_t *preg = (regex_t *)CFDataGetBytePtr(regexData);
int reError;
char reErrBuf[256];
int reErrStrLen;
SInt32 sessionInt;
CFNumberRef sessionNum;
reError = regexec(preg, oldKeyStr, 0, NULL, 0);
switch (reError) {
case 0 :
sessionInt = CFStringGetIntValue(sessionKey);
sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &sessionInt);
_removeWatcher(sessionNum, removedKey);
CFRelease(sessionNum);
break;
case REG_NOMATCH :
break;
default :
reErrStrLen = regerror(reError, preg, reErrBuf, sizeof(reErrBuf));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
break;
}
}
CFAllocatorDeallocate(NULL, oldKeyStr);
return;
}