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