1/* 2 * Copyright (c) 2000-2004, 2006, 2008, 2011, 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 "configd.h" 35#include "session.h" 36 37__private_extern__ 38int 39__SCDynamicStoreRemoveValue(SCDynamicStoreRef store, CFStringRef key, Boolean internal) 40{ 41 CFDictionaryRef dict; 42 CFMutableDictionaryRef newDict; 43 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store; 44 int sc_status = kSCStatusOK; 45 CFStringRef sessionKey; 46 47 if (_configd_trace) { 48 SCTrace(TRUE, _configd_trace, 49 CFSTR("%s : %5d : %@\n"), 50 internal ? "*remove" : "remove ", 51 storePrivate->server, 52 key); 53 } 54 55 /* 56 * Ensure that this key exists. 57 */ 58 dict = CFDictionaryGetValue(storeData, key); 59 if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDData) == FALSE)) { 60 /* key doesn't exist (or data never defined) */ 61 sc_status = kSCStatusNoKey; 62 goto done; 63 } 64 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict); 65 66 /* 67 * Mark this key as "changed". Any "watchers" will be 68 * notified as soon as the lock is released. 69 */ 70 CFSetAddValue(changedKeys, key); 71 72 /* 73 * Add this key to a deferred cleanup list so that, after 74 * the change notifications are posted, any associated 75 * regex keys can be removed. 76 */ 77 CFSetAddValue(deferredRemovals, key); 78 79 /* 80 * Check if this is a session key and, if so, add it 81 * to the (session) removal list 82 */ 83 sessionKey = CFDictionaryGetValue(newDict, kSCDSession); 84 if (sessionKey) { 85 CFStringRef removedKey; 86 87 /* We are no longer a session key! */ 88 CFDictionaryRemoveValue(newDict, kSCDSession); 89 90 /* add this session key to the (session) removal list */ 91 removedKey = CFStringCreateWithFormat(NULL, 0, CFSTR("%@:%@"), sessionKey, key); 92 CFSetAddValue(removedSessionKeys, removedKey); 93 CFRelease(removedKey); 94 } 95 96 /* 97 * Remove data and update/remove the dictionary store entry. 98 */ 99 CFDictionaryRemoveValue(newDict, kSCDData); 100 if (CFDictionaryGetCount(newDict) > 0) { 101 /* this key is still being "watched" */ 102 CFDictionarySetValue(storeData, key, newDict); 103 } else { 104 /* no information left, remove the empty dictionary */ 105 CFDictionaryRemoveValue(storeData, key); 106 } 107 CFRelease(newDict); 108 109 if (!internal) { 110 /* push changes */ 111 __SCDynamicStorePush(); 112 } 113 114 done: 115 116 return sc_status; 117} 118 119 120__private_extern__ 121kern_return_t 122_configremove(mach_port_t server, 123 xmlData_t keyRef, /* raw XML bytes */ 124 mach_msg_type_number_t keyLen, 125 int *sc_status, 126 audit_token_t audit_token) 127{ 128 CFStringRef key = NULL; /* key (un-serialized) */ 129 serverSessionRef mySession; 130 131 /* un-serialize the key */ 132 if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) { 133 *sc_status = kSCStatusFailed; 134 goto done; 135 } 136 137 if (!isA_CFString(key)) { 138 *sc_status = kSCStatusInvalidArgument; 139 goto done; 140 } 141 142 mySession = getSession(server); 143 if (mySession == NULL) { 144 mySession = tempSession(server, CFSTR("SCDynamicStoreRemoveValue"), audit_token); 145 if (mySession == NULL) { 146 /* you must have an open session to play */ 147 *sc_status = kSCStatusNoStoreSession; 148 goto done; 149 } 150 } 151 152 if (!hasWriteAccess(mySession, key)) { 153 *sc_status = kSCStatusAccessError; 154 goto done; 155 } 156 157 *sc_status = __SCDynamicStoreRemoveValue(mySession->store, key, FALSE); 158 159 done : 160 161 if (key) CFRelease(key); 162 163 return KERN_SUCCESS; 164} 165 166