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