]> git.saurik.com Git - apple/configd.git/blob - scutil.tproj/cache.c
configd-1061.0.2.tar.gz
[apple/configd.git] / scutil.tproj / cache.c
1 /*
2 * Copyright (c) 2000-2005, 2011, 2017, 2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
29 *
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
31 * - initial revision
32 */
33
34 #include <sys/types.h>
35
36 #include "scutil.h"
37 #include "cache.h"
38 #include "SCDynamicStoreInternal.h"
39
40
41 #pragma mark -
42 #pragma mark SCDynamicStore "cache"
43
44
45 #pragma mark -
46 #pragma mark SCDynamicStore operations
47
48
49 __private_extern__
50 void
51 do_block(int argc, char **argv)
52 {
53 Boolean enable = FALSE;
54
55 if (argc >= 1) {
56 if ((strcasecmp(argv[0], "begin") == 0) ||
57 (strcasecmp(argv[0], "start") == 0) ||
58 (strcasecmp(argv[0], "on" ) == 0) ||
59 (strcasecmp(argv[0], "1" ) == 0)) {
60 enable = TRUE;
61 } else if ((strcasecmp(argv[0], "end" ) == 0) ||
62 (strcasecmp(argv[0], "stop" ) == 0) ||
63 (strcasecmp(argv[0], "off" ) == 0) ||
64 (strcasecmp(argv[0], "0" ) == 0)) {
65 enable = FALSE;
66 } else {
67 SCPrint(TRUE, stdout, CFSTR("invalid value\n"));
68 return;
69 }
70 } else {
71 enable = !_SCDynamicStoreCacheIsActive(store); // toggle
72 }
73
74 if (enable) {
75 // begin block of SCDynamicStore operations
76 if (_SCDynamicStoreCacheIsActive(store)) {
77 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusLocked));
78 return;
79 }
80
81 SCPrint(TRUE, stdout, CFSTR("Begin block of SCDynamicStore operations\n"));
82
83 _SCDynamicStoreCacheOpen(store);
84 } else {
85 CFIndex n = 0;
86 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
87
88 // end block of SCDynamicStore operations
89 if (!_SCDynamicStoreCacheIsActive(store)) {
90 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(kSCStatusNeedLock));
91 return;
92 }
93
94 n += (storePrivate->cached_set != NULL)
95 ? CFDictionaryGetCount(storePrivate->cached_set) : 0;
96 n += (storePrivate->cached_removals != NULL)
97 ? CFArrayGetCount(storePrivate->cached_removals) : 0;
98 n += (storePrivate->cached_notifys != NULL)
99 ? CFArrayGetCount(storePrivate->cached_notifys) : 0;
100
101 SCPrint(TRUE, stdout,
102 CFSTR("End block of SCDynamicStore operations%s\n"),
103 (n > 0) ? ", posting changes" : "");
104 if (n > 0) {
105 _SCDynamicStoreCacheCommitChanges(store);
106 }
107 _SCDynamicStoreCacheClose(store);
108 }
109
110 return;
111 }
112
113
114 static CFComparisonResult
115 sort_keys(const void *p1, const void *p2, void *context)
116 {
117 #pragma unused(context)
118 CFStringRef key1 = (CFStringRef)p1;
119 CFStringRef key2 = (CFStringRef)p2;
120 return CFStringCompare(key1, key2, 0);
121 }
122
123
124 #define N_QUICK 64
125
126
127 __private_extern__
128 void
129 do_list(int argc, char **argv)
130 {
131 int i;
132 CFStringRef pattern;
133 CFArrayRef list;
134 CFIndex listCnt;
135 CFMutableArrayRef sortedList;
136 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
137
138 pattern = CFStringCreateWithCString(NULL,
139 (argc >= 1) ? argv[0] : ".*",
140 kCFStringEncodingUTF8);
141
142 list = SCDynamicStoreCopyKeyList(store, pattern);
143 CFRelease(pattern);
144 if (list == NULL) {
145 if (SCError() != kSCStatusOK) {
146 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
147 return;
148 } else {
149 if (!_SCDynamicStoreCacheIsActive(store)) {
150 SCPrint(TRUE, stdout, CFSTR(" no keys.\n"));
151 return;
152 } else {
153 CFIndex n;
154
155 n = (storePrivate->cached_set != NULL)
156 ? CFDictionaryGetCount(storePrivate->cached_set) : 0;
157 if (n > 0) {
158 const void * cachedKeys_q[N_QUICK];
159 const void ** cachedKeys = cachedKeys_q;
160
161 if (n > (CFIndex)(sizeof(cachedKeys_q) / sizeof(CFStringRef))) {
162 cachedKeys = CFAllocatorAllocate(NULL, n * sizeof(CFStringRef), 0);
163 }
164 CFDictionaryGetKeysAndValues(storePrivate->cached_set, cachedKeys, NULL);
165 list = CFArrayCreate(NULL, cachedKeys, n, &kCFTypeArrayCallBacks);
166 if (cachedKeys != cachedKeys_q) {
167 CFAllocatorDeallocate(NULL, cachedKeys);
168 }
169 } else {
170 SCPrint(TRUE, stdout, CFSTR(" no keys.\n"));
171 return;
172 }
173 }
174 }
175 } else if (_SCDynamicStoreCacheIsActive(store) &&
176 (((storePrivate->cached_set != NULL) &&
177 (CFDictionaryGetCount(storePrivate->cached_set) > 0)) ||
178 ((storePrivate->cached_removals != NULL) &&
179 (CFArrayGetCount(storePrivate->cached_removals) > 0)))) {
180 SCPrint(TRUE, stdout,
181 CFSTR(" Note: SCDynamicStore transactions in progress, key list (below) may be out of date.\n\n"));
182 }
183
184 listCnt = CFArrayGetCount(list);
185 sortedList = CFArrayCreateMutableCopy(NULL, listCnt, list);
186 CFRelease(list);
187 CFArraySortValues(sortedList,
188 CFRangeMake(0, listCnt),
189 sort_keys,
190 NULL);
191
192 if (listCnt > 0) {
193 for (i = 0; i < listCnt; i++) {
194 SCPrint(TRUE,
195 stdout,
196 CFSTR(" subKey [%d] = %@\n"),
197 i,
198 CFArrayGetValueAtIndex(sortedList, i));
199 }
200 } else {
201 SCPrint(TRUE, stdout, CFSTR(" no keys.\n"));
202 }
203 CFRelease(sortedList);
204
205 return;
206 }
207
208
209 __private_extern__
210 void
211 do_add(int argc, char **argv)
212 {
213 CFStringRef key;
214
215 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
216
217 if (argc < 2) {
218 if (!_SCDynamicStoreCacheIsActive(store)) {
219 if (!SCDynamicStoreAddValue(store, key, value)) {
220 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
221 }
222 } else {
223 SCPrint(TRUE, stdout, CFSTR(" Cannot \"add\" with block\n"));
224 }
225 } else {
226 if (!_SCDynamicStoreCacheIsActive(store)) {
227 if (!SCDynamicStoreAddTemporaryValue(store, key, value)) {
228 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
229 }
230 } else {
231 SCPrint(TRUE, stdout, CFSTR(" Cannot \"add temporary\" with block\n"));
232 }
233 }
234
235 CFRelease(key);
236 return;
237 }
238
239
240 __private_extern__
241 void
242 do_get(int argc, char **argv)
243 {
244 #pragma unused(argc)
245 CFStringRef key;
246 CFPropertyListRef newValue;
247
248 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
249 newValue = SCDynamicStoreCopyValue(store, key);
250 CFRelease(key);
251 if (newValue == NULL) {
252 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
253 return;
254 }
255
256 if (value != NULL) {
257 CFRelease(value); /* we have new information, release the old */
258 }
259 value = newValue;
260
261 return;
262 }
263
264
265 __private_extern__
266 void
267 do_set(int argc, char **argv)
268 {
269 #pragma unused(argc)
270 CFStringRef key;
271
272 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
273 if (!SCDynamicStoreSetValue(store, key, value)) {
274 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
275 }
276 CFRelease(key);
277 return;
278 }
279
280
281 __private_extern__
282 void
283 do_show(int argc, char **argv)
284 {
285 CFStringRef key;
286 CFPropertyListRef newValue;
287
288 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
289
290 if (argc == 1) {
291 newValue = SCDynamicStoreCopyValue(store, key);
292 } else {
293 CFArrayRef patterns;
294
295 patterns = CFArrayCreate(NULL, (const void **)&key, 1, &kCFTypeArrayCallBacks);
296 if (!_SCDynamicStoreCacheIsActive(store)) {
297 newValue = SCDynamicStoreCopyMultiple(store, NULL, patterns);
298 } else {
299 CFArrayRef keys;
300 CFMutableDictionaryRef newDict;
301 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
302
303 newDict = CFDictionaryCreateMutable(NULL,
304 0,
305 &kCFTypeDictionaryKeyCallBacks,
306 &kCFTypeDictionaryValueCallBacks);
307 keys = SCDynamicStoreCopyKeyList(store, key);
308 if (keys != NULL) {
309 CFIndex i;
310 CFIndex n;
311
312 n = CFArrayGetCount(keys);
313 for (i = 0; i < n; i++) {
314 CFStringRef storeKey;
315 CFTypeRef storeVal;
316
317 storeKey = CFArrayGetValueAtIndex(keys, i);
318 storeVal = SCDynamicStoreCopyValue(store, storeKey);
319 if (storeVal != NULL) {
320 CFDictionarySetValue(newDict, storeKey, storeVal);
321 CFRelease(storeVal);
322 }
323 }
324 CFRelease(keys);
325 }
326
327 if (((storePrivate->cached_set != NULL) &&
328 (CFDictionaryGetCount(storePrivate->cached_set) > 0)) ||
329 ((storePrivate->cached_removals != NULL) &&
330 (CFArrayGetCount(storePrivate->cached_removals) > 0))) {
331 SCPrint(TRUE, stdout, CFSTR(" Note: SCDynamicStore locked, keys included (below) may be out of date.\n\n"));
332 }
333
334 newValue = newDict;
335 }
336 CFRelease(patterns);
337 }
338
339 CFRelease(key);
340 if (newValue == NULL) {
341 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
342 return;
343 }
344
345 SCPrint(TRUE, stdout, CFSTR("%@\n"), newValue);
346 CFRelease(newValue);
347 return;
348 }
349
350
351 __private_extern__
352 void
353 do_remove(int argc, char **argv)
354 {
355 #pragma unused(argc)
356 CFStringRef key;
357
358 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
359 if (!SCDynamicStoreRemoveValue(store, key)) {
360 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
361 }
362 CFRelease(key);
363 return;
364 }
365
366
367 __private_extern__
368 void
369 do_notify(int argc, char **argv)
370 {
371 #pragma unused(argc)
372 CFStringRef key;
373
374 key = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
375 if (!SCDynamicStoreNotifyValue(store, key)) {
376 SCPrint(TRUE, stdout, CFSTR(" %s\n"), SCErrorString(SCError()));
377 }
378 CFRelease(key);
379 return;
380 }