#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/param.h>
#include <mach/mach.h>
#include <mach/notify.h>
#include <mach/mach_error.h>
#include <pthread.h>
#include <CoreFoundation/CFPropertyList.h>
#include <CoreFoundation/CFData.h>
#include <CoreFoundation/CFBase.h>
#include <CoreFoundation/CFUUID.h>
#include <CoreFoundation/CFNumber.h>
#include <SystemConfiguration/SCValidation.h>
#include "myCFUtil.h"
static const CFStringEncoding S_encodings[] = {
kCFStringEncodingUTF8,
kCFStringEncodingMacRoman
};
static const int S_encodings_count = (sizeof(S_encodings)
/ sizeof(S_encodings[0]));
Boolean
my_CFEqual(CFTypeRef val1, CFTypeRef val2)
{
if (val1 == NULL) {
if (val2 == NULL) {
return (TRUE);
}
return (FALSE);
}
if (val2 == NULL) {
return (FALSE);
}
return (CFEqual(val1, val2));
}
void
my_CFRelease(void * t)
{
void * * obj = (void * *)t;
if (obj && *obj) {
CFRelease(*obj);
*obj = NULL;
}
return;
}
static char *
S_copy_cstring(CFStringRef cfstr, CFRange range, CFStringEncoding encoding)
{
CFIndex l;
uint8_t * str;
CFStringGetBytes(cfstr, range, encoding, 0, FALSE, NULL, 0, &l);
if (l <= 0) {
return (NULL);
}
str = (uint8_t *)malloc(l + 1);
CFStringGetBytes(cfstr, range, encoding, 0, FALSE, str, l, &l);
str[l] = '\0';
return ((char *)str);
}
char *
my_CFStringToCString(CFStringRef cfstr, CFStringEncoding encoding)
{
int i;
CFRange range;
range = CFRangeMake(0, CFStringGetLength(cfstr));
if (encoding != kCFStringEncodingInvalidId) {
return (S_copy_cstring(cfstr, range, encoding));
}
for (i = 0; i < S_encodings_count; i++) {
char * str;
str = S_copy_cstring(cfstr, range, S_encodings[i]);
if (str != NULL) {
return (str);
}
}
return (NULL);
}
static void *
read_file(const char * filename, size_t * data_length)
{
void * data = NULL;
size_t len = 0;
int fd = -1;
struct stat sb;
*data_length = 0;
if (stat(filename, &sb) < 0)
goto done;
len = sb.st_size;
if (len == 0)
goto done;
data = malloc(len);
if (data == NULL)
goto done;
fd = open(filename, O_RDONLY);
if (fd < 0)
goto done;
if (read(fd, data, len) != len) {
goto done;
}
done:
if (fd >= 0)
close(fd);
if (data) {
*data_length = len;
}
return (data);
}
static int
write_file(const char * filename, const void * data, size_t data_length)
{
char path[MAXPATHLEN];
int fd = -1;
int ret = 0;
snprintf(path, sizeof(path), "%s-", filename);
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0644);
if (fd < 0) {
ret = -1;
goto done;
}
if (write(fd, data, data_length) != data_length) {
ret = -1;
goto done;
}
rename(path, filename);
done:
if (fd >= 0) {
close(fd);
}
return (ret);
}
CFPropertyListRef
my_CFPropertyListCreateFromFile(const char * filename)
{
void * buf;
size_t bufsize;
CFDataRef data = NULL;
CFPropertyListRef plist = NULL;
buf = read_file(filename, &bufsize);
if (buf == NULL) {
return (NULL);
}
data = CFDataCreate(NULL, buf, bufsize);
if (data == NULL) {
goto done;
}
plist = CFPropertyListCreateWithData(NULL, data,
kCFPropertyListImmutable,
NULL, NULL);
done:
if (data)
CFRelease(data);
if (buf)
free(buf);
return (plist);
}
int
my_CFPropertyListWriteFile(CFPropertyListRef plist, const char * filename)
{
CFDataRef data;
int ret;
if (plist == NULL)
return (0);
data = CFPropertyListCreateData(NULL, plist,
kCFPropertyListXMLFormat_v1_0,
0, NULL);
if (data == NULL) {
return (0);
}
ret = write_file(filename,
(const void *)CFDataGetBytePtr(data),
CFDataGetLength(data));
CFRelease(data);
return (ret);
}
CFPropertyListRef
my_CFPropertyListCreateWithBytePtrAndLength(const void * data, int data_len)
{
CFPropertyListRef plist;
CFDataRef xml_data;
xml_data = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)data,
data_len,
kCFAllocatorNull);
if (xml_data == NULL) {
return (NULL);
}
plist = CFPropertyListCreateWithData(NULL, xml_data,
kCFPropertyListImmutable,
NULL, NULL);
CFRelease(xml_data);
return (plist);
}
Boolean
my_CFDictionaryGetBooleanValue(CFDictionaryRef properties, CFStringRef propname,
Boolean def_value)
{
bool ret = def_value;
if (properties != NULL) {
CFBooleanRef val;
val = CFDictionaryGetValue(properties, propname);
if (isA_CFBoolean(val)) {
ret = CFBooleanGetValue(val);
}
}
return (ret);
}
CFStringRef
my_CFUUIDStringCreate(CFAllocatorRef alloc)
{
CFUUIDRef uuid;
CFStringRef uuid_str;
uuid = CFUUIDCreate(alloc);
uuid_str = CFUUIDCreateString(alloc, uuid);
CFRelease(uuid);
return (uuid_str);
}
CFStringRef
my_CFStringCreateWithData(CFDataRef data)
{
CFAllocatorRef allocator = CFGetAllocator(data);
int i;
CFStringRef str;
for (i = 0; i < S_encodings_count; i++) {
str = CFStringCreateWithBytes(allocator,
CFDataGetBytePtr(data),
CFDataGetLength(data),
S_encodings[i],
FALSE);
if (str != NULL) {
return (str);
}
}
return (NULL);
}
CFStringRef
my_CFStringCreateWithCString(const char * cstr)
{
int i;
CFStringRef str;
for (i = 0; i < S_encodings_count; i++) {
str = CFStringCreateWithCString(NULL, cstr,
S_encodings[i]);
if (str != NULL) {
return (str);
}
}
return (NULL);
}
CFDataRef
my_CFDataCreateWithString(CFStringRef str)
{
CFDataRef data;
int i;
for (i = 0; i < S_encodings_count; i++) {
data = CFStringCreateExternalRepresentation(NULL, str,
S_encodings[i], 0);
if (data != NULL) {
return (data);
}
}
return (NULL);
}
void
my_FieldSetRetainedCFType(void * field_p, const void * v)
{
CFTypeRef existing = *((CFTypeRef *)field_p);
CFTypeRef val = (CFTypeRef)v;
if (val != NULL) {
CFRetain(val);
}
if (existing != NULL) {
CFRelease(existing);
}
*((CFTypeRef *)field_p) = val;
return;
}
CFStringRef
my_CFPropertyListCopyAsXMLString(CFPropertyListRef plist)
{
CFDataRef data;
CFStringRef str;
data = CFPropertyListCreateData(NULL, plist,
kCFPropertyListXMLFormat_v1_0, 0, NULL);
if (data == NULL) {
return (NULL);
}
str = CFStringCreateWithBytes(NULL,
CFDataGetBytePtr(data),
CFDataGetLength(data),
kCFStringEncodingUTF8,
FALSE);
CFRelease(data);
return (str);
}
vm_address_t
my_CFPropertyListCreateVMData(CFPropertyListRef plist,
mach_msg_type_number_t * ret_data_len)
{
vm_address_t data;
int data_len;
kern_return_t status;
CFDataRef xml_data;
data = 0;
*ret_data_len = 0;
xml_data = CFPropertyListCreateData(NULL, plist,
kCFPropertyListBinaryFormat_v1_0,
0, NULL);
if (xml_data == NULL) {
goto done;
}
data_len = (int)CFDataGetLength(xml_data);
status = vm_allocate(mach_task_self(), &data, data_len, TRUE);
if (status != KERN_SUCCESS) {
goto done;
}
bcopy((char *)CFDataGetBytePtr(xml_data), (char *)data, data_len);
*ret_data_len = data_len;
done:
my_CFRelease(&xml_data);
return (data);
}
CFStringRef
my_CFStringCopyComponent(CFStringRef path, CFStringRef separator,
CFIndex component_index)
{
CFArrayRef arr;
CFStringRef component = NULL;
arr = CFStringCreateArrayBySeparatingStrings(NULL, path, separator);
if (arr == NULL) {
goto done;
}
if (CFArrayGetCount(arr) <= component_index) {
goto done;
}
component = CFRetain(CFArrayGetValueAtIndex(arr, component_index));
done:
my_CFRelease(&arr);
return (component);
}