1/* 2 * Copyright (c) 2000, 2001, 2003, 2004, 2006-2012 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Modification History 26 * 27 * June 1, 2001 Allan Nathanson <ajn@apple.com> 28 * - public API conversion 29 * 30 * March 24, 2000 Allan Nathanson <ajn@apple.com> 31 * - initial revision 32 */ 33 34#include <unistd.h> 35 36#include "configd.h" 37#include "session.h" 38 39static Boolean 40isMySessionKey(CFStringRef sessionKey, CFStringRef key) 41{ 42 CFDictionaryRef dict; 43 CFStringRef storeSessionKey; 44 45 dict = CFDictionaryGetValue(storeData, key); 46 if (!dict) { 47 /* if key no longer exists */ 48 return FALSE; 49 } 50 51 storeSessionKey = CFDictionaryGetValue(dict, kSCDSession); 52 if (!storeSessionKey) { 53 /* if this is not a session key */ 54 return FALSE; 55 } 56 57 if (!CFEqual(sessionKey, storeSessionKey)) { 58 /* if this is not "my" session key */ 59 return FALSE; 60 } 61 62 return TRUE; 63} 64 65 66static void 67removeAllKeys(SCDynamicStoreRef store, Boolean isRegex) 68{ 69 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; 70 CFArrayRef keys; 71 CFIndex n; 72 73 keys = isRegex ? storePrivate->patterns : storePrivate->keys; 74 n = (keys != NULL) ? CFArrayGetCount(keys) : 0; 75 if (n > 0) { 76 CFIndex i; 77 CFArrayRef keysToRemove; 78 79 keysToRemove = CFArrayCreateCopy(NULL, keys); 80 for (i = 0; i < n; i++) { 81 (void) __SCDynamicStoreRemoveWatchedKey(store, 82 CFArrayGetValueAtIndex(keysToRemove, i), 83 isRegex, 84 TRUE); 85 } 86 CFRelease(keysToRemove); 87 } 88 89 return; 90} 91 92 93__private_extern__ 94int 95__SCDynamicStoreClose(SCDynamicStoreRef *store) 96{ 97 CFDictionaryRef dict; 98 CFArrayRef keys; 99 CFIndex keyCnt; 100 serverSessionRef mySession; 101 CFStringRef sessionKey; 102 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)*store; 103 104 if (_configd_trace) { 105 SCTrace(TRUE, _configd_trace, 106 CFSTR("close : %5d\n"), 107 storePrivate->server); 108 } 109 110 /* Remove all notification keys and patterns */ 111 removeAllKeys(*store, FALSE); // keys 112 removeAllKeys(*store, TRUE); // patterns 113 114 /* Remove/cancel any outstanding notification requests. */ 115 __MACH_PORT_DEBUG(storePrivate->notifyPort != MACH_PORT_NULL, "*** __SCDynamicStoreClose", storePrivate->notifyPort); 116 (void) __SCDynamicStoreNotifyCancel(*store); 117 118 /* Remove any session keys */ 119 sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), storePrivate->server); 120 dict = CFDictionaryGetValue(sessionData, sessionKey); 121 keys = CFDictionaryGetValue(dict, kSCDSessionKeys); 122 if (keys && ((keyCnt = CFArrayGetCount(keys)) > 0)) { 123 CFIndex i; 124 Boolean push = FALSE; 125 126 /* remove session keys */ 127 for (i = 0; i < keyCnt; i++) { 128 if (isMySessionKey(sessionKey, CFArrayGetValueAtIndex(keys, i))) { 129 (void) __SCDynamicStoreRemoveValue(*store, CFArrayGetValueAtIndex(keys, i), TRUE); 130 push = TRUE; 131 } 132 } 133 134 if (push) { 135 /* push changes */ 136 (void) __SCDynamicStorePush(); 137 } 138 } 139 CFRelease(sessionKey); 140 141 /* 142 * invalidate and release our run loop source on the server 143 * port (for this client). Then, release the port. 144 */ 145 mySession = getSession(storePrivate->server); 146 if (mySession->serverRunLoopSource) { 147 CFRunLoopSourceInvalidate(mySession->serverRunLoopSource); 148 CFRelease(mySession->serverRunLoopSource); 149 mySession->serverRunLoopSource = NULL; 150 } 151 if (mySession->serverPort != NULL) { 152 CFMachPortInvalidate(mySession->serverPort); 153 CFRelease(mySession->serverPort); 154 mySession->serverPort = NULL; 155 } 156 157 storePrivate->server = MACH_PORT_NULL; 158 CFRelease(*store); 159 *store = NULL; 160 161 return kSCStatusOK; 162} 163