2 * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
26 // CoreFoundation related utilities
28 #include <security_utilities/cfutilities.h>
29 #include <security_utilities/errors.h>
30 #include <security_utilities/debugging.h>
38 ModuleNexus
<CFEmptyArray
> cfEmptyArray
;
40 CFEmptyArray::CFEmptyArray()
42 mArray
= CFArrayCreate(NULL
, NULL
, 0, NULL
);
47 // Turn a C(++) string into a CFURLRef indicating a file: path
49 CFURLRef
makeCFURL(const char *s
, bool isDirectory
, CFURLRef base
)
52 return CFURLCreateWithFileSystemPathRelativeToBase(NULL
,
53 CFTempString(s
), kCFURLPOSIXPathStyle
, isDirectory
, base
);
55 return CFURLCreateWithFileSystemPath(NULL
,
56 CFTempString(s
), kCFURLPOSIXPathStyle
, isDirectory
);
59 CFURLRef
makeCFURL(CFStringRef s
, bool isDirectory
, CFURLRef base
)
62 return CFURLCreateWithFileSystemPathRelativeToBase(NULL
, s
, kCFURLPOSIXPathStyle
, isDirectory
, base
);
64 return CFURLCreateWithFileSystemPath(NULL
, s
, kCFURLPOSIXPathStyle
, isDirectory
);
69 // CFMallocData objects
71 CFMallocData::operator CFDataRef ()
73 CFDataRef result
= makeCFDataMalloc(mData
, mSize
);
76 mData
= NULL
; // release ownership
82 // Make CFDictionaries from stuff
84 CFDictionaryRef
makeCFDictionary(unsigned count
, ...)
86 CFTypeRef keys
[count
], values
[count
];
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
);
94 return CFDictionaryCreate(NULL
, (const void **)keys
, (const void **)values
, count
,
95 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
98 CFMutableDictionaryRef
makeCFMutableDictionary()
100 if (CFMutableDictionaryRef r
= CFDictionaryCreateMutable(NULL
, 0,
101 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
))
106 CFMutableDictionaryRef
makeCFMutableDictionary(unsigned count
, ...)
108 CFMutableDictionaryRef dict
= makeCFMutableDictionary();
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
);
122 CFMutableDictionaryRef
makeCFMutableDictionary(CFDictionaryRef dict
)
124 if (CFMutableDictionaryRef r
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
))
129 CFDictionaryRef
makeCFDictionaryFrom(CFDataRef data
)
132 CFPropertyListRef plist
= CFPropertyListCreateFromXMLData(NULL
, data
,
133 kCFPropertyListImmutable
, NULL
);
134 if (plist
&& CFGetTypeID(plist
) != CFDictionaryGetTypeID())
136 return CFDictionaryRef(plist
);
142 CFDictionaryRef
makeCFDictionaryFrom(const void *data
, size_t length
)
144 return makeCFDictionaryFrom(CFTempData(data
, length
).get());
149 static void cfarrayApplyBlock_func(const void *value
, const void *ctx
)
151 CFArrayApplierBlock block
= CFArrayApplierBlock(ctx
);
154 void cfArrayApplyBlock(CFArrayRef array
, CFRange range
, CFArrayApplierBlock block
)
156 CFArrayApplyFunction(array
, range
, (CFArrayApplierFunction
)cfarrayApplyBlock_func
, block
);
158 void cfArrayApplyBlock(CFArrayRef array
, CFArrayApplierBlock block
)
160 CFRange range
= CFRangeMake(0, CFArrayGetCount(array
));
161 cfArrayApplyBlock(array
, range
, block
);
164 static void cfdictionaryApplyBlock_func(const void *key
, const void *value
, void *ctx
)
166 CFDictionaryApplierBlock block
= CFDictionaryApplierBlock(ctx
);
169 void cfDictionaryApplyBlock(CFDictionaryRef dict
, CFDictionaryApplierBlock block
)
171 CFDictionaryApplyFunction(dict
, cfdictionaryApplyBlock_func
, block
);
176 // Turn a CFString into a UTF8-encoded C++ string.
177 // If release==true, the argument will be CFReleased even in case of error.
179 string
cfString(CFStringRef str
)
184 if (const char *s
= CFStringGetCStringPtr(str
, kCFStringEncodingUTF8
)) {
188 // need to extract into buffer
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
))
198 string
cfStringRelease(CFStringRef inStr
)
200 CFRef
<CFStringRef
> str(inStr
);
201 return cfString(str
);
204 string
cfString(CFURLRef inUrl
)
209 UInt8 buffer
[PATH_MAX
+1];
210 if (CFURLGetFileSystemRepresentation(inUrl
, true, buffer
, sizeof(buffer
)))
211 return string(reinterpret_cast<char *>(buffer
));
216 string
cfStringRelease(CFURLRef inUrl
)
218 CFRef
<CFURLRef
> bundle(inUrl
);
219 return cfString(bundle
);
222 string
cfString(CFBundleRef inBundle
)
226 return cfStringRelease(CFBundleCopyBundleURL(inBundle
));
229 string
cfStringRelease(CFBundleRef inBundle
)
231 CFRef
<CFBundleRef
> bundle(inBundle
);
232 return cfString(bundle
);
236 string
cfString(CFTypeRef it
, OSStatus err
)
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
));
248 return cfString(CFCopyDescription(it
), true);
253 // CFURLAccess wrappers for specific purposes
255 CFDataRef
cfLoadFile(CFURLRef url
)
260 if (CFURLCreateDataAndPropertiesFromResource(NULL
, url
,
261 &data
, NULL
, NULL
, &error
)) {
264 secdebug("cfloadfile", "failed to fetch %s error=%d", cfString(url
).c_str(), int(error
));
269 CFDataRef
cfLoadFile(int fd
, size_t bytes
)
271 uint8_t *buffer
= (uint8_t *) malloc(bytes
);
276 if (read(fd
, buffer
, bytes
) != bytes
) {
281 CFDataRef result
= CFDataCreateWithBytesNoCopy(kCFAllocatorMalloc
, buffer
, bytes
, kCFAllocatorMalloc
);
283 // If CFDataCreateWithBytesNoCopy fails, the buffer is not free()-ed
284 if (result
== NULL
) {
295 CFArrayRef
makeCFArray(CFIndex count
, ...)
297 CFTypeRef elements
[count
];
299 va_start(args
, count
);
300 for (CFIndex n
= 0; n
< count
; n
++)
301 elements
[n
] = va_arg(args
, CFTypeRef
);
303 return CFArrayCreate(NULL
, elements
, count
, &kCFTypeArrayCallBacks
);
306 CFMutableArrayRef
makeCFMutableArray(CFIndex count
, ...)
308 CFMutableArrayRef array
= CFArrayCreateMutable(NULL
, count
, &kCFTypeArrayCallBacks
);
310 va_start(args
, count
);
311 for (CFIndex n
= 0; n
< count
; n
++)
312 CFArrayAppendValue(array
, va_arg(args
, CFTypeRef
));
318 } // end namespace Security