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>
31 #include <utilities/SecCFRelease.h>
39 ModuleNexus
<CFEmptyArray
> cfEmptyArray
;
41 CFEmptyArray::CFEmptyArray()
43 mArray
= CFArrayCreate(NULL
, NULL
, 0, NULL
);
48 // Turn a C(++) string into a CFURLRef indicating a file: path
50 CFURLRef
makeCFURL(const char *s
, bool isDirectory
, CFURLRef base
)
53 return CFURLCreateWithFileSystemPathRelativeToBase(NULL
,
54 CFTempString(s
), kCFURLPOSIXPathStyle
, isDirectory
, base
);
56 return CFURLCreateWithFileSystemPath(NULL
,
57 CFTempString(s
), kCFURLPOSIXPathStyle
, isDirectory
);
60 CFURLRef
makeCFURL(CFStringRef s
, bool isDirectory
, CFURLRef base
)
63 return CFURLCreateWithFileSystemPathRelativeToBase(NULL
, s
, kCFURLPOSIXPathStyle
, isDirectory
, base
);
65 return CFURLCreateWithFileSystemPath(NULL
, s
, kCFURLPOSIXPathStyle
, isDirectory
);
70 // CFMallocData objects
72 CFMallocData::operator CFDataRef ()
74 CFDataRef result
= makeCFDataMalloc(mData
, mSize
);
77 mData
= NULL
; // release ownership
83 // Make CFDictionaries from stuff
85 CFDictionaryRef
makeCFDictionary(unsigned count
, ...)
87 CFTypeRef keys
[count
], values
[count
];
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
);
95 return CFDictionaryCreate(NULL
, (const void **)keys
, (const void **)values
, count
,
96 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
99 CFMutableDictionaryRef
makeCFMutableDictionary()
101 if (CFMutableDictionaryRef r
= CFDictionaryCreateMutable(NULL
, 0,
102 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
))
107 CFMutableDictionaryRef
makeCFMutableDictionary(unsigned count
, ...)
109 CFMutableDictionaryRef dict
= makeCFMutableDictionary();
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
);
123 CFMutableDictionaryRef
makeCFMutableDictionary(CFDictionaryRef dict
)
125 if (CFMutableDictionaryRef r
= CFDictionaryCreateMutableCopy(NULL
, 0, dict
))
130 CFDictionaryRef
makeCFDictionaryFrom(CFDataRef data
)
133 CFPropertyListRef plist
= CFPropertyListCreateFromXMLData(NULL
, data
,
134 kCFPropertyListImmutable
, NULL
);
135 if (plist
&& CFGetTypeID(plist
) != CFDictionaryGetTypeID())
137 return CFDictionaryRef(plist
);
143 CFDictionaryRef
makeCFDictionaryFrom(const void *data
, size_t length
)
145 return makeCFDictionaryFrom(CFTempData(data
, length
).get());
150 static void cfarrayApplyBlock_func(const void *value
, const void *ctx
)
152 CFArrayApplierBlock block
= CFArrayApplierBlock(ctx
);
155 void cfArrayApplyBlock(CFArrayRef array
, CFRange range
, CFArrayApplierBlock block
)
157 CFArrayApplyFunction(array
, range
, (CFArrayApplierFunction
)cfarrayApplyBlock_func
, block
);
159 void cfArrayApplyBlock(CFArrayRef array
, CFArrayApplierBlock block
)
161 CFRange range
= CFRangeMake(0, CFArrayGetCount(array
));
162 cfArrayApplyBlock(array
, range
, block
);
165 static void cfdictionaryApplyBlock_func(const void *key
, const void *value
, void *ctx
)
167 CFDictionaryApplierBlock block
= CFDictionaryApplierBlock(ctx
);
170 void cfDictionaryApplyBlock(CFDictionaryRef dict
, CFDictionaryApplierBlock block
)
172 CFDictionaryApplyFunction(dict
, cfdictionaryApplyBlock_func
, block
);
177 // Turn a CFString into a UTF8-encoded C++ string.
178 // If release==true, the argument will be CFReleased even in case of error.
180 string
cfString(CFStringRef str
)
185 if (const char *s
= CFStringGetCStringPtr(str
, kCFStringEncodingUTF8
)) {
189 // need to extract into buffer
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
))
199 string
cfStringRelease(CFStringRef CF_CONSUMED inStr
)
201 CFRef
<CFStringRef
> str(inStr
);
202 return cfString(str
);
205 string
cfString(CFURLRef inUrl
)
210 UInt8 buffer
[PATH_MAX
+1];
211 if (CFURLGetFileSystemRepresentation(inUrl
, true, buffer
, sizeof(buffer
)))
212 return string(reinterpret_cast<char *>(buffer
));
217 string
cfStringRelease(CFURLRef CF_CONSUMED inUrl
)
219 CFRef
<CFURLRef
> bundle(inUrl
);
220 return cfString(bundle
);
223 string
cfString(CFBundleRef inBundle
)
227 return cfStringRelease(CFBundleCopyBundleURL(inBundle
));
230 string
cfStringRelease(CFBundleRef CF_CONSUMED inBundle
)
232 CFRef
<CFBundleRef
> bundle(inBundle
);
233 return cfString(bundle
);
237 string
cfString(CFTypeRef it
, OSStatus err
)
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
));
249 return cfStringRelease(CFCopyDescription(it
));
255 // CFURLAccess wrappers for specific purposes
257 CFDataRef
cfLoadFile(CFURLRef url
)
262 if (CFURLCreateDataAndPropertiesFromResource(NULL
, url
,
263 &data
, NULL
, NULL
, &error
)) {
266 secinfo("cfloadfile", "failed to fetch %s error=%d", cfString(url
).c_str(), int(error
));
271 CFDataRef
cfLoadFile(int fd
, size_t bytes
)
273 uint8_t *buffer
= (uint8_t *) malloc(bytes
);
278 if (read(fd
, buffer
, bytes
) != bytes
) {
283 CFDataRef result
= CFDataCreateWithBytesNoCopy(kCFAllocatorMalloc
, buffer
, bytes
, kCFAllocatorMalloc
);
285 // If CFDataCreateWithBytesNoCopy fails, the buffer is not free()-ed
286 if (result
== NULL
) {
297 CFArrayRef
makeCFArray(CFIndex count
, ...)
299 CFTypeRef elements
[count
];
301 va_start(args
, count
);
302 for (CFIndex n
= 0; n
< count
; n
++)
303 elements
[n
] = va_arg(args
, CFTypeRef
);
305 return CFArrayCreate(NULL
, elements
, count
, &kCFTypeArrayCallBacks
);
308 CFMutableArrayRef
makeCFMutableArray(CFIndex count
, ...)
310 CFMutableArrayRef array
= CFArrayCreateMutable(NULL
, count
, &kCFTypeArrayCallBacks
);
312 va_start(args
, count
);
313 for (CFIndex n
= 0; n
< count
; n
++)
314 CFArrayAppendValue(array
, va_arg(args
, CFTypeRef
));
320 } // end namespace Security