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 * March 24, 2000 Allan Nathanson <ajn@apple.com>
37 __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store
, CFStringRef key
, Boolean isRegex
, CFArrayRef
*subKeys
)
39 SCDynamicStorePrivateRef storePrivate
= (SCDynamicStorePrivateRef
)store
;
43 CFMutableArrayRef keyArray
;
46 CFDictionaryRef storeValue
;
48 char *regexBuf
= NULL
;
54 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("__SCDynamicStoreCopyKeyList:"));
55 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" key = %@"), key
);
56 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" isRegex = %s"), isRegex
? "TRUE" : "FALSE");
58 if (!store
|| (storePrivate
->server
== MACH_PORT_NULL
)) {
59 return kSCStatusNoStoreSession
; /* you must have an open session to play */
62 storeCnt
= CFDictionaryGetCount(storeData
);
63 keyArray
= CFArrayCreateMutable(NULL
, storeCnt
, &kCFTypeArrayCallBacks
);
70 CFMutableStringRef regexStr
;
72 regexStr
= CFStringCreateMutableCopy(NULL
, 0, key
);
73 regexLen
= CFStringGetLength(regexStr
);
75 ch_s
= CFStringGetCharacterAtIndex(regexStr
, 0);
76 ch_e
= CFStringGetCharacterAtIndex(regexStr
, regexLen
- 1);
78 if ((regexLen
== 0) || ((ch_s
!= (UniChar
)'^') && (ch_e
!= (UniChar
)'$'))) {
79 /* if regex pattern is not already bounded */
80 CFStringInsert(regexStr
, 0, CFSTR("^"));
81 CFStringAppend(regexStr
, CFSTR("$"));
85 * compile the provided regular expression using the
88 regexBufLen
= CFStringGetLength(regexStr
)+1;
89 regexBuf
= CFAllocatorAllocate(NULL
, regexBufLen
, 0);
90 ok
= CFStringGetCString(regexStr
, regexBuf
, regexBufLen
, kCFStringEncodingMacRoman
);
93 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("CFStringGetCString() key: could not convert to regex string"));
94 CFAllocatorDeallocate(NULL
, regexBuf
);
95 return kSCStatusFailed
;
98 reError
= regcomp(&preg
, regexBuf
, REG_EXTENDED
);
100 reErrStrLen
= regerror(reError
, &preg
, reErrBuf
, sizeof(reErrBuf
));
101 storeStr
= CFStringCreateWithCString(NULL
, reErrBuf
, kCFStringEncodingMacRoman
);
102 CFArrayAppendValue(keyArray
, storeStr
);
104 *subKeys
= CFArrayCreateCopy(NULL
, keyArray
);
106 CFAllocatorDeallocate(NULL
, regexBuf
);
107 return kSCStatusFailed
;
111 storeKeys
= CFAllocatorAllocate(NULL
, storeCnt
* sizeof(CFStringRef
), 0);
112 storeValues
= CFAllocatorAllocate(NULL
, storeCnt
* sizeof(CFStringRef
), 0);
113 CFDictionaryGetKeysAndValues(storeData
, storeKeys
, storeValues
);
114 for (i
=0; i
<storeCnt
; i
++) {
115 storeStr
= (CFStringRef
)storeKeys
[i
];
116 storeValue
= (CFDictionaryRef
)storeValues
[i
];
119 * only return those keys which match the regular
120 * expression specified in the provided key.
123 int storeKeyLen
= CFStringGetLength(storeStr
) + 1;
124 char *storeKey
= CFAllocatorAllocate(NULL
, storeKeyLen
, 0);
126 if (!CFStringGetCString(storeStr
,
129 kCFStringEncodingMacRoman
)) {
130 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("CFStringGetCString: could not convert store key to C string"));
131 CFAllocatorDeallocate(NULL
, storeKey
);
135 reError
= regexec(&preg
,
142 /* we've got a match */
143 if (CFDictionaryContainsKey(storeValue
, kSCDData
))
144 CFArrayAppendValue(keyArray
, storeStr
);
150 reErrStrLen
= regerror(reError
,
154 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("regexec(): %s"), reErrBuf
);
157 CFAllocatorDeallocate(NULL
, storeKey
);
160 * only return those keys which are prefixed by the
161 * provided key string and have data.
163 if (((CFStringGetLength(key
) == 0) || CFStringHasPrefix(storeStr
, key
)) &&
164 CFDictionaryContainsKey(storeValue
, kSCDData
)) {
165 CFArrayAppendValue(keyArray
, storeStr
);
169 CFAllocatorDeallocate(NULL
, storeKeys
);
170 CFAllocatorDeallocate(NULL
, storeValues
);
174 CFAllocatorDeallocate(NULL
, regexBuf
);
184 _configlist(mach_port_t server
,
185 xmlData_t keyRef
, /* raw XML bytes */
186 mach_msg_type_number_t keyLen
,
188 xmlDataOut_t
*listRef
, /* raw XML bytes */
189 mach_msg_type_number_t
*listLen
,
193 kern_return_t status
;
194 serverSessionRef mySession
= getSession(server
);
195 CFDataRef xmlKey
; /* key (XML serialized) */
196 CFStringRef key
; /* key (un-serialized) */
197 CFArrayRef subKeys
; /* array of CFStringRef's */
198 CFDataRef xmlList
; /* list (XML serialized) */
199 CFStringRef xmlError
;
201 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("List keys in configuration database."));
202 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR(" server = %d"), server
);
207 /* un-serialize the key */
208 xmlKey
= CFDataCreate(NULL
, keyRef
, keyLen
);
209 status
= vm_deallocate(mach_task_self(), (vm_address_t
)keyRef
, keyLen
);
210 if (status
!= KERN_SUCCESS
) {
211 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
212 /* non-fatal???, proceed */
214 key
= CFPropertyListCreateFromXMLData(NULL
,
216 kCFPropertyListImmutable
,
221 SCLog(_configd_verbose
, LOG_DEBUG
,
222 CFSTR("CFPropertyListCreateFromXMLData() key: %@"),
226 *sc_status
= kSCStatusFailed
;
228 } else if (!isA_CFString(key
)) {
230 *sc_status
= kSCStatusInvalidArgument
;
234 *sc_status
= __SCDynamicStoreCopyKeyList(mySession
->store
, key
, isRegex
, &subKeys
);
236 if (*sc_status
!= kSCStatusOK
) {
241 * serialize the array, copy it into an allocated buffer which will be
242 * released when it is returned as part of a Mach message.
244 xmlList
= CFPropertyListCreateXMLData(NULL
, subKeys
);
246 *listLen
= CFDataGetLength(xmlList
);
247 status
= vm_allocate(mach_task_self(), (void *)listRef
, *listLen
, TRUE
);
248 if (status
!= KERN_SUCCESS
) {
249 SCLog(_configd_verbose
, LOG_DEBUG
, CFSTR("vm_allocate(): %s"), mach_error_string(status
));
250 *sc_status
= kSCStatusFailed
;
256 bcopy((char *)CFDataGetBytePtr(xmlList
), *listRef
, *listLen
);