2 * Copyright (c) 2000-2005, 2011, 2017, 2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * June 1, 2001 Allan Nathanson <ajn@apple.com>
28 * - public API conversion
30 * November 9, 2000 Allan Nathanson <ajn@apple.com>
34 #include <sys/types.h>
38 #include "SCDynamicStoreInternal.h"
42 #pragma mark SCDynamicStore "cache"
46 #pragma mark SCDynamicStore operations
51 do_block(int argc
, char **argv
)
53 Boolean enable
= FALSE
;
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)) {
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)) {
67 SCPrint(TRUE
, stdout
, CFSTR("invalid value\n"));
71 enable
= !_SCDynamicStoreCacheIsActive(store
); // toggle
75 // begin block of SCDynamicStore operations
76 if (_SCDynamicStoreCacheIsActive(store
)) {
77 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(kSCStatusLocked
));
81 SCPrint(TRUE
, stdout
, CFSTR("Begin block of SCDynamicStore operations\n"));
83 _SCDynamicStoreCacheOpen(store
);
86 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
88 // end block of SCDynamicStore operations
89 if (!_SCDynamicStoreCacheIsActive(store
)) {
90 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(kSCStatusNeedLock
));
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;
101 SCPrint(TRUE
, stdout
,
102 CFSTR("End block of SCDynamicStore operations%s\n"),
103 (n
> 0) ? ", posting changes" : "");
105 _SCDynamicStoreCacheCommitChanges(store
);
107 _SCDynamicStoreCacheClose(store
);
114 static CFComparisonResult
115 sort_keys(const void *p1
, const void *p2
, void *context
)
117 #pragma unused(context)
118 CFStringRef key1
= (CFStringRef
)p1
;
119 CFStringRef key2
= (CFStringRef
)p2
;
120 return CFStringCompare(key1
, key2
, 0);
129 do_list(int argc
, char **argv
)
135 CFMutableArrayRef sortedList
;
136 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
138 pattern
= CFStringCreateWithCString(NULL
,
139 (argc
>= 1) ? argv
[0] : ".*",
140 kCFStringEncodingUTF8
);
142 list
= SCDynamicStoreCopyKeyList(store
, pattern
);
145 if (SCError() != kSCStatusOK
) {
146 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
149 if (!_SCDynamicStoreCacheIsActive(store
)) {
150 SCPrint(TRUE
, stdout
, CFSTR(" no keys.\n"));
155 n
= (storePrivate
->cached_set
!= NULL
)
156 ? CFDictionaryGetCount(storePrivate
->cached_set
) : 0;
158 const void * cachedKeys_q
[N_QUICK
];
159 const void ** cachedKeys
= cachedKeys_q
;
161 if (n
> (CFIndex
)(sizeof(cachedKeys_q
) / sizeof(CFStringRef
))) {
162 cachedKeys
= CFAllocatorAllocate(NULL
, n
* sizeof(CFStringRef
), 0);
164 CFDictionaryGetKeysAndValues(storePrivate
->cached_set
, cachedKeys
, NULL
);
165 list
= CFArrayCreate(NULL
, cachedKeys
, n
, &kCFTypeArrayCallBacks
);
166 if (cachedKeys
!= cachedKeys_q
) {
167 CFAllocatorDeallocate(NULL
, cachedKeys
);
170 SCPrint(TRUE
, stdout
, CFSTR(" no keys.\n"));
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"));
184 listCnt
= CFArrayGetCount(list
);
185 sortedList
= CFArrayCreateMutableCopy(NULL
, listCnt
, list
);
187 CFArraySortValues(sortedList
,
188 CFRangeMake(0, listCnt
),
193 for (i
= 0; i
< listCnt
; i
++) {
196 CFSTR(" subKey [%d] = %@\n"),
198 CFArrayGetValueAtIndex(sortedList
, i
));
201 SCPrint(TRUE
, stdout
, CFSTR(" no keys.\n"));
203 CFRelease(sortedList
);
211 do_add(int argc
, char **argv
)
215 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
218 if (!_SCDynamicStoreCacheIsActive(store
)) {
219 if (!SCDynamicStoreAddValue(store
, key
, value
)) {
220 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
223 SCPrint(TRUE
, stdout
, CFSTR(" Cannot \"add\" with block\n"));
226 if (!_SCDynamicStoreCacheIsActive(store
)) {
227 if (!SCDynamicStoreAddTemporaryValue(store
, key
, value
)) {
228 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
231 SCPrint(TRUE
, stdout
, CFSTR(" Cannot \"add temporary\" with block\n"));
242 do_get(int argc
, char **argv
)
246 CFPropertyListRef newValue
;
248 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
249 newValue
= SCDynamicStoreCopyValue(store
, key
);
251 if (newValue
== NULL
) {
252 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
257 CFRelease(value
); /* we have new information, release the old */
267 do_set(int argc
, char **argv
)
272 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
273 if (!SCDynamicStoreSetValue(store
, key
, value
)) {
274 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
283 do_show(int argc
, char **argv
)
286 CFPropertyListRef newValue
;
288 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
291 newValue
= SCDynamicStoreCopyValue(store
, key
);
295 patterns
= CFArrayCreate(NULL
, (const void **)&key
, 1, &kCFTypeArrayCallBacks
);
296 if (!_SCDynamicStoreCacheIsActive(store
)) {
297 newValue
= SCDynamicStoreCopyMultiple(store
, NULL
, patterns
);
300 CFMutableDictionaryRef newDict
;
301 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
303 newDict
= CFDictionaryCreateMutable(NULL
,
305 &kCFTypeDictionaryKeyCallBacks
,
306 &kCFTypeDictionaryValueCallBacks
);
307 keys
= SCDynamicStoreCopyKeyList(store
, key
);
312 n
= CFArrayGetCount(keys
);
313 for (i
= 0; i
< n
; i
++) {
314 CFStringRef storeKey
;
317 storeKey
= CFArrayGetValueAtIndex(keys
, i
);
318 storeVal
= SCDynamicStoreCopyValue(store
, storeKey
);
319 if (storeVal
!= NULL
) {
320 CFDictionarySetValue(newDict
, storeKey
, storeVal
);
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"));
340 if (newValue
== NULL
) {
341 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
345 SCPrint(TRUE
, stdout
, CFSTR("%@\n"), newValue
);
353 do_remove(int argc
, char **argv
)
358 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
359 if (!SCDynamicStoreRemoveValue(store
, key
)) {
360 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));
369 do_notify(int argc
, char **argv
)
374 key
= CFStringCreateWithCString(NULL
, argv
[0], kCFStringEncodingUTF8
);
375 if (!SCDynamicStoreNotifyValue(store
, key
)) {
376 SCPrint(TRUE
, stdout
, CFSTR(" %s\n"), SCErrorString(SCError()));