2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
29 * March 24, 2000 Allan Nathanson <ajn@apple.com>
37 __SCDynamicStoreSetValue(SCDynamicStoreRef store
, CFStringRef key
, CFPropertyListRef value
)
39 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
40 int sc_status
= kSCStatusOK
;
42 CFMutableDictionaryRef newDict
;
43 Boolean newEntry
= FALSE
;
44 CFStringRef sessionKey
;
45 CFStringRef storeSessionKey
;
47 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("__SCDynamicStoreSetValue:"));
48 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" key = %@"), key
);
49 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" value = %@"), value
);
51 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
52 return kSCStatusNoStoreSession
; /* you must have an open session to play */
56 * 1. Ensure that we hold the lock.
58 sc_status
= __SCDynamicStoreLock(store
, TRUE
);
59 if (sc_status
!= kSCStatusOK
) {
64 * 2. Grab the current (or establish a new) dictionary for this key.
67 dict
= CFDictionaryGetValue(storeData
, key
);
69 newDict
= CFDictionaryCreateMutableCopy(NULL
,
73 newDict
= CFDictionaryCreateMutable(NULL
,
75 &kCFTypeDictionaryKeyCallBacks
,
76 &kCFTypeDictionaryValueCallBacks
);
80 * 3. Update the dictionary entry to be saved to the store.
82 newEntry
= !CFDictionaryContainsKey(newDict
, kSCDData
);
83 CFDictionarySetValue(newDict
, kSCDData
, value
);
86 * 4. Since we are updating this key we need to check and, if
87 * necessary, remove the indication that this key is on
88 * another session's remove-on-close list.
90 sessionKey
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), storePrivate
->server
);
91 if (CFDictionaryGetValueIfPresent(newDict
, kSCDSession
, (void *)&storeSessionKey
) &&
92 !CFEqual(sessionKey
, storeSessionKey
)) {
93 CFStringRef removedKey
;
95 /* We are no longer a session key! */
96 CFDictionaryRemoveValue(newDict
, kSCDSession
);
98 /* add this session key to the (session) removal list */
99 removedKey
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%@:%@"), storeSessionKey
, key
);
100 CFSetAddValue(removedSessionKeys
, removedKey
);
101 CFRelease(removedKey
);
103 CFRelease(sessionKey
);
106 * 5. Update the dictionary entry in the store.
109 CFDictionarySetValue(storeData
, key
, newDict
);
113 * 6. For "new" entries to the store, check the deferred cleanup
114 * list. If the key is flagged for removal, remove it from the
115 * list since any defined regex's for this key are still defined
116 * and valid. If the key is not flagged then iterate over the
117 * sessionData dictionary looking for regex keys which match the
118 * updated key. If a match is found then we mark those keys as
123 if (CFSetContainsValue(deferredRemovals
, key
)) {
124 CFSetRemoveValue(deferredRemovals
, key
);
126 CFDictionaryApplyFunction(sessionData
,
127 (CFDictionaryApplierFunction
)_addRegexWatchersBySession
,
133 * 7. Mark this key as "changed". Any "watchers" will be notified
134 * as soon as the lock is released.
136 CFSetAddValue(changedKeys
, key
);
139 * 8. Release our lock.
141 __SCDynamicStoreUnlock(store
, TRUE
);
147 _configset(mach_port_t server
,
148 xmlData_t keyRef
, /* raw XML bytes */
149 mach_msg_type_number_t keyLen
,
150 xmlData_t dataRef
, /* raw XML bytes */
151 mach_msg_type_number_t dataLen
,
157 serverSessionRef mySession
= getSession(server
);
158 CFStringRef key
; /* key (un-serialized) */
159 CFPropertyListRef data
; /* data (un-serialized) */
161 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("Set key to configuration database."));
162 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
164 *sc_status
= kSCStatusOK
;
166 /* un-serialize the key */
167 if (!_SCUnserialize((CFPropertyListRef
*)&key
, (void *)keyRef
, keyLen
)) {
168 *sc_status
= kSCStatusFailed
;
171 if (!isA_CFString(key
)) {
172 *sc_status
= kSCStatusInvalidArgument
;
175 /* un-serialize the data */
176 if (!_SCUnserialize((CFPropertyListRef
*)&data
, (void *)dataRef
, dataLen
)) {
177 *sc_status
= kSCStatusFailed
;
180 if (!isA_CFPropertyList(data
)) {
181 *sc_status
= kSCStatusInvalidArgument
;
184 if (*sc_status
!= kSCStatusOK
) {
185 if (key
) CFRelease(key
);
186 if (data
) CFRelease(data
);
190 *sc_status
= __SCDynamicStoreSetValue(mySession
->store
, key
, data
);
200 setSpecificKey(const void *key
, const void *value
, void *context
)
202 CFStringRef k
= (CFStringRef
)key
;
203 CFPropertyListRef v
= (CFPropertyListRef
)value
;
204 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
206 if (!isA_CFString(k
)) {
210 if (!isA_CFPropertyList(v
)) {
214 (void) __SCDynamicStoreSetValue(store
, k
, v
);
220 removeSpecificKey(const void *value
, void *context
)
222 CFStringRef k
= (CFStringRef
)value
;
223 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
225 if (!isA_CFString(k
)) {
229 (void) __SCDynamicStoreRemoveValue(store
, k
);
235 notifySpecificKey(const void *value
, void *context
)
237 CFStringRef k
= (CFStringRef
)value
;
238 SCDynamicStoreRef store
= (SCDynamicStoreRef
)context
;
240 if (!isA_CFString(k
)) {
244 (void) __SCDynamicStoreNotifyValue(store
, k
);
250 _configset_m(mach_port_t server
,
252 mach_msg_type_number_t dictLen
,
254 mach_msg_type_number_t removeLen
,
256 mach_msg_type_number_t notifyLen
,
259 serverSessionRef mySession
= getSession(server
);
260 CFDictionaryRef dict
= NULL
; /* key/value dictionary (un-serialized) */
261 CFArrayRef remove
= NULL
; /* keys to remove (un-serialized) */
262 CFArrayRef notify
= NULL
; /* keys to notify (un-serialized) */
264 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("Set key to configuration database."));
265 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
267 *sc_status
= kSCStatusOK
;
269 if (dictRef
&& (dictLen
> 0)) {
270 /* un-serialize the key/value pairs to set */
271 if (!_SCUnserialize((CFPropertyListRef
*)&dict
, (void *)dictRef
, dictLen
)) {
272 *sc_status
= kSCStatusFailed
;
275 if (!isA_CFDictionary(dict
)) {
276 *sc_status
= kSCStatusInvalidArgument
;
280 if (removeRef
&& (removeLen
> 0)) {
281 /* un-serialize the keys to remove */
282 if (!_SCUnserialize((CFPropertyListRef
*)&remove
, (void *)removeRef
, removeLen
)) {
283 *sc_status
= kSCStatusFailed
;
286 if (!isA_CFArray(remove
)) {
287 *sc_status
= kSCStatusInvalidArgument
;
291 if (notifyRef
&& (notifyLen
> 0)) {
292 /* un-serialize the keys to notify */
293 if (!_SCUnserialize((CFPropertyListRef
*)¬ify
, (void *)notifyRef
, notifyLen
)) {
294 *sc_status
= kSCStatusFailed
;
297 if (!isA_CFArray(notify
)) {
298 *sc_status
= kSCStatusInvalidArgument
;
302 if (*sc_status
!= kSCStatusOK
) {
307 * Ensure that we hold the lock
309 *sc_status
= __SCDynamicStoreLock(mySession
->store
, TRUE
);
310 if (*sc_status
!= kSCStatusOK
) {
315 * Set the new/updated keys
318 CFDictionaryApplyFunction(dict
,
320 (void *)mySession
->store
);
324 * Remove the specified keys
327 CFArrayApplyFunction(remove
,
328 CFRangeMake(0, CFArrayGetCount(remove
)),
330 (void *)mySession
->store
);
334 * Notify the specified keys
337 CFArrayApplyFunction(notify
,
338 CFRangeMake(0, CFArrayGetCount(notify
)),
340 (void *)mySession
->store
);
343 __SCDynamicStoreUnlock(mySession
->store
, TRUE
); /* Release our lock */
347 if (dict
) CFRelease(dict
);
348 if (remove
) CFRelease(remove
);
349 if (notify
) CFRelease(notify
);