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