]> git.saurik.com Git - apple/configd.git/blame - configd.tproj/_notifyadd.c
configd-699.30.1.tar.gz
[apple/configd.git] / configd.tproj / _notifyadd.c
CommitLineData
5958d7c0 1/*
78403150 2 * Copyright (c) 2000-2004, 2006, 2008, 2010, 2011, 2014 Apple Inc. All rights reserved.
5958d7c0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
009ee3c6 5 *
009ee3c6
A
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
5958d7c0
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
009ee3c6
A
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 *
5958d7c0
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
0fae82ee
A
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
5958d7c0
A
34#include "configd.h"
35#include "session.h"
009ee3c6 36#include "pattern.h"
5958d7c0 37
0fae82ee
A
38
39static __inline__ void
6bb65964
A
40my_CFArrayApplyFunction(CFArrayRef theArray,
41 CFArrayApplierFunction applier,
42 void *context)
5958d7c0 43{
0fae82ee 44 CFAllocatorRef myAllocator;
6bb65964 45 CFArrayRef myArray;
0fae82ee 46
6bb65964
A
47 myAllocator = CFGetAllocator(theArray);
48 myArray = CFArrayCreateCopy(myAllocator, theArray);
49 CFArrayApplyFunction(myArray, CFRangeMake(0, CFArrayGetCount(myArray)), applier, context);
50 CFRelease(myArray);
51 return;
52}
53
54
55static int
56hasKey(CFMutableArrayRef keys, CFStringRef key)
57{
58 if (keys != NULL) {
59 CFIndex n;
60
61 n = CFArrayGetCount(keys);
62 if (CFArrayContainsValue(keys, CFRangeMake(0, n), key)) {
63 /* sorry, pattern already exists in notifier list */
64 return kSCStatusKeyExists;
65 }
66 }
67
68 return kSCStatusOK;
69}
70
71
72static void
73addKey(CFMutableArrayRef *keysP, CFStringRef key)
74{
75 if (*keysP == NULL) {
76 *keysP = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
77 }
78
79 CFArrayAppendValue(*keysP, key);
0fae82ee
A
80 return;
81}
82
83
009ee3c6 84__private_extern__
0fae82ee 85int
009ee3c6 86__SCDynamicStoreAddWatchedKey(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, Boolean internal)
0fae82ee 87{
009ee3c6
A
88 int sc_status = kSCStatusOK;
89 CFNumberRef sessionNum = NULL;
90 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
5958d7c0 91
009ee3c6
A
92 if (_configd_trace) {
93 SCTrace(TRUE, _configd_trace,
94 CFSTR("%s : %5d : %s : %@\n"),
95 internal ? "*watch+" : "watch+ ",
96 storePrivate->server,
97 isRegex ? "pattern" : "key",
98 key);
5958d7c0
A
99 }
100
009ee3c6 101 sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
5958d7c0 102
009ee3c6 103 if (isRegex) {
6bb65964
A
104 sc_status = hasKey(storePrivate->patterns, key);
105 if (sc_status != kSCStatusOK) {
009ee3c6 106 goto done;
5958d7c0
A
107 }
108
109 /*
009ee3c6 110 * add this session as a pattern watcher
5958d7c0 111 */
009ee3c6
A
112 if (!patternAddSession(key, sessionNum)) {
113 sc_status = kSCStatusInvalidArgument;
114 goto done;
5958d7c0
A
115 }
116
009ee3c6 117 /* add pattern to this sessions notifier list */
6bb65964 118 addKey(&storePrivate->patterns, key);
5958d7c0 119 } else {
6bb65964
A
120 sc_status = hasKey(storePrivate->keys, key);
121 if (sc_status != kSCStatusOK) {
009ee3c6
A
122 goto done;
123 }
5958d7c0
A
124
125 /*
126 * We are watching a specific key. As such, update the
0fae82ee 127 * store to mark our interest in any changes.
5958d7c0 128 */
5958d7c0 129 _addWatcher(sessionNum, key);
009ee3c6
A
130
131 /* add key to this sessions notifier list */
6bb65964 132 addKey(&storePrivate->keys, key);
5958d7c0
A
133 }
134
009ee3c6
A
135 done :
136
edebe297 137 if (sessionNum != NULL) CFRelease(sessionNum);
009ee3c6 138 return sc_status;
5958d7c0
A
139}
140
141
009ee3c6 142__private_extern__
5958d7c0
A
143kern_return_t
144_notifyadd(mach_port_t server,
145 xmlData_t keyRef, /* raw XML bytes */
146 mach_msg_type_number_t keyLen,
0fae82ee
A
147 int isRegex,
148 int *sc_status
5958d7c0
A
149)
150{
dbf6a266 151 CFStringRef key = NULL; /* key (un-serialized) */
a40a14f8 152 serverSessionRef mySession;
5958d7c0
A
153
154 /* un-serialize the key */
009ee3c6 155 if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
0fae82ee 156 *sc_status = kSCStatusFailed;
dbf6a266 157 goto done;
a5f60add
A
158 }
159
160 if (!isA_CFString(key)) {
0fae82ee 161 *sc_status = kSCStatusInvalidArgument;
dbf6a266 162 goto done;
009ee3c6
A
163 }
164
a40a14f8 165 mySession = getSession(server);
edebe297 166 if (mySession == NULL) {
009ee3c6 167 *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
dbf6a266 168 goto done;
5958d7c0
A
169 }
170
009ee3c6 171 *sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex != 0, FALSE);
5958d7c0 172
dbf6a266
A
173 done :
174
175 if (key) CFRelease(key);
5958d7c0
A
176 return KERN_SUCCESS;
177}
009ee3c6
A
178
179
180/*
181 * "context" argument for removeOldKey() and addNewKey()
182 */
183typedef struct {
184 SCDynamicStoreRef store;
6bb65964 185 CFArrayRef oldKeys; /* for addNewKey */
009ee3c6
A
186 CFArrayRef newKeys; /* for removeOldKey */
187 Boolean isRegex;
188 int sc_status;
189} updateKeysContext, *updateKeysContextRef;
190
191
192static void
193removeOldKey(const void *value, void *context)
194{
195 CFStringRef oldKey = (CFStringRef)value;
196 updateKeysContextRef myContextRef = (updateKeysContextRef)context;
197
198 if (myContextRef->sc_status != kSCStatusOK) {
199 return;
200 }
201
edebe297 202 if ((myContextRef->newKeys == NULL) ||
009ee3c6
A
203 !CFArrayContainsValue(myContextRef->newKeys,
204 CFRangeMake(0, CFArrayGetCount(myContextRef->newKeys)),
205 oldKey)) {
206 /* the old notification key is not being retained, remove it */
207 myContextRef->sc_status = __SCDynamicStoreRemoveWatchedKey(myContextRef->store,
208 oldKey,
209 myContextRef->isRegex,
210 TRUE);
211 }
212
213 return;
214}
215
216
217static void
218addNewKey(const void *value, void *context)
219{
220 CFStringRef newKey = (CFStringRef)value;
221 updateKeysContextRef myContextRef = (updateKeysContextRef)context;
222
223 if (myContextRef->sc_status != kSCStatusOK) {
224 return;
225 }
226
edebe297 227 if ((myContextRef->oldKeys == NULL) ||
6bb65964
A
228 !CFArrayContainsValue(myContextRef->oldKeys,
229 CFRangeMake(0, CFArrayGetCount(myContextRef->oldKeys)),
230 newKey)) {
009ee3c6
A
231 /* if this is a new notification key */
232 myContextRef->sc_status = __SCDynamicStoreAddWatchedKey(myContextRef->store,
233 newKey,
234 myContextRef->isRegex,
235 TRUE);
236 }
237
238 return;
239}
240
241
242__private_extern__
243int
244__SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRef patterns)
245{
246 updateKeysContext myContext;
247 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
248
009ee3c6
A
249 if (_configd_trace) {
250 SCTrace(TRUE, _configd_trace,
78403150 251 CFSTR("watch : %5d : %ld keys, %ld patterns\n"),
009ee3c6
A
252 storePrivate->server,
253 keys ? CFArrayGetCount(keys) : 0,
254 patterns ? CFArrayGetCount(patterns) : 0);
255 }
256
257 myContext.store = store;
258 myContext.sc_status = kSCStatusOK;
259
260 /* remove any previously registered keys, register any new keys */
6bb65964 261 myContext.oldKeys = NULL;
009ee3c6
A
262 myContext.newKeys = keys;
263 myContext.isRegex = FALSE;
6bb65964
A
264 if (storePrivate->keys != NULL) {
265 myContext.oldKeys = CFArrayCreateCopy(NULL, storePrivate->keys);
266 my_CFArrayApplyFunction(storePrivate->keys, removeOldKey, &myContext);
267 }
edebe297 268 if (keys != NULL) {
009ee3c6
A
269 CFArrayApplyFunction(keys,
270 CFRangeMake(0, CFArrayGetCount(keys)),
271 addNewKey,
272 &myContext);
273 }
6bb65964 274 if (myContext.oldKeys != NULL) CFRelease(myContext.oldKeys);
009ee3c6
A
275
276 /* remove any previously registered patterns, register any new patterns */
6bb65964 277 myContext.oldKeys = NULL;
009ee3c6
A
278 myContext.newKeys = patterns;
279 myContext.isRegex = TRUE;
6bb65964
A
280 if (storePrivate->patterns != NULL) {
281 myContext.oldKeys = CFArrayCreateCopy(NULL, storePrivate->patterns);
282 my_CFArrayApplyFunction(storePrivate->patterns, removeOldKey, &myContext);
283 }
edebe297 284 if (patterns != NULL) {
009ee3c6
A
285 CFArrayApplyFunction(patterns,
286 CFRangeMake(0, CFArrayGetCount(patterns)),
287 addNewKey,
288 &myContext);
289 }
6bb65964 290 if (myContext.oldKeys != NULL) CFRelease(myContext.oldKeys);
009ee3c6
A
291
292 return myContext.sc_status;
293}
294
295
296__private_extern__
297kern_return_t
298_notifyset(mach_port_t server,
299 xmlData_t keysRef, /* raw XML bytes */
300 mach_msg_type_number_t keysLen,
301 xmlData_t patternsRef, /* raw XML bytes */
302 mach_msg_type_number_t patternsLen,
303 int *sc_status
304)
305{
009ee3c6 306 CFArrayRef keys = NULL; /* key (un-serialized) */
a40a14f8 307 serverSessionRef mySession;
009ee3c6
A
308 CFArrayRef patterns = NULL; /* patterns (un-serialized) */
309
009ee3c6
A
310 *sc_status = kSCStatusOK;
311
edebe297 312 if ((keysRef != NULL) && (keysLen > 0)) {
009ee3c6
A
313 /* un-serialize the keys */
314 if (!_SCUnserialize((CFPropertyListRef *)&keys, NULL, (void *)keysRef, keysLen)) {
315 *sc_status = kSCStatusFailed;
009ee3c6
A
316 }
317 }
318
edebe297 319 if ((patternsRef != NULL) && (patternsLen > 0)) {
009ee3c6
A
320 /* un-serialize the patterns */
321 if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) {
322 *sc_status = kSCStatusFailed;
009ee3c6
A
323 }
324 }
325
edebe297
A
326 if (*sc_status != kSCStatusOK) {
327 goto done;
328 }
329
330 if ((keys != NULL) && !isA_CFArray(keys)) {
331 *sc_status = kSCStatusInvalidArgument;
332 goto done;
333 }
334
335 if ((patterns != NULL) && !isA_CFArray(patterns)) {
336 *sc_status = kSCStatusInvalidArgument;
337 goto done;
338 }
339
a40a14f8 340 mySession = getSession(server);
edebe297 341 if (mySession == NULL) {
009ee3c6
A
342 /* you must have an open session to play */
343 *sc_status = kSCStatusNoStoreSession;
edebe297 344 goto done;
009ee3c6
A
345 }
346
edebe297
A
347 *sc_status = __SCDynamicStoreSetNotificationKeys(mySession->store, keys, patterns);
348
349 done :
009ee3c6 350
edebe297
A
351 if (keys != NULL) CFRelease(keys);
352 if (patterns != NULL) CFRelease(patterns);
009ee3c6
A
353
354 return KERN_SUCCESS;
355}