2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
27 * Modification History
29 * June 1, 2001 Allan Nathanson <ajn@apple.com>
30 * - public API conversion
32 * March 24, 2000 Allan Nathanson <ajn@apple.com>
44 __SCDynamicStoreSetValue(SCDynamicStoreRef store
, CFStringRef key
, CFDataRef value
, Boolean internal
)
46 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
47 int sc_status
= kSCStatusOK
;
49 CFMutableDictionaryRef newDict
;
50 Boolean newEntry
= FALSE
;
51 CFStringRef sessionKey
;
52 CFStringRef storeSessionKey
;
54 if (_configd_verbose
) {
55 CFPropertyListRef val
;
57 (void) _SCUnserialize(&val
, value
, NULL
, NULL
);
58 SCLog(TRUE
, LOG_DEBUG
, CFSTR("__SCDynamicStoreSetValue:"));
59 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" key = %@"), key
);
60 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" value = %@"), val
);
64 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
65 return kSCStatusNoStoreSession
; /* you must have an open session to play */
69 SCTrace(TRUE
, _configd_trace
,
70 CFSTR("%s : %5d : %@\n"),
71 internal
? "*set " : "set ",
77 * 1. Ensure that we hold the lock.
79 sc_status
= __SCDynamicStoreLock(store
, TRUE
);
80 if (sc_status
!= kSCStatusOK
) {
85 * 2. Grab the current (or establish a new) dictionary for this key.
88 dict
= CFDictionaryGetValue(storeData
, key
);
90 newDict
= CFDictionaryCreateMutableCopy(NULL
,
94 newDict
= CFDictionaryCreateMutable(NULL
,
96 &kCFTypeDictionaryKeyCallBacks
,
97 &kCFTypeDictionaryValueCallBacks
);
101 * 3. Update the dictionary entry to be saved to the store.
103 newEntry
= !CFDictionaryContainsKey(newDict
, kSCDData
);
104 CFDictionarySetValue(newDict
, kSCDData
, value
);
107 * 4. Since we are updating this key we need to check and, if
108 * necessary, remove the indication that this key is on
109 * another session's remove-on-close list.
111 sessionKey
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), storePrivate
->server
);
112 if (CFDictionaryGetValueIfPresent(newDict
, kSCDSession
, (void *)&storeSessionKey
) &&
113 !CFEqual(sessionKey
, storeSessionKey
)) {
114 CFStringRef removedKey
;
116 /* We are no longer a session key! */
117 CFDictionaryRemoveValue(newDict
, kSCDSession
);
119 /* add this session key to the (session) removal list */
120 removedKey
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%@:%@"), storeSessionKey
, key
);
121 CFSetAddValue(removedSessionKeys
, removedKey
);
122 CFRelease(removedKey
);
124 CFRelease(sessionKey
);
127 * 5. Update the dictionary entry in the store.
130 CFDictionarySetValue(storeData
, key
, newDict
);
134 * 6. For "new" entries to the store, check the deferred cleanup
135 * list. If the key is flagged for removal, remove it from the
136 * list since any defined regex's for this key are still defined
137 * and valid. If the key is not flagged then iterate over the
138 * sessionData dictionary looking for regex keys which match the
139 * updated key. If a match is found then we mark those keys as
144 if (CFSetContainsValue(deferredRemovals
, key
)) {
145 CFSetRemoveValue(deferredRemovals
, key
);
152 * 7. Mark this key as "changed". Any "watchers" will be notified
153 * as soon as the lock is released.
155 CFSetAddValue(changedKeys
, key
);
158 * 8. Release our lock.
160 __SCDynamicStoreUnlock(store
, TRUE
);
167 _configset(mach_port_t server
,
168 xmlData_t keyRef
, /* raw XML bytes */
169 mach_msg_type_number_t keyLen
,
170 xmlData_t dataRef
, /* raw XML bytes */
171 mach_msg_type_number_t dataLen
,
177 serverSessionRef mySession
= getSession(server
);
178 CFStringRef key
; /* key (un-serialized) */
179 CFDataRef data
; /* data (un-serialized) */
181 if (_configd_verbose
) {
182 SCLog(TRUE
, LOG_DEBUG
, CFSTR("Set key to configuration database."));
183 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
186 *sc_status
= kSCStatusOK
;
188 /* un-serialize the key */
189 if (!_SCUnserializeString(&key
, NULL
, (void *)keyRef
, keyLen
)) {
190 *sc_status
= kSCStatusFailed
;
191 } else if (!isA_CFString(key
)) {
192 *sc_status
= kSCStatusInvalidArgument
;
195 /* un-serialize the data */
196 if (!_SCUnserializeData(&data
, (void *)dataRef
, dataLen
)) {
197 *sc_status
= kSCStatusFailed
;
201 *sc_status
= kSCStatusNoStoreSession
; /* you must have an open session to play */
204 if (*sc_status
!= kSCStatusOK
) {
205 if (key
) CFRelease(key
);
206 if (data
) CFRelease(data
);
210 *sc_status
= __SCDynamicStoreSetValue(mySession
->store
, key
, data
, FALSE
);
220 setSpecificKey(const void *key
, const void *value
, void *context
)
222 CFStringRef k
= (CFStringRef
)key
;
223 CFDataRef v
= (CFDataRef
)value
;
224 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
226 if (!isA_CFString(k
)) {
230 if (!isA_CFData(v
)) {
234 (void) __SCDynamicStoreSetValue(store
, k
, v
, TRUE
);
240 removeSpecificKey(const void *value
, void *context
)
242 CFStringRef k
= (CFStringRef
)value
;
243 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
245 if (!isA_CFString(k
)) {
249 (void) __SCDynamicStoreRemoveValue(store
, k
, TRUE
);
255 notifySpecificKey(const void *value
, void *context
)
257 CFStringRef k
= (CFStringRef
)value
;
258 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
260 if (!isA_CFString(k
)) {
264 (void) __SCDynamicStoreNotifyValue(store
, k
, TRUE
);
271 __SCDynamicStoreSetMultiple(SCDynamicStoreRef store
, CFDictionaryRef keysToSet
, CFArrayRef keysToRemove
, CFArrayRef keysToNotify
)
273 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
274 int sc_status
= kSCStatusOK
;
276 if (_configd_verbose
) {
277 CFDictionaryRef expDict
;
279 expDict
= keysToSet
? _SCUnserializeMultiple(keysToSet
) : NULL
;
280 SCLog(TRUE
, LOG_DEBUG
, CFSTR("__SCDynamicStoreSetMultiple:"));
281 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" keysToSet = %@"), expDict
);
282 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" keysToRemove = %@"), keysToRemove
);
283 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" keysToNotify = %@"), keysToNotify
);
284 if (expDict
) CFRelease(expDict
);
287 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
288 return kSCStatusNoStoreSession
; /* you must have an open session to play */
291 if (_configd_trace
) {
292 SCTrace(TRUE
, _configd_trace
,
293 CFSTR("set m : %5d : %d set, %d remove, %d notify\n"),
294 storePrivate
->server
,
295 keysToSet
? CFDictionaryGetCount(keysToSet
) : 0,
296 keysToRemove
? CFArrayGetCount (keysToRemove
) : 0,
297 keysToNotify
? CFArrayGetCount (keysToNotify
) : 0);
301 * Ensure that we hold the lock
303 sc_status
= __SCDynamicStoreLock(store
, TRUE
);
304 if (sc_status
!= kSCStatusOK
) {
309 * Set the new/updated keys
312 CFDictionaryApplyFunction(keysToSet
,
318 * Remove the specified keys
321 CFArrayApplyFunction(keysToRemove
,
322 CFRangeMake(0, CFArrayGetCount(keysToRemove
)),
328 * Notify the specified keys
331 CFArrayApplyFunction(keysToNotify
,
332 CFRangeMake(0, CFArrayGetCount(keysToNotify
)),
337 /* Release our lock */
338 __SCDynamicStoreUnlock(store
, TRUE
);
345 _configset_m(mach_port_t server
,
347 mach_msg_type_number_t dictLen
,
349 mach_msg_type_number_t removeLen
,
351 mach_msg_type_number_t notifyLen
,
354 serverSessionRef mySession
= getSession(server
);
355 CFDictionaryRef dict
= NULL
; /* key/value dictionary (un-serialized) */
356 CFArrayRef remove
= NULL
; /* keys to remove (un-serialized) */
357 CFArrayRef notify
= NULL
; /* keys to notify (un-serialized) */
359 if (_configd_verbose
) {
360 SCLog(TRUE
, LOG_DEBUG
, CFSTR("Set/remove/notify keys to configuration database."));
361 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
364 *sc_status
= kSCStatusOK
;
366 if (dictRef
&& (dictLen
> 0)) {
367 /* un-serialize the key/value pairs to set */
368 if (!_SCUnserialize((CFPropertyListRef
*)&dict
, NULL
, (void *)dictRef
, dictLen
)) {
369 *sc_status
= kSCStatusFailed
;
370 } else if (!isA_CFDictionary(dict
)) {
371 *sc_status
= kSCStatusInvalidArgument
;
375 if (removeRef
&& (removeLen
> 0)) {
376 /* un-serialize the keys to remove */
377 if (!_SCUnserialize((CFPropertyListRef
*)&remove
, NULL
, (void *)removeRef
, removeLen
)) {
378 *sc_status
= kSCStatusFailed
;
379 } else if (!isA_CFArray(remove
)) {
380 *sc_status
= kSCStatusInvalidArgument
;
384 if (notifyRef
&& (notifyLen
> 0)) {
385 /* un-serialize the keys to notify */
386 if (!_SCUnserialize((CFPropertyListRef
*)¬ify
, NULL
, (void *)notifyRef
, notifyLen
)) {
387 *sc_status
= kSCStatusFailed
;
388 } else if (!isA_CFArray(notify
)) {
389 *sc_status
= kSCStatusInvalidArgument
;
394 /* you must have an open session to play */
395 *sc_status
= kSCStatusNoStoreSession
;
398 if (*sc_status
!= kSCStatusOK
) {
402 *sc_status
= __SCDynamicStoreSetMultiple(mySession
->store
, dict
, remove
, notify
);
406 if (dict
) CFRelease(dict
);
407 if (remove
) CFRelease(remove
);
408 if (notify
) CFRelease(notify
);