]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/_configlist.c
configd-42.tar.gz
[apple/configd.git] / configd.tproj / _configlist.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * Modification History
25 *
26 * June 1, 2001 Allan Nathanson <ajn@apple.com>
27 * - public API conversion
28 *
29 * March 24, 2000 Allan Nathanson <ajn@apple.com>
30 * - initial revision
31 */
32
33 #include "configd.h"
34 #include "session.h"
35
36 int
37 __SCDynamicStoreCopyKeyList(SCDynamicStoreRef store, CFStringRef key, Boolean isRegex, CFArrayRef *subKeys)
38 {
39 SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
40 CFIndex storeCnt;
41 void **storeKeys;
42 void **storeValues;
43 CFMutableArrayRef keyArray;
44 int i;
45 CFStringRef storeStr;
46 CFDictionaryRef storeValue;
47 int regexBufLen;
48 char *regexBuf = NULL;
49 regex_t preg;
50 int reError;
51 char reErrBuf[256];
52 int reErrStrLen;
53
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");
57
58 if (!store || (storePrivate->server == MACH_PORT_NULL)) {
59 return kSCStatusNoStoreSession; /* you must have an open session to play */
60 }
61
62 storeCnt = CFDictionaryGetCount(storeData);
63 keyArray = CFArrayCreateMutable(NULL, storeCnt, &kCFTypeArrayCallBacks);
64
65 if (isRegex) {
66 UniChar ch_s = 0;
67 UniChar ch_e = 0;
68 Boolean ok;
69 CFIndex regexLen;
70 CFMutableStringRef regexStr;
71
72 regexStr = CFStringCreateMutableCopy(NULL, 0, key);
73 regexLen = CFStringGetLength(regexStr);
74 if (regexLen > 0) {
75 ch_s = CFStringGetCharacterAtIndex(regexStr, 0);
76 ch_e = CFStringGetCharacterAtIndex(regexStr, regexLen - 1);
77 }
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("$"));
82 }
83
84 /*
85 * compile the provided regular expression using the
86 * provided isRegex.
87 */
88 regexBufLen = CFStringGetLength(regexStr)+1;
89 regexBuf = CFAllocatorAllocate(NULL, regexBufLen, 0);
90 ok = CFStringGetCString(regexStr, regexBuf, regexBufLen, kCFStringEncodingMacRoman);
91 CFRelease(regexStr);
92 if (!ok) {
93 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString() key: could not convert to regex string"));
94 CFAllocatorDeallocate(NULL, regexBuf);
95 return kSCStatusFailed;
96 }
97
98 reError = regcomp(&preg, regexBuf, REG_EXTENDED);
99 if (reError != 0) {
100 reErrStrLen = regerror(reError, &preg, reErrBuf, sizeof(reErrBuf));
101 storeStr = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingMacRoman);
102 CFArrayAppendValue(keyArray, storeStr);
103 CFRelease(storeStr);
104 *subKeys = CFArrayCreateCopy(NULL, keyArray);
105 CFRelease(keyArray);
106 CFAllocatorDeallocate(NULL, regexBuf);
107 return kSCStatusFailed;
108 }
109 }
110
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];
117 if (isRegex) {
118 /*
119 * only return those keys which match the regular
120 * expression specified in the provided key.
121 */
122
123 int storeKeyLen = CFStringGetLength(storeStr) + 1;
124 char *storeKey = CFAllocatorAllocate(NULL, storeKeyLen, 0);
125
126 if (!CFStringGetCString(storeStr,
127 storeKey,
128 storeKeyLen,
129 kCFStringEncodingMacRoman)) {
130 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("CFStringGetCString: could not convert store key to C string"));
131 CFAllocatorDeallocate(NULL, storeKey);
132 continue;
133 }
134
135 reError = regexec(&preg,
136 storeKey,
137 0,
138 NULL,
139 0);
140 switch (reError) {
141 case 0 :
142 /* we've got a match */
143 if (CFDictionaryContainsKey(storeValue, kSCDData))
144 CFArrayAppendValue(keyArray, storeStr);
145 break;
146 case REG_NOMATCH :
147 /* no match */
148 break;
149 default :
150 reErrStrLen = regerror(reError,
151 &preg,
152 reErrBuf,
153 sizeof(reErrBuf));
154 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf);
155 break;
156 }
157 CFAllocatorDeallocate(NULL, storeKey);
158 } else {
159 /*
160 * only return those keys which are prefixed by the
161 * provided key string and have data.
162 */
163 if (((CFStringGetLength(key) == 0) || CFStringHasPrefix(storeStr, key)) &&
164 CFDictionaryContainsKey(storeValue, kSCDData)) {
165 CFArrayAppendValue(keyArray, storeStr);
166 }
167 }
168 }
169 CFAllocatorDeallocate(NULL, storeKeys);
170 CFAllocatorDeallocate(NULL, storeValues);
171
172 if (isRegex) {
173 regfree(&preg);
174 CFAllocatorDeallocate(NULL, regexBuf);
175 }
176
177 *subKeys = keyArray;
178
179 return kSCStatusOK;
180 }
181
182
183 kern_return_t
184 _configlist(mach_port_t server,
185 xmlData_t keyRef, /* raw XML bytes */
186 mach_msg_type_number_t keyLen,
187 int isRegex,
188 xmlDataOut_t *listRef, /* raw XML bytes */
189 mach_msg_type_number_t *listLen,
190 int *sc_status
191 )
192 {
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;
200
201 SCLog(_configd_verbose, LOG_DEBUG, CFSTR("List keys in configuration database."));
202 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" server = %d"), server);
203
204 *listRef = NULL;
205 *listLen = 0;
206
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 */
213 }
214 key = CFPropertyListCreateFromXMLData(NULL,
215 xmlKey,
216 kCFPropertyListImmutable,
217 &xmlError);
218 CFRelease(xmlKey);
219 if (!key) {
220 if (xmlError) {
221 SCLog(_configd_verbose, LOG_DEBUG,
222 CFSTR("CFPropertyListCreateFromXMLData() key: %@"),
223 xmlError);
224 CFRelease(xmlError);
225 }
226 *sc_status = kSCStatusFailed;
227 return KERN_SUCCESS;
228 } else if (!isA_CFString(key)) {
229 CFRelease(key);
230 *sc_status = kSCStatusInvalidArgument;
231 return KERN_SUCCESS;
232 }
233
234 *sc_status = __SCDynamicStoreCopyKeyList(mySession->store, key, isRegex, &subKeys);
235 CFRelease(key);
236 if (*sc_status != kSCStatusOK) {
237 return KERN_SUCCESS;
238 }
239
240 /*
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.
243 */
244 xmlList = CFPropertyListCreateXMLData(NULL, subKeys);
245 CFRelease(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;
251 CFRelease(xmlList);
252 *listRef = NULL;
253 *listLen = 0;
254 return KERN_SUCCESS;
255 }
256 bcopy((char *)CFDataGetBytePtr(xmlList), *listRef, *listLen);
257 CFRelease(xmlList);
258
259 return KERN_SUCCESS;
260 }