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>
41 static __inline__
void
42 my_CFSetApplyFunction(CFSetRef theSet
,
43 CFSetApplierFunction applier
,
46 CFAllocatorRef myAllocator
;
49 myAllocator
= CFGetAllocator(theSet
);
50 mySet
= CFSetCreateCopy(myAllocator
, theSet
);
51 CFSetApplyFunction(mySet
, applier
, context
);
59 __SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store
, CFStringRef key
, Boolean isRegex
, Boolean internal
)
61 int sc_status
= kSCStatusOK
;
62 CFNumberRef sessionNum
= NULL
;
63 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
65 if (_configd_verbose
) {
66 SCLog(TRUE
, LOG_DEBUG
, CFSTR("__SCDynamicStoreAddWatchedKey:"));
67 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" key = %@"), key
);
68 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" isRegex = %s"), isRegex
? "TRUE" : "FALSE");
71 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
72 return kSCStatusNoStoreSession
; /* you must have an open session to play */
76 SCTrace(TRUE
, _configd_trace
,
77 CFSTR("%s : %5d : %s : %@\n"),
78 internal
? "*watch+" : "watch+ ",
80 isRegex
? "pattern" : "key",
84 sessionNum
= CFNumberCreate(NULL
, kCFNumberIntType
, &storePrivate
->server
);
87 if (CFSetContainsValue(storePrivate
->patterns
, key
)) {
88 /* sorry, pattern already exists in notifier list */
89 sc_status
= kSCStatusKeyExists
;
94 * add this session as a pattern watcher
96 if (!patternAddSession(key
, sessionNum
)) {
97 sc_status
= kSCStatusInvalidArgument
;
101 /* add pattern to this sessions notifier list */
102 CFSetAddValue(storePrivate
->patterns
, key
);
104 if (CFSetContainsValue(storePrivate
->keys
, key
)) {
105 /* sorry, key already exists in notifier list */
106 sc_status
= kSCStatusKeyExists
;
111 * We are watching a specific key. As such, update the
112 * store to mark our interest in any changes.
114 _addWatcher(sessionNum
, key
);
116 /* add key to this sessions notifier list */
117 CFSetAddValue(storePrivate
->keys
, key
);
122 if (sessionNum
) CFRelease(sessionNum
);
129 _notifyadd(mach_port_t server
,
130 xmlData_t keyRef
, /* raw XML bytes */
131 mach_msg_type_number_t keyLen
,
136 serverSessionRef mySession
= getSession(server
);
137 CFStringRef key
; /* key (un-serialized) */
139 if (_configd_verbose
) {
140 SCLog(TRUE
, LOG_DEBUG
, CFSTR("Add notification key for this session."));
141 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
144 /* un-serialize the key */
145 if (!_SCUnserializeString(&key
, NULL
, (void *)keyRef
, keyLen
)) {
146 *sc_status
= kSCStatusFailed
;
150 if (!isA_CFString(key
)) {
151 *sc_status
= kSCStatusInvalidArgument
;
157 *sc_status
= kSCStatusNoStoreSession
; /* you must have an open session to play */
162 *sc_status
= __SCDynamicStoreAddWatchedKey(mySession
->store
, key
, isRegex
!= 0, FALSE
);
170 * "context" argument for removeOldKey() and addNewKey()
173 SCDynamicStoreRef store
;
174 CFSetRef oldKeys
; /* for addNewKey */
175 CFArrayRef newKeys
; /* for removeOldKey */
178 } updateKeysContext
, *updateKeysContextRef
;
182 removeOldKey(const void *value
, void *context
)
184 CFStringRef oldKey
= (CFStringRef
)value
;
185 updateKeysContextRef myContextRef
= (updateKeysContextRef
)context
;
187 if (myContextRef
->sc_status
!= kSCStatusOK
) {
191 if (!myContextRef
->newKeys
||
192 !CFArrayContainsValue(myContextRef
->newKeys
,
193 CFRangeMake(0, CFArrayGetCount(myContextRef
->newKeys
)),
195 /* the old notification key is not being retained, remove it */
196 myContextRef
->sc_status
= __SCDynamicStoreRemoveWatchedKey(myContextRef
->store
,
198 myContextRef
->isRegex
,
207 addNewKey(const void *value
, void *context
)
209 CFStringRef newKey
= (CFStringRef
)value
;
210 updateKeysContextRef myContextRef
= (updateKeysContextRef
)context
;
212 if (myContextRef
->sc_status
!= kSCStatusOK
) {
216 if (!myContextRef
->oldKeys
||
217 !CFSetContainsValue(myContextRef
->oldKeys
, newKey
)) {
218 /* if this is a new notification key */
219 myContextRef
->sc_status
= __SCDynamicStoreAddWatchedKey(myContextRef
->store
,
221 myContextRef
->isRegex
,
231 __SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store
, CFArrayRef keys
, CFArrayRef patterns
)
233 updateKeysContext myContext
;
234 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
236 if (_configd_verbose
) {
237 SCLog(TRUE
, LOG_DEBUG
, CFSTR("__SCDynamicStoreSetNotificationKeys:"));
238 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" keys = %@"), keys
);
239 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" patterns = %@"), patterns
);
242 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
243 return kSCStatusNoStoreSession
; /* you must have an open session to play */
246 if (_configd_trace
) {
247 SCTrace(TRUE
, _configd_trace
,
248 CFSTR("watch : %5d : %d keys, %d patterns\n"),
249 storePrivate
->server
,
250 keys
? CFArrayGetCount(keys
) : 0,
251 patterns
? CFArrayGetCount(patterns
) : 0);
254 myContext
.store
= store
;
255 myContext
.sc_status
= kSCStatusOK
;
257 /* remove any previously registered keys, register any new keys */
258 myContext
.oldKeys
= CFSetCreateCopy(NULL
, storePrivate
->keys
);
259 myContext
.newKeys
= keys
;
260 myContext
.isRegex
= FALSE
;
261 my_CFSetApplyFunction(storePrivate
->keys
, removeOldKey
, &myContext
);
263 CFArrayApplyFunction(keys
,
264 CFRangeMake(0, CFArrayGetCount(keys
)),
268 CFRelease(myContext
.oldKeys
);
270 /* remove any previously registered patterns, register any new patterns */
271 myContext
.oldKeys
= CFSetCreateCopy(NULL
, storePrivate
->patterns
);
272 myContext
.newKeys
= patterns
;
273 myContext
.isRegex
= TRUE
;
274 my_CFSetApplyFunction(storePrivate
->patterns
, removeOldKey
, &myContext
);
276 CFArrayApplyFunction(patterns
,
277 CFRangeMake(0, CFArrayGetCount(patterns
)),
281 CFRelease(myContext
.oldKeys
);
283 return myContext
.sc_status
;
289 _notifyset(mach_port_t server
,
290 xmlData_t keysRef
, /* raw XML bytes */
291 mach_msg_type_number_t keysLen
,
292 xmlData_t patternsRef
, /* raw XML bytes */
293 mach_msg_type_number_t patternsLen
,
297 serverSessionRef mySession
= getSession(server
);
298 CFArrayRef keys
= NULL
; /* key (un-serialized) */
299 CFArrayRef patterns
= NULL
; /* patterns (un-serialized) */
301 if (_configd_verbose
) {
302 SCLog(TRUE
, LOG_DEBUG
, CFSTR("Add notification key for this session."));
303 SCLog(TRUE
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
306 *sc_status
= kSCStatusOK
;
308 if (keysRef
&& (keysLen
> 0)) {
309 /* un-serialize the keys */
310 if (!_SCUnserialize((CFPropertyListRef
*)&keys
, NULL
, (void *)keysRef
, keysLen
)) {
311 *sc_status
= kSCStatusFailed
;
312 } else if (!isA_CFArray(keys
)) {
313 *sc_status
= kSCStatusInvalidArgument
;
317 if (patternsRef
&& (patternsLen
> 0)) {
318 /* un-serialize the patterns */
319 if (!_SCUnserialize((CFPropertyListRef
*)&patterns
, NULL
, (void *)patternsRef
, patternsLen
)) {
320 *sc_status
= kSCStatusFailed
;
321 } else if (!isA_CFArray(patterns
)) {
322 *sc_status
= kSCStatusInvalidArgument
;
327 /* you must have an open session to play */
328 *sc_status
= kSCStatusNoStoreSession
;
331 if (*sc_status
== kSCStatusOK
) {
332 *sc_status
= __SCDynamicStoreSetNotificationKeys(mySession
->store
, keys
, patterns
);
335 if (keys
) CFRelease(keys
);
336 if (patterns
) CFRelease(patterns
);