]> git.saurik.com Git - apple/configd.git/blame - configd.tproj/_notifyadd.c
configd-1109.101.1.tar.gz
[apple/configd.git] / configd.tproj / _notifyadd.c
CommitLineData
5958d7c0 1/*
942cecd7 2 * Copyright (c) 2000-2004, 2006, 2008, 2010, 2011, 2014-2016 Apple Inc. All rights reserved.
5958d7c0
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
9de8ab86 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.
9de8ab86 12 *
009ee3c6
A
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.
9de8ab86 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
942cecd7 92 SC_trace("%s : %5d : %s : %@",
9de8ab86
A
93 internal ? "*watch+" : "watch+ ",
94 storePrivate->server,
95 isRegex ? "pattern" : "key",
96 key);
5958d7c0 97
009ee3c6 98 sessionNum = CFNumberCreate(NULL, kCFNumberIntType, &storePrivate->server);
5958d7c0 99
009ee3c6 100 if (isRegex) {
6bb65964
A
101 sc_status = hasKey(storePrivate->patterns, key);
102 if (sc_status != kSCStatusOK) {
009ee3c6 103 goto done;
5958d7c0
A
104 }
105
106 /*
009ee3c6 107 * add this session as a pattern watcher
5958d7c0 108 */
009ee3c6
A
109 if (!patternAddSession(key, sessionNum)) {
110 sc_status = kSCStatusInvalidArgument;
111 goto done;
5958d7c0
A
112 }
113
009ee3c6 114 /* add pattern to this sessions notifier list */
6bb65964 115 addKey(&storePrivate->patterns, key);
5958d7c0 116 } else {
6bb65964
A
117 sc_status = hasKey(storePrivate->keys, key);
118 if (sc_status != kSCStatusOK) {
009ee3c6
A
119 goto done;
120 }
5958d7c0
A
121
122 /*
123 * We are watching a specific key. As such, update the
0fae82ee 124 * store to mark our interest in any changes.
5958d7c0 125 */
5958d7c0 126 _addWatcher(sessionNum, key);
009ee3c6
A
127
128 /* add key to this sessions notifier list */
6bb65964 129 addKey(&storePrivate->keys, key);
5958d7c0
A
130 }
131
009ee3c6
A
132 done :
133
edebe297 134 if (sessionNum != NULL) CFRelease(sessionNum);
009ee3c6 135 return sc_status;
5958d7c0
A
136}
137
138
009ee3c6 139__private_extern__
5958d7c0
A
140kern_return_t
141_notifyadd(mach_port_t server,
142 xmlData_t keyRef, /* raw XML bytes */
143 mach_msg_type_number_t keyLen,
0fae82ee
A
144 int isRegex,
145 int *sc_status
5958d7c0
A
146)
147{
dbf6a266 148 CFStringRef key = NULL; /* key (un-serialized) */
a40a14f8 149 serverSessionRef mySession;
5958d7c0
A
150
151 /* un-serialize the key */
009ee3c6 152 if (!_SCUnserializeString(&key, NULL, (void *)keyRef, keyLen)) {
0fae82ee 153 *sc_status = kSCStatusFailed;
dbf6a266 154 goto done;
a5f60add
A
155 }
156
157 if (!isA_CFString(key)) {
0fae82ee 158 *sc_status = kSCStatusInvalidArgument;
dbf6a266 159 goto done;
009ee3c6
A
160 }
161
a40a14f8 162 mySession = getSession(server);
edebe297 163 if (mySession == NULL) {
009ee3c6 164 *sc_status = kSCStatusNoStoreSession; /* you must have an open session to play */
dbf6a266 165 goto done;
5958d7c0
A
166 }
167
009ee3c6 168 *sc_status = __SCDynamicStoreAddWatchedKey(mySession->store, key, isRegex != 0, FALSE);
5958d7c0 169
dbf6a266
A
170 done :
171
172 if (key) CFRelease(key);
5958d7c0
A
173 return KERN_SUCCESS;
174}
009ee3c6
A
175
176
177/*
178 * "context" argument for removeOldKey() and addNewKey()
179 */
180typedef struct {
181 SCDynamicStoreRef store;
6bb65964 182 CFArrayRef oldKeys; /* for addNewKey */
009ee3c6
A
183 CFArrayRef newKeys; /* for removeOldKey */
184 Boolean isRegex;
185 int sc_status;
186} updateKeysContext, *updateKeysContextRef;
187
188
189static void
190removeOldKey(const void *value, void *context)
191{
192 CFStringRef oldKey = (CFStringRef)value;
193 updateKeysContextRef myContextRef = (updateKeysContextRef)context;
194
195 if (myContextRef->sc_status != kSCStatusOK) {
196 return;
197 }
198
edebe297 199 if ((myContextRef->newKeys == NULL) ||
009ee3c6
A
200 !CFArrayContainsValue(myContextRef->newKeys,
201 CFRangeMake(0, CFArrayGetCount(myContextRef->newKeys)),
202 oldKey)) {
203 /* the old notification key is not being retained, remove it */
204 myContextRef->sc_status = __SCDynamicStoreRemoveWatchedKey(myContextRef->store,
205 oldKey,
206 myContextRef->isRegex,
207 TRUE);
208 }
209
210 return;
211}
212
213
214static void
215addNewKey(const void *value, void *context)
216{
217 CFStringRef newKey = (CFStringRef)value;
218 updateKeysContextRef myContextRef = (updateKeysContextRef)context;
219
220 if (myContextRef->sc_status != kSCStatusOK) {
221 return;
222 }
223
edebe297 224 if ((myContextRef->oldKeys == NULL) ||
6bb65964
A
225 !CFArrayContainsValue(myContextRef->oldKeys,
226 CFRangeMake(0, CFArrayGetCount(myContextRef->oldKeys)),
227 newKey)) {
009ee3c6
A
228 /* if this is a new notification key */
229 myContextRef->sc_status = __SCDynamicStoreAddWatchedKey(myContextRef->store,
230 newKey,
231 myContextRef->isRegex,
232 TRUE);
233 }
234
235 return;
236}
237
238
239__private_extern__
240int
241__SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRef patterns)
242{
243 updateKeysContext myContext;
244 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
245
942cecd7 246 SC_trace("watch : %5d : %ld keys, %ld patterns",
9de8ab86
A
247 storePrivate->server,
248 keys ? CFArrayGetCount(keys) : 0,
249 patterns ? CFArrayGetCount(patterns) : 0);
009ee3c6
A
250
251 myContext.store = store;
252 myContext.sc_status = kSCStatusOK;
253
254 /* remove any previously registered keys, register any new keys */
6bb65964 255 myContext.oldKeys = NULL;
009ee3c6
A
256 myContext.newKeys = keys;
257 myContext.isRegex = FALSE;
6bb65964
A
258 if (storePrivate->keys != NULL) {
259 myContext.oldKeys = CFArrayCreateCopy(NULL, storePrivate->keys);
260 my_CFArrayApplyFunction(storePrivate->keys, removeOldKey, &myContext);
261 }
edebe297 262 if (keys != NULL) {
009ee3c6
A
263 CFArrayApplyFunction(keys,
264 CFRangeMake(0, CFArrayGetCount(keys)),
265 addNewKey,
266 &myContext);
267 }
6bb65964 268 if (myContext.oldKeys != NULL) CFRelease(myContext.oldKeys);
009ee3c6
A
269
270 /* remove any previously registered patterns, register any new patterns */
6bb65964 271 myContext.oldKeys = NULL;
009ee3c6
A
272 myContext.newKeys = patterns;
273 myContext.isRegex = TRUE;
6bb65964
A
274 if (storePrivate->patterns != NULL) {
275 myContext.oldKeys = CFArrayCreateCopy(NULL, storePrivate->patterns);
276 my_CFArrayApplyFunction(storePrivate->patterns, removeOldKey, &myContext);
277 }
edebe297 278 if (patterns != NULL) {
009ee3c6
A
279 CFArrayApplyFunction(patterns,
280 CFRangeMake(0, CFArrayGetCount(patterns)),
281 addNewKey,
282 &myContext);
283 }
6bb65964 284 if (myContext.oldKeys != NULL) CFRelease(myContext.oldKeys);
009ee3c6
A
285
286 return myContext.sc_status;
287}
288
289
290__private_extern__
291kern_return_t
292_notifyset(mach_port_t server,
293 xmlData_t keysRef, /* raw XML bytes */
294 mach_msg_type_number_t keysLen,
295 xmlData_t patternsRef, /* raw XML bytes */
296 mach_msg_type_number_t patternsLen,
297 int *sc_status
298)
299{
009ee3c6 300 CFArrayRef keys = NULL; /* key (un-serialized) */
a40a14f8 301 serverSessionRef mySession;
009ee3c6
A
302 CFArrayRef patterns = NULL; /* patterns (un-serialized) */
303
009ee3c6
A
304 *sc_status = kSCStatusOK;
305
edebe297 306 if ((keysRef != NULL) && (keysLen > 0)) {
009ee3c6
A
307 /* un-serialize the keys */
308 if (!_SCUnserialize((CFPropertyListRef *)&keys, NULL, (void *)keysRef, keysLen)) {
309 *sc_status = kSCStatusFailed;
009ee3c6
A
310 }
311 }
312
edebe297 313 if ((patternsRef != NULL) && (patternsLen > 0)) {
009ee3c6
A
314 /* un-serialize the patterns */
315 if (!_SCUnserialize((CFPropertyListRef *)&patterns, NULL, (void *)patternsRef, patternsLen)) {
316 *sc_status = kSCStatusFailed;
009ee3c6
A
317 }
318 }
319
edebe297
A
320 if (*sc_status != kSCStatusOK) {
321 goto done;
322 }
323
324 if ((keys != NULL) && !isA_CFArray(keys)) {
325 *sc_status = kSCStatusInvalidArgument;
326 goto done;
327 }
328
329 if ((patterns != NULL) && !isA_CFArray(patterns)) {
330 *sc_status = kSCStatusInvalidArgument;
331 goto done;
332 }
333
a40a14f8 334 mySession = getSession(server);
edebe297 335 if (mySession == NULL) {
009ee3c6
A
336 /* you must have an open session to play */
337 *sc_status = kSCStatusNoStoreSession;
edebe297 338 goto done;
009ee3c6
A
339 }
340
edebe297
A
341 *sc_status = __SCDynamicStoreSetNotificationKeys(mySession->store, keys, patterns);
342
343 done :
009ee3c6 344
edebe297
A
345 if (keys != NULL) CFRelease(keys);
346 if (patterns != NULL) CFRelease(patterns);
009ee3c6
A
347
348 return KERN_SUCCESS;
349}