]>
Commit | Line | Data |
---|---|---|
5958d7c0 A |
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 | #include "configd.h" | |
24 | #include "session.h" | |
25 | ||
26 | SCDStatus | |
27 | _SCDList(SCDSessionRef session, CFStringRef key, int regexOptions, CFArrayRef *subKeys) | |
28 | { | |
29 | SCDSessionPrivateRef sessionPrivate = (SCDSessionPrivateRef)session; | |
30 | CFIndex cacheCnt; | |
31 | void **cacheKeys; | |
32 | void **cacheValues; | |
33 | CFMutableArrayRef keyArray; | |
34 | int i; | |
35 | CFStringRef cacheStr; | |
36 | CFDictionaryRef cacheValue; | |
37 | int regexStrLen; | |
38 | char *regexStr = NULL; | |
39 | regex_t preg; | |
40 | int reError; | |
41 | char reErrBuf[256]; | |
42 | int reErrStrLen; | |
43 | ||
44 | SCDLog(LOG_DEBUG, CFSTR("_SCDList:")); | |
45 | SCDLog(LOG_DEBUG, CFSTR(" key = %@"), key); | |
46 | SCDLog(LOG_DEBUG, CFSTR(" regexOptions = %0o"), regexOptions); | |
47 | ||
48 | if ((session == NULL) || (sessionPrivate->server == MACH_PORT_NULL)) { | |
49 | return SCD_NOSESSION; | |
50 | } | |
51 | ||
52 | cacheCnt = CFDictionaryGetCount(cacheData); | |
53 | keyArray = CFArrayCreateMutable(NULL, cacheCnt, &kCFTypeArrayCallBacks); | |
54 | ||
55 | if (regexOptions & kSCDRegexKey) { | |
56 | /* | |
57 | * compile the provided regular expression using the | |
58 | * provided regexOptions (passing only those flags | |
59 | * which would make sense). | |
60 | */ | |
61 | regexStrLen = CFStringGetLength(key) + 1; | |
62 | regexStr = CFAllocatorAllocate(NULL, regexStrLen, 0); | |
63 | if (!CFStringGetCString(key, | |
64 | regexStr, | |
65 | regexStrLen, | |
66 | kCFStringEncodingMacRoman)) { | |
67 | SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString() key: could not convert to regex string")); | |
68 | CFAllocatorDeallocate(NULL, regexStr); | |
69 | return SCD_FAILED; | |
70 | } | |
71 | ||
72 | reError = regcomp(&preg, regexStr, REG_EXTENDED); | |
73 | if (reError != 0) { | |
74 | reErrStrLen = regerror(reError, &preg, reErrBuf, sizeof(reErrBuf)); | |
75 | cacheStr = CFStringCreateWithCString(NULL, reErrBuf, kCFStringEncodingMacRoman); | |
76 | CFArrayAppendValue(keyArray, cacheStr); | |
77 | CFRelease(cacheStr); | |
78 | *subKeys = CFArrayCreateCopy(NULL, keyArray); | |
79 | CFRelease(keyArray); | |
80 | CFAllocatorDeallocate(NULL, regexStr); | |
81 | return SCD_FAILED; | |
82 | } | |
83 | } | |
84 | ||
85 | cacheKeys = CFAllocatorAllocate(NULL, cacheCnt * sizeof(CFStringRef), 0); | |
86 | cacheValues = CFAllocatorAllocate(NULL, cacheCnt * sizeof(CFStringRef), 0); | |
87 | CFDictionaryGetKeysAndValues(cacheData, cacheKeys, cacheValues); | |
88 | for (i=0; i<cacheCnt; i++) { | |
89 | cacheStr = (CFStringRef)cacheKeys[i]; | |
90 | cacheValue = (CFDictionaryRef)cacheValues[i]; | |
91 | if (regexOptions & kSCDRegexKey) { | |
92 | /* | |
93 | * only return those keys which match the regular | |
94 | * expression specified in the provided key. | |
95 | */ | |
96 | ||
97 | int cacheKeyLen = CFStringGetLength(cacheStr) + 1; | |
98 | char *cacheKey = CFAllocatorAllocate(NULL, cacheKeyLen, 0); | |
99 | ||
100 | if (!CFStringGetCString(cacheStr, | |
101 | cacheKey, | |
102 | cacheKeyLen, | |
103 | kCFStringEncodingMacRoman)) { | |
104 | SCDLog(LOG_DEBUG, CFSTR("CFStringGetCString: could not convert cache key to C string")); | |
105 | CFAllocatorDeallocate(NULL, cacheKey); | |
106 | continue; | |
107 | } | |
108 | ||
109 | reError = regexec(&preg, | |
110 | cacheKey, | |
111 | 0, | |
112 | NULL, | |
113 | 0); | |
114 | switch (reError) { | |
115 | case 0 : | |
116 | /* we've got a match */ | |
117 | if (CFDictionaryContainsKey(cacheValue, kSCDData)) | |
118 | CFArrayAppendValue(keyArray, cacheStr); | |
119 | break; | |
120 | case REG_NOMATCH : | |
121 | /* no match */ | |
122 | break; | |
123 | default : | |
124 | reErrStrLen = regerror(reError, | |
125 | &preg, | |
126 | reErrBuf, | |
127 | sizeof(reErrBuf)); | |
128 | SCDLog(LOG_DEBUG, CFSTR("regexec(): %s"), reErrBuf); | |
129 | break; | |
130 | } | |
131 | CFAllocatorDeallocate(NULL, cacheKey); | |
132 | } else { | |
133 | /* | |
134 | * only return those keys which are prefixed by the | |
135 | * provided key string and have data. | |
136 | */ | |
137 | if (((CFStringGetLength(key) == 0) || CFStringHasPrefix(cacheStr, key)) && | |
138 | CFDictionaryContainsKey(cacheValue, kSCDData)) { | |
139 | CFArrayAppendValue(keyArray, cacheStr); | |
140 | } | |
141 | } | |
142 | } | |
143 | CFAllocatorDeallocate(NULL, cacheKeys); | |
144 | CFAllocatorDeallocate(NULL, cacheValues); | |
145 | ||
146 | if (regexOptions & kSCDRegexKey) { | |
147 | regfree(&preg); | |
148 | } | |
149 | ||
150 | *subKeys = keyArray; | |
151 | ||
152 | if (regexOptions & kSCDRegexKey) { | |
153 | CFAllocatorDeallocate(NULL, regexStr); | |
154 | } | |
155 | ||
156 | return SCD_OK; | |
157 | } | |
158 | ||
159 | ||
160 | kern_return_t | |
161 | _configlist(mach_port_t server, | |
162 | xmlData_t keyRef, /* raw XML bytes */ | |
163 | mach_msg_type_number_t keyLen, | |
164 | int regexOptions, | |
165 | xmlDataOut_t *listRef, /* raw XML bytes */ | |
166 | mach_msg_type_number_t *listLen, | |
167 | int *scd_status | |
168 | ) | |
169 | { | |
170 | kern_return_t status; | |
171 | serverSessionRef mySession = getSession(server); | |
172 | CFDataRef xmlKey; /* key (XML serialized) */ | |
173 | CFStringRef key; /* key (un-serialized) */ | |
174 | CFArrayRef subKeys; /* array of CFStringRef's */ | |
175 | CFDataRef xmlList; /* list (XML serialized) */ | |
176 | CFStringRef xmlError; | |
177 | ||
178 | SCDLog(LOG_DEBUG, CFSTR("List keys in configuration database.")); | |
179 | SCDLog(LOG_DEBUG, CFSTR(" server = %d"), server); | |
180 | ||
181 | /* un-serialize the key */ | |
182 | xmlKey = CFDataCreate(NULL, keyRef, keyLen); | |
183 | status = vm_deallocate(mach_task_self(), (vm_address_t)keyRef, keyLen); | |
184 | if (status != KERN_SUCCESS) { | |
185 | SCDLog(LOG_DEBUG, CFSTR("vm_deallocate(): %s"), mach_error_string(status)); | |
186 | /* non-fatal???, proceed */ | |
187 | } | |
188 | key = CFPropertyListCreateFromXMLData(NULL, | |
189 | xmlKey, | |
190 | kCFPropertyListImmutable, | |
191 | &xmlError); | |
192 | CFRelease(xmlKey); | |
193 | if (xmlError) { | |
194 | SCDLog(LOG_DEBUG, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError); | |
195 | *scd_status = SCD_FAILED; | |
196 | return KERN_SUCCESS; | |
197 | } | |
198 | ||
199 | *scd_status = _SCDList(mySession->session, key, regexOptions, &subKeys); | |
200 | CFRelease(key); | |
201 | if (*scd_status != SCD_OK) { | |
202 | *listRef = NULL; | |
203 | *listLen = 0; | |
204 | return KERN_SUCCESS; | |
205 | } | |
206 | ||
207 | /* | |
208 | * serialize the array, copy it into an allocated buffer which will be | |
209 | * released when it is returned as part of a Mach message. | |
210 | */ | |
211 | xmlList = CFPropertyListCreateXMLData(NULL, subKeys); | |
212 | CFRelease(subKeys); | |
213 | *listLen = CFDataGetLength(xmlList); | |
214 | status = vm_allocate(mach_task_self(), (void *)listRef, *listLen, TRUE); | |
215 | if (status != KERN_SUCCESS) { | |
216 | SCDLog(LOG_DEBUG, CFSTR("vm_allocate(): %s"), mach_error_string(status)); | |
217 | *scd_status = SCD_FAILED; | |
218 | CFRelease(xmlList); | |
219 | *listRef = NULL; | |
220 | *listLen = 0; | |
221 | return KERN_SUCCESS; | |
222 | } | |
223 | bcopy((char *)CFDataGetBytePtr(xmlList), *listRef, *listLen); | |
224 | CFRelease(xmlList); | |
225 | ||
226 | return KERN_SUCCESS; | |
227 | } |