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 // Turn a CFString into a UTF8-encoded C++ string.
150 // If release==true, the argument will be CFReleased even in case of error.
152 string
cfString(CFStringRef str
)
157 if (const char *s
= CFStringGetCStringPtr(str
, kCFStringEncodingUTF8
)) {
161 // need to extract into buffer
163 CFIndex length
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(str
), kCFStringEncodingUTF8
);
164 std::vector
<char> buffer
;
165 buffer
.resize(length
+ 1);
166 if (CFStringGetCString(str
, &buffer
[0], length
+ 1, kCFStringEncodingUTF8
))
171 string
cfStringRelease(CFStringRef inStr
)
173 CFRef
<CFStringRef
> str(inStr
);
174 return cfString(str
);
177 string
cfString(CFURLRef inUrl
)
182 UInt8 buffer
[PATH_MAX
+1];
183 if (CFURLGetFileSystemRepresentation(inUrl
, true, buffer
, sizeof(buffer
)))
184 return string(reinterpret_cast<char *>(buffer
));
189 string
cfStringRelease(CFURLRef inUrl
)
191 CFRef
<CFURLRef
> bundle(inUrl
);
192 return cfString(bundle
);
195 string
cfString(CFBundleRef inBundle
)
199 return cfStringRelease(CFBundleCopyBundleURL(inBundle
));
202 string
cfStringRelease(CFBundleRef inBundle
)
204 CFRef
<CFBundleRef
> bundle(inBundle
);
205 return cfString(bundle
);
209 string
cfString(CFTypeRef it
, OSStatus err
)
212 MacOSError::throwMe(err
);
213 CFTypeID id
= CFGetTypeID(it
);
214 if (id
== CFStringGetTypeID())
215 return cfString(CFStringRef(it
));
216 else if (id
== CFURLGetTypeID())
217 return cfString(CFURLRef(it
));
218 else if (id
== CFBundleGetTypeID())
219 return cfString(CFBundleRef(it
));
221 return cfString(CFCopyDescription(it
), true);
226 // CFURLAccess wrappers for specific purposes
228 CFDataRef
cfLoadFile(CFURLRef url
)
233 if (CFURLCreateDataAndPropertiesFromResource(NULL
, url
,
234 &data
, NULL
, NULL
, &error
)) {
237 secdebug("cfloadfile", "failed to fetch %s error=%d", cfString(url
).c_str(), int(error
));
242 CFDataRef
cfLoadFile(int fd
, size_t bytes
)
244 uint8_t *buffer
= (uint8_t *) malloc(bytes
);
249 if (read(fd
, buffer
, bytes
) != bytes
) {
254 CFDataRef result
= CFDataCreateWithBytesNoCopy(kCFAllocatorMalloc
, buffer
, bytes
, kCFAllocatorMalloc
);
256 // If CFDataCreateWithBytesNoCopy fails, the buffer is not free()-ed
257 if (result
== NULL
) {
268 CFArrayRef
makeCFArray(CFIndex count
, ...)
270 CFTypeRef elements
[count
];
272 va_start(args
, count
);
273 for (CFIndex n
= 0; n
< count
; n
++)
274 elements
[n
] = va_arg(args
, CFTypeRef
);
276 return CFArrayCreate(NULL
, elements
, count
, &kCFTypeArrayCallBacks
);
279 CFMutableArrayRef
makeCFMutableArray(CFIndex count
, ...)
281 CFMutableArrayRef array
= CFArrayCreateMutable(NULL
, count
, &kCFTypeArrayCallBacks
);
283 va_start(args
, count
);
284 for (CFIndex n
= 0; n
< count
; n
++)
285 CFArrayAppendValue(array
, va_arg(args
, CFTypeRef
));
291 } // end namespace Security