#include "configd.h"
#include "session.h"
static __inline__ void
my_CFDictionaryApplyFunction(CFDictionaryRef theDict,
CFDictionaryApplierFunction applier,
void *context)
{
CFAllocatorRef myAllocator;
CFDictionaryRef myDict;
myAllocator = CFGetAllocator(theDict);
myDict = CFDictionaryCreateCopy(myAllocator, theDict);
CFDictionaryApplyFunction(myDict, applier, context);
CFRelease(myDict);
return;
}
int
__SCDynamicStoreRemoveWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreRemoveWatchedKey:"));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" key = %@"), key);
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" isRegex = %s"), isRegex ? "TRUE" : "FALSE");
if (!store || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession;
}
if (isRegex) {
if (!CFSetContainsValue(storePrivate->reKeys, key))
return kSCStatusNoKey;
CFSetRemoveValue(storePrivate->reKeys, key);
} else {
if (!CFSetContainsValue(storePrivate->keys, key))
return kSCStatusNoKey;
CFSetRemoveValue(storePrivate->keys, key);
}
if (isRegex) {
CFStringRef sessionKey;
CFDictionaryRef info;
CFMutableDictionaryRef newInfo;
CFArrayRef rKeys;
CFMutableArrayRef newRKeys;
CFArrayRef rData;
CFMutableArrayRef newRData;
CFIndex i;
CFDataRef regexData;
removeContext context;
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
info = CFDictionaryGetValue(sessionData, sessionKey);
newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
rKeys = CFDictionaryGetValue(newInfo, kSCDRegexKeys);
newRKeys = CFArrayCreateMutableCopy(NULL, 0, rKeys);
rData = CFDictionaryGetValue(newInfo, kSCDRegexData);
newRData = CFArrayCreateMutableCopy(NULL, 0, rData);
i = CFArrayGetFirstIndexOfValue(newRKeys,
CFRangeMake(0, CFArrayGetCount(newRData)),
key);
regexData = CFArrayGetValueAtIndex(newRData, i);
context.store = storePrivate;
context.preg = (regex_t *)CFDataGetBytePtr(regexData);
my_CFDictionaryApplyFunction(storeData,
(CFDictionaryApplierFunction)_removeRegexWatcherByKey,
&context);
CFArrayRemoveValueAtIndex(newRKeys, i);
if (CFArrayGetCount(newRKeys) > 0) {
CFDictionarySetValue(newInfo, kSCDRegexKeys, newRKeys);
} else {
CFDictionaryRemoveValue(newInfo, kSCDRegexKeys);
}
CFRelease(newRKeys);
regfree((regex_t *)CFDataGetBytePtr(regexData));
CFArrayRemoveValueAtIndex(newRData, i);
if (CFArrayGetCount(newRData) > 0) {
CFDictionarySetValue(newInfo, kSCDRegexData, newRData);
} else {
CFDictionaryRemoveValue(newInfo, kSCDRegexData);
}
CFRelease(newRData);
CFDictionarySetValue(sessionData, sessionKey, newInfo);
CFRelease(newInfo);
CFRelease(sessionKey);
} else {
CFNumberRef sessionNum;
sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
_removeWatcher(sessionNum, key);
CFRelease(sessionNum);
}
return kSCStatusOK;
}
kern_return_t
_notifyremove(mach_port_t server,
xmlData_t keyRef,
mach_msg_type_number_t keyLen,
int isRegex,
int *sc_status
)
{
serverSessionRef mySession = getSession(server);
CFStringRef key;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Remove notification key for this session."));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
if (!_SCUnserialize((CFPropertyListRef *)&key, (void *)keyRef, keyLen)) {
*sc_status = kSCStatusFailed;
return KERN_SUCCESS;
}
if (!isA_CFString(key)) {
CFRelease(key);
*sc_status = kSCStatusInvalidArgument;
return KERN_SUCCESS;
}
*sc_status = __SCDynamicStoreRemoveWatchedKey(mySession->store, key, isRegex);
CFRelease(key);
return KERN_SUCCESS;
}