#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;
}
int
__SCDynamicStoreClose(SCDynamicStoreRef *store)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store;
CFIndex keyCnt;
CFStringRef sessionKey;
CFDictionaryRef dict;
CFArrayRef keys;
serverSessionRef mySession;
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("__SCDynamicStoreClose:"));
if ((*store == NULL) || (storePrivate->server == MACH_PORT_NULL)) {
return kSCStatusNoStoreSession;
}
keyCnt = CFSetGetCount(storePrivate->keys);
if (keyCnt > 0) {
const void **watchedKeys;
CFArrayRef keysToRemove;
CFIndex i;
watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
CFSetGetValues(storePrivate->keys, watchedKeys);
keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
CFAllocatorDeallocate(NULL, watchedKeys);
for (i=0; i<keyCnt; i++) {
(void) __SCDynamicStoreRemoveWatchedKey(*store,
CFArrayGetValueAtIndex(keysToRemove, i),
FALSE);
}
CFRelease(keysToRemove);
}
keyCnt = CFSetGetCount(storePrivate->reKeys);
if (keyCnt > 0) {
const void **watchedKeys;
CFArrayRef keysToRemove;
CFIndex i;
watchedKeys = CFAllocatorAllocate(NULL, keyCnt * sizeof(CFStringRef), 0);
CFSetGetValues(storePrivate->reKeys, watchedKeys);
keysToRemove = CFArrayCreate(NULL, watchedKeys, keyCnt, &kCFTypeArrayCallBacks);
CFAllocatorDeallocate(NULL, watchedKeys);
for (i=0; i<keyCnt; i++) {
(void) __SCDynamicStoreRemoveWatchedKey(*store,
CFArrayGetValueAtIndex(keysToRemove, i),
TRUE);
}
CFRelease(keysToRemove);
}
(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)) {
Boolean wasLocked;
CFIndex i;
wasLocked = (storeLocked > 0);
if (!wasLocked) {
(void) __SCDynamicStoreLock(*store, FALSE);
}
for (i=0; i<keyCnt; i++) {
if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i))) {
(void) __SCDynamicStoreRemoveValue(*store, CFArrayGetValueAtIndex(keys, i));
}
}
if (wasLocked) {
_swapLockedStoreData();
for (i=0; i<keyCnt; i++) {
if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i)))
(void) __SCDynamicStoreRemoveValue(*store, CFArrayGetValueAtIndex(keys, i));
}
_swapLockedStoreData();
}
}
CFRelease(sessionKey);
if (storePrivate->locked) {
(void) __SCDynamicStoreUnlock(*store, FALSE);
}
mySession = getSession(storePrivate->server);
if (mySession->serverRunLoopSource) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
mySession->serverRunLoopSource,
kCFRunLoopDefaultMode);
CFRelease(mySession->serverRunLoopSource);
}
CFMachPortInvalidate(mySession->serverPort);
CFRelease(mySession->serverPort);
storePrivate->server = MACH_PORT_NULL;
CFRelease(*store);
*store = NULL;
return kSCStatusOK;
}
kern_return_t
_configclose(mach_port_t server, int *sc_status)
{
serverSessionRef mySession = getSession(server);
SCLog(_configd_verbose, LOG_DEBUG, CFSTR("Close session."));
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
*sc_status = __SCDynamicStoreClose(&mySession->store);
if (*sc_status != kSCStatusOK) {
SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" __SCDynamicStoreClose(): %s"), SCErrorString(*sc_status));
return KERN_SUCCESS;
}
removeSession(server);
return KERN_SUCCESS;
}