2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * March 24, 2000 Allan Nathanson <ajn@apple.com>
42 __SCDynamicStoreSetValue(SCDynamicStoreRef store
, CFStringRef key
, CFDataRef value
, Boolean internal
)
44 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
45 int sc_status
= kSCStatusOK
;
47 CFMutableDictionaryRef newDict
;
48 Boolean newEntry
= FALSE
;
49 CFStringRef sessionKey
;
50 CFStringRef storeSessionKey
;
52 if (_configd_verbose
) {
53 CFPropertyListRef val
;
55 (void) _SCUnserialize(&val
, value
, NULL
, NULL
);
56 SCLog(TRUE
, LOG_DEBUG
, CFSTR("__SCDynamicStoreSetValue:"));
57 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" key = %@"), key
);
58 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" value = %@"), val
);
62 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
63 return kSCStatusNoStoreSession
; /* you must have an open session to play */
67 SCTrace(TRUE
, _configd_trace
,
68 CFSTR("%s : %5d : %@\n"),
69 internal
? "*set " : "set ",
75 * 1. Ensure that we hold the lock.
77 sc_status
= __SCDynamicStoreLock(store
, TRUE
);
78 if (sc_status
!= kSCStatusOK
) {
83 * 2. Grab the current (or establish a new) dictionary for this key.
86 dict
= CFDictionaryGetValue(storeData
, key
);
88 newDict
= CFDictionaryCreateMutableCopy(NULL
,
92 newDict
= CFDictionaryCreateMutable(NULL
,
94 &kCFTypeDictionaryKeyCallBacks
,
95 &kCFTypeDictionaryValueCallBacks
);
99 * 3. Update the dictionary entry to be saved to the store.
101 newEntry
= !CFDictionaryContainsKey(newDict
, kSCDData
);
102 CFDictionarySetValue(newDict
, kSCDData
, value
);
105 * 4. Since we are updating this key we need to check and, if
106 * necessary, remove the indication that this key is on
107 * another session's remove-on-close list.
109 sessionKey
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), storePrivate
->server
);
110 if (CFDictionaryGetValueIfPresent(newDict
, kSCDSession
, (void *)&storeSessionKey
) &&
111 !CFEqual(sessionKey
, storeSessionKey
)) {
112 CFStringRef removedKey
;
114 /* We are no longer a session key! */
115 CFDictionaryRemoveValue(newDict
, kSCDSession
);
117 /* add this session key to the (session) removal list */
118 removedKey
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%@:%@"), storeSessionKey
, key
);
119 CFSetAddValue(removedSessionKeys
, removedKey
);
120 CFRelease(removedKey
);
122 CFRelease(sessionKey
);
125 * 5. Update the dictionary entry in the store.
128 CFDictionarySetValue(storeData
, key
, newDict
);
132 * 6. For "new" entries to the store, check the deferred cleanup
133 * list. If the key is flagged for removal, remove it from the
134 * list since any defined regex's for this key are still defined
135 * and valid. If the key is not flagged then iterate over the
136 * sessionData dictionary looking for regex keys which match the
137 * updated key. If a match is found then we mark those keys as
142 if (CFSetContainsValue(deferredRemovals
, key
)) {
143 CFSetRemoveValue(deferredRemovals
, key
);
150 * 7. Mark this key as "changed". Any "watchers" will be notified
151 * as soon as the lock is released.
153 CFSetAddValue(changedKeys
, key
);
156 * 8. Release our lock.
158 __SCDynamicStoreUnlock(store
, TRUE
);
165 _configset(mach_port_t server
,
166 xmlData_t keyRef
, /* raw XML bytes */
167 mach_msg_type_number_t keyLen
,
168 xmlData_t dataRef
, /* raw XML bytes */
169 mach_msg_type_number_t dataLen
,
175 serverSessionRef mySession
= getSession(server
);
176 CFStringRef key
; /* key (un-serialized) */
177 CFDataRef data
; /* data (un-serialized) */
179 if (_configd_verbose
) {
180 SCLog(TRUE
, LOG_DEBUG
, CFSTR("Set key to configuration database."));
181 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
184 *sc_status
= kSCStatusOK
;
186 /* un-serialize the key */
187 if (!_SCUnserializeString(&key
, NULL
, (void *)keyRef
, keyLen
)) {
188 *sc_status
= kSCStatusFailed
;
189 } else if (!isA_CFString(key
)) {
190 *sc_status
= kSCStatusInvalidArgument
;
193 /* un-serialize the data */
194 if (!_SCUnserializeData(&data
, (void *)dataRef
, dataLen
)) {
195 *sc_status
= kSCStatusFailed
;
199 *sc_status
= kSCStatusNoStoreSession
; /* you must have an open session to play */
202 if (*sc_status
!= kSCStatusOK
) {
203 if (key
) CFRelease(key
);
204 if (data
) CFRelease(data
);
208 *sc_status
= __SCDynamicStoreSetValue(mySession
->store
, key
, data
, FALSE
);
218 setSpecificKey(const void *key
, const void *value
, void *context
)
220 CFStringRef k
= (CFStringRef
)key
;
221 CFDataRef v
= (CFDataRef
)value
;
222 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
224 if (!isA_CFString(k
)) {
228 if (!isA_CFData(v
)) {
232 (void) __SCDynamicStoreSetValue(store
, k
, v
, TRUE
);
238 removeSpecificKey(const void *value
, void *context
)
240 CFStringRef k
= (CFStringRef
)value
;
241 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
243 if (!isA_CFString(k
)) {
247 (void) __SCDynamicStoreRemoveValue(store
, k
, TRUE
);
253 notifySpecificKey(const void *value
, void *context
)
255 CFStringRef k
= (CFStringRef
)value
;
256 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
258 if (!isA_CFString(k
)) {
262 (void) __SCDynamicStoreNotifyValue(store
, k
, TRUE
);
269 __SCDynamicStoreSetMultiple(SCDynamicStoreRef store
, CFDictionaryRef keysToSet
, CFArrayRef keysToRemove
, CFArrayRef keysToNotify
)
271 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
272 int sc_status
= kSCStatusOK
;
274 if (_configd_verbose
) {
275 CFDictionaryRef expDict
;
277 expDict
= keysToSet
? _SCUnserializeMultiple(keysToSet
) : NULL
;
278 SCLog(TRUE
, LOG_DEBUG
, CFSTR("__SCDynamicStoreSetMultiple:"));
279 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" keysToSet = %@"), expDict
);
280 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" keysToRemove = %@"), keysToRemove
);
281 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" keysToNotify = %@"), keysToNotify
);
282 if (expDict
) CFRelease(expDict
);
285 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
286 return kSCStatusNoStoreSession
; /* you must have an open session to play */
289 if (_configd_trace
) {
290 SCTrace(TRUE
, _configd_trace
,
291 CFSTR("set m : %5d : %d set, %d remove, %d notify\n"),
292 storePrivate
->server
,
293 keysToSet
? CFDictionaryGetCount(keysToSet
) : 0,
294 keysToRemove
? CFArrayGetCount (keysToRemove
) : 0,
295 keysToNotify
? CFArrayGetCount (keysToNotify
) : 0);
299 * Ensure that we hold the lock
301 sc_status
= __SCDynamicStoreLock(store
, TRUE
);
302 if (sc_status
!= kSCStatusOK
) {
307 * Set the new/updated keys
310 CFDictionaryApplyFunction(keysToSet
,
316 * Remove the specified keys
319 CFArrayApplyFunction(keysToRemove
,
320 CFRangeMake(0, CFArrayGetCount(keysToRemove
)),
326 * Notify the specified keys
329 CFArrayApplyFunction(keysToNotify
,
330 CFRangeMake(0, CFArrayGetCount(keysToNotify
)),
335 /* Release our lock */
336 __SCDynamicStoreUnlock(store
, TRUE
);
343 _configset_m(mach_port_t server
,
345 mach_msg_type_number_t dictLen
,
347 mach_msg_type_number_t removeLen
,
349 mach_msg_type_number_t notifyLen
,
352 serverSessionRef mySession
= getSession(server
);
353 CFDictionaryRef dict
= NULL
; /* key/value dictionary (un-serialized) */
354 CFArrayRef remove
= NULL
; /* keys to remove (un-serialized) */
355 CFArrayRef notify
= NULL
; /* keys to notify (un-serialized) */
357 if (_configd_verbose
) {
358 SCLog(TRUE
, LOG_DEBUG
, CFSTR("Set/remove/notify keys to configuration database."));
359 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
362 *sc_status
= kSCStatusOK
;
364 if (dictRef
&& (dictLen
> 0)) {
365 /* un-serialize the key/value pairs to set */
366 if (!_SCUnserialize((CFPropertyListRef
*)&dict
, NULL
, (void *)dictRef
, dictLen
)) {
367 *sc_status
= kSCStatusFailed
;
368 } else if (!isA_CFDictionary(dict
)) {
369 *sc_status
= kSCStatusInvalidArgument
;
373 if (removeRef
&& (removeLen
> 0)) {
374 /* un-serialize the keys to remove */
375 if (!_SCUnserialize((CFPropertyListRef
*)&remove
, NULL
, (void *)removeRef
, removeLen
)) {
376 *sc_status
= kSCStatusFailed
;
377 } else if (!isA_CFArray(remove
)) {
378 *sc_status
= kSCStatusInvalidArgument
;
382 if (notifyRef
&& (notifyLen
> 0)) {
383 /* un-serialize the keys to notify */
384 if (!_SCUnserialize((CFPropertyListRef
*)¬ify
, NULL
, (void *)notifyRef
, notifyLen
)) {
385 *sc_status
= kSCStatusFailed
;
386 } else if (!isA_CFArray(notify
)) {
387 *sc_status
= kSCStatusInvalidArgument
;
392 /* you must have an open session to play */
393 *sc_status
= kSCStatusNoStoreSession
;
396 if (*sc_status
!= kSCStatusOK
) {
400 *sc_status
= __SCDynamicStoreSetMultiple(mySession
->store
, dict
, remove
, notify
);
404 if (dict
) CFRelease(dict
);
405 if (remove
) CFRelease(remove
);
406 if (notify
) CFRelease(notify
);