2 * Copyright(c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1(the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 * Modification History
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
29 * November 16, 2000 Allan Nathanson <ajn@apple.com>
33 #include <SystemConfiguration/SystemConfiguration.h>
34 #include <SystemConfiguration/SCPrivate.h>
37 normalizePath(CFStringRef path
)
39 CFArrayRef tmpElements
;
40 CFMutableArrayRef elements
;
44 if (!CFStringHasPrefix(path
, CFSTR("/"))) {
45 /* if no root separator */
49 tmpElements
= CFStringCreateArrayBySeparatingStrings(NULL
, path
, CFSTR("/"));
50 elements
= CFArrayCreateMutableCopy(NULL
, 0, tmpElements
);
51 CFRelease(tmpElements
);
53 /* remove empty path components */
54 nElements
= CFArrayGetCount(elements
);
55 for (i
=nElements
; i
>0; i
--) {
56 CFStringRef pathElement
;
58 pathElement
= CFArrayGetValueAtIndex(elements
, i
-1);
59 if (CFStringGetLength(pathElement
) == 0) {
60 CFArrayRemoveValueAtIndex(elements
, i
-1);
75 getPath(SCPreferencesRef session
, CFStringRef path
, CFMutableDictionaryRef
*entity
)
80 int status
= kSCStatusFailed
;
81 CFMutableDictionaryRef value
= NULL
;
83 elements
= normalizePath(path
);
84 if (elements
== NULL
) {
85 return kSCStatusNoKey
;
88 /* get preferences key */
89 value
= (CFMutableDictionaryRef
)SCPreferencesGetValue(session
,
90 CFArrayGetValueAtIndex(elements
, 0));
92 status
= kSCStatusNoKey
;
96 if (CFGetTypeID(value
) != CFDictionaryGetTypeID()) {
97 status
= kSCStatusNoKey
;
101 nElements
= CFArrayGetCount(elements
);
102 for (i
=1; i
<nElements
; i
++) {
105 element
= CFArrayGetValueAtIndex(elements
, i
);
106 value
= (CFMutableDictionaryRef
)CFDictionaryGetValue(value
, element
);
108 /* if (parent) path component does not exist */
109 status
= kSCStatusNoKey
;
113 if (CFGetTypeID(value
) != CFDictionaryGetTypeID()) {
114 status
= kSCStatusNoKey
;
121 status
= kSCStatusOK
;
131 SCPreferencesPathCreateUniqueChild(SCPreferencesRef session
,
135 CFMutableDictionaryRef value
;
136 CFStringRef newPath
= NULL
;
137 Boolean newValue
= FALSE
;
139 CFMutableDictionaryRef newDict
= NULL
;
141 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesPathCreateUniqueChild:"));
142 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" prefix = %@"), prefix
);
144 status
= getPath(session
, prefix
, &value
);
148 case kSCStatusNoKey
:
149 value
= CFDictionaryCreateMutable(NULL
,
151 &kCFTypeDictionaryKeyCallBacks
,
152 &kCFTypeDictionaryValueCallBacks
);
159 if (CFGetTypeID(value
) != CFDictionaryGetTypeID()) {
160 /* if specified path is not a dictionary */
161 status
= kSCStatusNoKey
;
165 if (CFDictionaryContainsKey(value
, kSCResvLink
)) {
166 /* the path is a link... */
167 status
= kSCStatusFailed
;
173 CFStringRef pathComponent
;
176 pathComponent
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), i
);
177 found
= CFDictionaryContainsKey(value
, pathComponent
);
178 CFRelease(pathComponent
);
181 /* if we've identified the next unique key */
182 newPath
= CFStringCreateWithFormat(NULL
,
192 /* save the new dictionary */
193 newDict
= CFDictionaryCreateMutable(NULL
,
195 &kCFTypeDictionaryKeyCallBacks
,
196 &kCFTypeDictionaryValueCallBacks
);
197 if (!SCPreferencesPathSetValue(session
, newPath
, newDict
)) {
202 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" child = %@"), newPath
);
203 if (newValue
) CFRelease(value
);
208 if (newDict
) CFRelease(newDict
);
209 if (newValue
) CFRelease(value
);
210 if (newPath
) CFRelease(newPath
);
216 SCPreferencesPathGetValue(SCPreferencesRef session
,
220 CFMutableDictionaryRef entity
;
221 CFStringRef entityLink
;
223 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesPathGetValue:"));
224 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" path = %@"), path
);
226 status
= getPath(session
, path
, &entity
);
227 if (status
!= kSCStatusOK
) {
231 /* XXXX Add code here to chase multiple links XXXXX */
233 if ((CFGetTypeID(entity
) == CFDictionaryGetTypeID()) &&
234 (CFDictionaryGetValueIfPresent(entity
, kSCResvLink
, (void **)&entityLink
))) {
235 /* if this is a dictionary AND it is a link */
236 status
= getPath(session
, entityLink
, &entity
);
237 if (status
!= kSCStatusOK
) {
238 /* if it was a bad link */
243 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" value = %@"), entity
);
249 SCPreferencesPathGetLink(SCPreferencesRef session
,
253 CFMutableDictionaryRef entity
;
254 CFStringRef entityLink
;
256 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesPathGetLink:"));
257 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" path = %@"), path
);
259 status
= getPath(session
, path
, &entity
);
260 if (status
!= kSCStatusOK
) {
264 if ((CFGetTypeID(entity
) == CFDictionaryGetTypeID()) &&
265 (CFDictionaryGetValueIfPresent(entity
, kSCResvLink
, (void **)&entityLink
))) {
266 /* if this is a dictionary AND it is a link */
267 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" link = %@"), entityLink
);
276 SCPreferencesPathSetValue(SCPreferencesRef session
,
278 CFDictionaryRef value
)
280 CFMutableDictionaryRef element
;
281 CFArrayRef elements
= NULL
;
284 Boolean newRoot
= FALSE
;
286 CFMutableDictionaryRef root
= NULL
;
288 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesPathSetValue:"));
289 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" path = %@"), path
);
290 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" value = %@"), value
);
292 elements
= normalizePath(path
);
293 if (elements
== NULL
) {
294 _SCErrorSet(kSCStatusNoKey
);
298 /* get preferences key */
299 root
= (CFMutableDictionaryRef
)SCPreferencesGetValue(session
,
300 CFArrayGetValueAtIndex(elements
, 0));
302 root
= CFDictionaryCreateMutable(NULL
,
304 &kCFTypeDictionaryKeyCallBacks
,
305 &kCFTypeDictionaryValueCallBacks
);
309 nElements
= CFArrayGetCount(elements
);
310 if (nElements
== 1) {
311 /* if we are only updating the data associated with the preference key */
316 root
= (CFMutableDictionaryRef
)value
;
320 for (i
=1; i
<nElements
-1; i
++) {
321 CFStringRef pathComponent
;
322 CFMutableDictionaryRef tmpElement
;
324 pathComponent
= CFArrayGetValueAtIndex(elements
, i
);
325 tmpElement
= (void *)CFDictionaryGetValue(element
, pathComponent
);
326 if (tmpElement
== NULL
) {
327 /* if (parent) path component does not exist */
328 tmpElement
= CFDictionaryCreateMutable(NULL
,
330 &kCFTypeDictionaryKeyCallBacks
,
331 &kCFTypeDictionaryValueCallBacks
);
332 CFDictionarySetValue(element
, pathComponent
, tmpElement
);
333 CFRelease(tmpElement
);
335 element
= tmpElement
;
339 CFDictionarySetValue(element
,
340 CFArrayGetValueAtIndex(elements
, nElements
-1),
343 ok
= SCPreferencesSetValue(session
, CFArrayGetValueAtIndex(elements
, 0), root
);
344 if (newRoot
) CFRelease(root
);
351 SCPreferencesPathSetLink(SCPreferencesRef session
,
355 CFMutableDictionaryRef dict
;
358 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesPathSetLink:"));
359 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" path = %@"), path
);
360 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" link = %@"), link
);
362 dict
= CFDictionaryCreateMutable(NULL
,
364 &kCFTypeDictionaryKeyCallBacks
,
365 &kCFTypeDictionaryValueCallBacks
);
366 CFDictionaryAddValue(dict
, kSCResvLink
, link
);
367 ok
= SCPreferencesPathSetValue(session
, path
, dict
);
375 SCPreferencesPathRemoveValue(SCPreferencesRef session
,
378 CFMutableDictionaryRef element
;
379 CFArrayRef elements
= NULL
;
383 CFMutableDictionaryRef root
= NULL
;
385 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR("SCPreferencesPathRemoveValue:"));
386 SCLog(_sc_verbose
, LOG_DEBUG
, CFSTR(" path = %@"), path
);
388 elements
= normalizePath(path
);
389 if (elements
== NULL
) {
390 _SCErrorSet(kSCStatusNoKey
);
394 /* get preferences key */
395 root
= (CFMutableDictionaryRef
)SCPreferencesGetValue(session
,
396 CFArrayGetValueAtIndex(elements
, 0));
401 nElements
= CFArrayGetCount(elements
);
402 if (nElements
== 1) {
403 /* if we are removing the data associated with the preference key */
404 ok
= SCPreferencesRemoveValue(session
, CFArrayGetValueAtIndex(elements
, 0));
409 for (i
=1; i
<nElements
-1; i
++) {
410 CFStringRef pathComponent
;
411 CFMutableDictionaryRef tmpElement
;
413 pathComponent
= CFArrayGetValueAtIndex(elements
, i
);
414 tmpElement
= (void *)CFDictionaryGetValue(element
, pathComponent
);
415 if (tmpElement
== NULL
) {
418 element
= tmpElement
;
421 CFDictionaryRemoveValue(element
,
422 CFArrayGetValueAtIndex(elements
, nElements
-1));
423 ok
= SCPreferencesSetValue(session
, CFArrayGetValueAtIndex(elements
, 0), root
);