/ plconvert.c
plconvert.c
  1  /*
  2   * Copyright (c) 2015 Apple Inc. All rights reserved.
  3   *
  4   * @APPLE_LICENSE_HEADER_START@
  5   *
  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
 11   * file.
 12   *
 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.
 20   *
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  // Mac OS X: clang -F<path-to-CFLite-framework> -framework CoreFoundation Examples/plconvert.c -o plconvert
 25  //  note: When running this sample, be sure to set the environment variable DYLD_FRAMEWORK_PATH to point to the directory containing your new version of CoreFoundation.
 26  //   e.g.
 27  //  DYLD_FRAMEWORK_PATH=/tmp/CF-Root ./plconvert <input> <output>
 28  // 
 29  // Linux: clang -I/usr/local/include -L/usr/local/lib -lCoreFoundation plconvert.c -o plconvert
 30  
 31  /*
 32   This example shows usage of CFString, CFData, and other CFPropertyList types. It takes two arguments:
 33      1. A property list file to read, in either binary or XML property list format.
 34      2. A file name to write a converted property list file to.
 35   If the first input is binary, the output is XML and vice-versa.
 36  */
 37  
 38  #include <sys/types.h>
 39  #include <sys/stat.h>
 40  #include <fcntl.h>
 41  #include <string.h>
 42  #include <stdio.h>
 43  #include <unistd.h>
 44  
 45  #include <CoreFoundation/CoreFoundation.h>
 46  
 47  static void logIt(CFStringRef format, ...) {
 48      va_list args;
 49      va_start(args, format); 
 50      CFStringRef str = CFStringCreateWithFormatAndArguments(kCFAllocatorSystemDefault, NULL, format, args);
 51      if (!str) return;
 52      
 53      CFIndex blen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8);
 54      char *buf = str ? (char *)malloc(blen + 1) : 0;
 55      if (buf) {
 56          Boolean converted = CFStringGetCString(str, buf, blen, kCFStringEncodingUTF8);
 57          if (converted) {
 58              // null-terminate
 59              buf[blen] = 0;
 60              printf("%s\n", buf);
 61          }
 62      }
 63      if (buf) free(buf);
 64      if (str) CFRelease(str);      va_end(args);
 65  }
 66  
 67  static CFMutableDataRef createDataFromFile(const char *fname) {
 68      int fd = open(fname, O_RDONLY);
 69      CFMutableDataRef res = CFDataCreateMutable(kCFAllocatorSystemDefault, 0);
 70      char buf[4096];
 71      
 72      ssize_t amountRead;
 73      while ((amountRead = read(fd, buf, 4096)) > 0) {
 74          CFDataAppendBytes(res, (const UInt8 *)buf, amountRead);
 75      }
 76      
 77      close(fd);
 78      return res;
 79  }
 80  
 81  static bool writeDataToFile(CFDataRef data, const char *fname) {
 82      int fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 83      if (fd < 0) {
 84          printf("There was an error creating the file: %d", errno);
 85          return false;
 86      }
 87      int dataLen = CFDataGetLength(data);
 88      int w = write(fd, CFDataGetBytePtr(data), dataLen);
 89      fsync(fd);
 90      close(fd);
 91      if (w != dataLen) return false;
 92      return true;
 93  }
 94  
 95  int main(int argc, char **argv) {
 96      
 97      if (argc != 3) {
 98          printf("Usage: plconvert <in file> <out file>\nIf the in file is an XML property list, convert to binary property list in out file. If the in file is a binary property list, convert to XML property list in out file.\n");
 99      } else {
100          CFMutableDataRef plistData = createDataFromFile(argv[1]);
101          if (!plistData) {
102              printf("Unable to create data from file name: %s", argv[1]);
103          } else {
104              CFPropertyListFormat fmt;
105              CFErrorRef err;
106              CFPropertyListRef plist = CFPropertyListCreateWithData(kCFAllocatorSystemDefault, (CFDataRef)plistData, 0, &fmt, &err);
107              if (!plist) {
108                  logIt(CFSTR("Unable to create property list from data: %@"), err);
109              } else {
110                  logIt(CFSTR("Property list contents:\n%@"), plist);
111                  if (fmt == kCFPropertyListBinaryFormat_v1_0) {
112                      logIt(CFSTR("Converting to XML property list at: %s"), argv[2]);
113                      fmt = kCFPropertyListXMLFormat_v1_0;
114                  } else if (fmt == kCFPropertyListXMLFormat_v1_0) {
115                      logIt(CFSTR("Converting to binary property list at: %s"), argv[2]);
116                      fmt = kCFPropertyListBinaryFormat_v1_0;
117                  } else {
118                      logIt(CFSTR("Unknown property list format! Not converting output format."));
119                  }
120                  
121                  CFDataRef outputData = CFPropertyListCreateData(kCFAllocatorSystemDefault, plist, fmt, 0, &err);
122                  if (!outputData) {
123                      logIt(CFSTR("Unable to write property list to data: %@"), err);
124                  } else {
125                      bool success = writeDataToFile(outputData, argv[2]);
126                      if (!success) {
127                          logIt(CFSTR("Unable to write data to file"));
128                      }
129                      CFRelease(outputData);
130                  }
131                  CFRelease(plist);
132              }
133              CFRelease(plistData);
134          }
135      }
136  }