#include <unistd.h>
#include "configd.h"
#include "session.h"
static Boolean
isMySessionKey(CFStringRef sessionKey, CFStringRef key)
{
CFDictionaryRef dict;
CFStringRef storeSessionKey;
dict = CFDictionaryGetValue(storeData, key);
if (!dict) {
return FALSE;
}
storeSessionKey = CFDictionaryGetValue(dict, kSCDSession);
if (!storeSessionKey) {
return FALSE;
}
if (!CFEqual(sessionKey, storeSessionKey)) {
return FALSE;
}
return TRUE;
}
static void
removeAllKeys(SCDynamicStoreRef store, Boolean isRegex)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
CFArrayRef keys;
CFIndex n;
keys = isRegex ? storePrivate->patterns : storePrivate->keys;
n = (keys != NULL) ? CFArrayGetCount(keys) : 0;
if (n > 0) {
CFIndex i;
CFArrayRef keysToRemove;
keysToRemove = CFArrayCreateCopy(NULL, keys);
for (i = 0; i < n; i++) {
(void) __SCDynamicStoreRemoveWatchedKey(store,
CFArrayGetValueAtIndex(keysToRemove, i),
isRegex,
TRUE);
}
CFRelease(keysToRemove);
}
return;
}
__private_extern__
int
__SCDynamicStoreClose(SCDynamicStoreRef *store)
{
CFDictionaryRef dict;
CFArrayRef keys;
CFIndex keyCnt;
serverSessionRef mySession;
CFStringRef sessionKey;
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store;
SC_trace(_configd_trace, "close : %5d\n",
storePrivate->server);
removeAllKeys(*store, FALSE); removeAllKeys(*store, TRUE);
__MACH_PORT_DEBUG(storePrivate->notifyPort != MACH_PORT_NULL, "*** __SCDynamicStoreClose", storePrivate->notifyPort);
(void) __SCDynamicStoreNotifyCancel(*store);
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server);
dict = CFDictionaryGetValue(sessionData, sessionKey);
keys = CFDictionaryGetValue(dict, kSCDSessionKeys);
if (keys && ((keyCnt = CFArrayGetCount(keys)) > 0)) {
CFIndex i;
Boolean push = FALSE;
for (i = 0; i < keyCnt; i++) {
if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i))) {
(void) __SCDynamicStoreRemoveValue(*store, CFArrayGetValueAtIndex(keys, i), TRUE);
push = TRUE;
}
}
if (push) {
(void) __SCDynamicStorePush();
}
}
CFRelease(sessionKey);
mySession = getSession(storePrivate->server);
if (mySession->serverRunLoopSource) {
CFRunLoopSourceInvalidate(mySession->serverRunLoopSource);
CFRelease(mySession->serverRunLoopSource);
mySession->serverRunLoopSource = NULL;
}
if (mySession->serverPort != NULL) {
CFMachPortInvalidate(mySession->serverPort);
CFRelease(mySession->serverPort);
mySession->serverPort = NULL;
}
storePrivate->server = MACH_PORT_NULL;
CFRelease(*store);
*store = NULL;
return kSCStatusOK;
}