]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_utilities/lib/cfutilities.cpp
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / cfutilities.cpp
1 /*
2 * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // CoreFoundation related utilities
27 //
28 #include <security_utilities/cfutilities.h>
29 #include <security_utilities/errors.h>
30 #include <security_utilities/debugging.h>
31 #include <cstdarg>
32 #include <vector>
33
34
35 namespace Security {
36
37
38 ModuleNexus<CFEmptyArray> cfEmptyArray;
39
40 CFEmptyArray::CFEmptyArray()
41 {
42 mArray = CFArrayCreate(NULL, NULL, 0, NULL);
43 }
44
45
46 //
47 // Turn a C(++) string into a CFURLRef indicating a file: path
48 //
49 CFURLRef makeCFURL(const char *s, bool isDirectory, CFURLRef base)
50 {
51 if (base)
52 return CFURLCreateWithFileSystemPathRelativeToBase(NULL,
53 CFTempString(s), kCFURLPOSIXPathStyle, isDirectory, base);
54 else
55 return CFURLCreateWithFileSystemPath(NULL,
56 CFTempString(s), kCFURLPOSIXPathStyle, isDirectory);
57 }
58
59 CFURLRef makeCFURL(CFStringRef s, bool isDirectory, CFURLRef base)
60 {
61 if (base)
62 return CFURLCreateWithFileSystemPathRelativeToBase(NULL, s, kCFURLPOSIXPathStyle, isDirectory, base);
63 else
64 return CFURLCreateWithFileSystemPath(NULL, s, kCFURLPOSIXPathStyle, isDirectory);
65 }
66
67
68 //
69 // CFMallocData objects
70 //
71 CFMallocData::operator CFDataRef ()
72 {
73 CFDataRef result = makeCFDataMalloc(mData, mSize);
74 if (!result)
75 CFError::throwMe();
76 mData = NULL; // release ownership
77 return result;
78 }
79
80
81 //
82 // Make CFDictionaries from stuff
83 //
84 CFDictionaryRef makeCFDictionary(unsigned count, ...)
85 {
86 CFTypeRef keys[count], values[count];
87 va_list args;
88 va_start(args, count);
89 for (unsigned n = 0; n < count; n++) {
90 keys[n] = va_arg(args, CFTypeRef);
91 values[n] = va_arg(args, CFTypeRef);
92 }
93 va_end(args);
94 return CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, count,
95 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
96 }
97
98 CFMutableDictionaryRef makeCFMutableDictionary()
99 {
100 if (CFMutableDictionaryRef r = CFDictionaryCreateMutable(NULL, 0,
101 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks))
102 return r;
103 CFError::throwMe();
104 }
105
106 CFMutableDictionaryRef makeCFMutableDictionary(unsigned count, ...)
107 {
108 CFMutableDictionaryRef dict = makeCFMutableDictionary();
109 if (count > 0) {
110 va_list args;
111 va_start(args, count);
112 for (unsigned n = 0; n < count; n++) {
113 CFTypeRef key = va_arg(args, CFTypeRef);
114 CFTypeRef value = va_arg(args, CFTypeRef);
115 CFDictionaryAddValue(dict, key, value);
116 }
117 va_end(args);
118 }
119 return dict;
120 }
121
122 CFMutableDictionaryRef makeCFMutableDictionary(CFDictionaryRef dict)
123 {
124 if (CFMutableDictionaryRef r = CFDictionaryCreateMutableCopy(NULL, 0, dict))
125 return r;
126 CFError::throwMe();
127 }
128
129 CFDictionaryRef makeCFDictionaryFrom(CFDataRef data)
130 {
131 if (data) {
132 CFPropertyListRef plist = CFPropertyListCreateFromXMLData(NULL, data,
133 kCFPropertyListImmutable, NULL);
134 if (plist && CFGetTypeID(plist) != CFDictionaryGetTypeID())
135 CFError::throwMe();
136 return CFDictionaryRef(plist);
137 } else
138 return NULL;
139
140 }
141
142 CFDictionaryRef makeCFDictionaryFrom(const void *data, size_t length)
143 {
144 return makeCFDictionaryFrom(CFTempData(data, length).get());
145 }
146
147
148
149 static void cfarrayApplyBlock_func(const void *value, const void *ctx)
150 {
151 CFArrayApplierBlock block = CFArrayApplierBlock(ctx);
152 block(value);
153 }
154 void cfArrayApplyBlock(CFArrayRef array, CFRange range, CFArrayApplierBlock block)
155 {
156 CFArrayApplyFunction(array, range, (CFArrayApplierFunction)cfarrayApplyBlock_func, block);
157 }
158 void cfArrayApplyBlock(CFArrayRef array, CFArrayApplierBlock block)
159 {
160 CFRange range = CFRangeMake(0, CFArrayGetCount(array));
161 cfArrayApplyBlock(array, range, block);
162 }
163
164 static void cfdictionaryApplyBlock_func(const void *key, const void *value, void *ctx)
165 {
166 CFDictionaryApplierBlock block = CFDictionaryApplierBlock(ctx);
167 block(key, value);
168 }
169 void cfDictionaryApplyBlock(CFDictionaryRef dict, CFDictionaryApplierBlock block)
170 {
171 CFDictionaryApplyFunction(dict, cfdictionaryApplyBlock_func, block);
172 }
173
174
175 //
176 // Turn a CFString into a UTF8-encoded C++ string.
177 // If release==true, the argument will be CFReleased even in case of error.
178 //
179 string cfString(CFStringRef str)
180 {
181 if (!str)
182 return "";
183 // quick path first
184 if (const char *s = CFStringGetCStringPtr(str, kCFStringEncodingUTF8)) {
185 return s;
186 }
187
188 // need to extract into buffer
189 string ret;
190 CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
191 std::vector<char> buffer;
192 buffer.resize(length + 1);
193 if (CFStringGetCString(str, &buffer[0], length + 1, kCFStringEncodingUTF8))
194 ret = &buffer[0];
195 return ret;
196 }
197
198 string cfStringRelease(CFStringRef inStr)
199 {
200 CFRef<CFStringRef> str(inStr);
201 return cfString(str);
202 }
203
204 string cfString(CFURLRef inUrl)
205 {
206 if (!inUrl)
207 CFError::throwMe();
208
209 UInt8 buffer[PATH_MAX+1];
210 if (CFURLGetFileSystemRepresentation(inUrl, true, buffer, sizeof(buffer)))
211 return string(reinterpret_cast<char *>(buffer));
212 else
213 CFError::throwMe();
214 }
215
216 string cfStringRelease(CFURLRef inUrl)
217 {
218 CFRef<CFURLRef> bundle(inUrl);
219 return cfString(bundle);
220 }
221
222 string cfString(CFBundleRef inBundle)
223 {
224 if (!inBundle)
225 CFError::throwMe();
226 return cfStringRelease(CFBundleCopyBundleURL(inBundle));
227 }
228
229 string cfStringRelease(CFBundleRef inBundle)
230 {
231 CFRef<CFBundleRef> bundle(inBundle);
232 return cfString(bundle);
233 }
234
235
236 string cfString(CFTypeRef it, OSStatus err)
237 {
238 if (it == NULL)
239 MacOSError::throwMe(err);
240 CFTypeID id = CFGetTypeID(it);
241 if (id == CFStringGetTypeID())
242 return cfString(CFStringRef(it));
243 else if (id == CFURLGetTypeID())
244 return cfString(CFURLRef(it));
245 else if (id == CFBundleGetTypeID())
246 return cfString(CFBundleRef(it));
247 else
248 return cfString(CFCopyDescription(it), true);
249 }
250
251
252 //
253 // CFURLAccess wrappers for specific purposes
254 //
255 CFDataRef cfLoadFile(CFURLRef url)
256 {
257 assert(url);
258 CFDataRef data;
259 SInt32 error;
260 if (CFURLCreateDataAndPropertiesFromResource(NULL, url,
261 &data, NULL, NULL, &error)) {
262 return data;
263 } else {
264 secinfo("cfloadfile", "failed to fetch %s error=%d", cfString(url).c_str(), int(error));
265 return NULL;
266 }
267 }
268
269 CFDataRef cfLoadFile(int fd, size_t bytes)
270 {
271 uint8_t *buffer = (uint8_t *) malloc(bytes);
272
273 if (buffer == NULL)
274 return NULL;
275
276 if (read(fd, buffer, bytes) != bytes) {
277 free(buffer);
278 return NULL;
279 }
280
281 CFDataRef result = CFDataCreateWithBytesNoCopy(kCFAllocatorMalloc, buffer, bytes, kCFAllocatorMalloc);
282
283 // If CFDataCreateWithBytesNoCopy fails, the buffer is not free()-ed
284 if (result == NULL) {
285 free(buffer);
286 return NULL;
287 }
288
289 return result;
290 }
291
292 //
293 // CFArray creators
294 //
295 CFArrayRef makeCFArray(CFIndex count, ...)
296 {
297 CFTypeRef elements[count];
298 va_list args;
299 va_start(args, count);
300 for (CFIndex n = 0; n < count; n++)
301 elements[n] = va_arg(args, CFTypeRef);
302 va_end(args);
303 return CFArrayCreate(NULL, elements, count, &kCFTypeArrayCallBacks);
304 }
305
306 CFMutableArrayRef makeCFMutableArray(CFIndex count, ...)
307 {
308 CFMutableArrayRef array = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
309 va_list args;
310 va_start(args, count);
311 for (CFIndex n = 0; n < count; n++)
312 CFArrayAppendValue(array, va_arg(args, CFTypeRef));
313 va_end(args);
314 return array;
315 }
316
317
318 } // end namespace Security