1/* 2 * Copyright (c) 2004 Apple Computer, 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#include <stdio.h> 25#include <string.h> 26#include <stdlib.h> 27#include <limits.h> 28#include <errno.h> 29#include <err.h> 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <fcntl.h> 33#include <pwd.h> 34#include <grp.h> 35#include <unistd.h> 36 37#include <CoreFoundation/CoreFoundation.h> 38 39#include "util.h" 40 41void 42PrintValue(const void *key, const void *value, void *context) { 43 int key_len, value_len; 44 const CFStringRef kStr = key; 45 const CFTypeRef kVal = value; 46 char *buf = NULL; 47 int32_t val; 48 char *intFmt = "%d\n"; 49 50 if (CFGetTypeID(kStr) != CFStringGetTypeID()) { 51 warnx("PrintDictionary: key type is not a string"); 52 return; 53 } 54 55 if (CFStringCompare(kStr, CFSTR("owner-mode"), 0) == kCFCompareEqualTo) { 56 intFmt = "0%o\n"; 57 } else if (!gVerbose && (CFStringCompare(kStr, CFSTR("Base"), 0) == kCFCompareEqualTo || 58 CFStringCompare(kStr, CFSTR("Size"), 0) == kCFCompareEqualTo)) { 59 return; 60 } 61 62 key_len = CFStringGetLength(kStr); 63 buf = malloc(key_len * 2); 64 if (!buf) { 65 warnx("PrintDictionary: unable to allocate buffer for key"); 66 goto out; 67 } 68 if (!CFStringGetCString(kStr, buf, key_len * 2, kCFStringEncodingASCII)) { 69 warnx("PrintDictionary: unable to get key as C string"); 70 goto out; 71 } 72 printf("\t%s = ", buf); 73 free(buf); buf = NULL; 74 75 if (CFGetTypeID(kVal) == CFStringGetTypeID()) { 76 value_len = CFStringGetLength(kVal); 77 buf = malloc(value_len * 2); 78 if (buf == NULL) { 79 warnx("PrintDictionary: unable to allocate buffer for value"); 80 printf("* * * ERROR * * *\n"); 81 goto out; 82 } 83 if (!CFStringGetCString(kVal, buf, value_len * 2, kCFStringEncodingASCII)) { 84 warnx("PrintDictionary: unable to get value as C String"); 85 printf("* * * ERROR * * *\n"); 86 goto out; 87 } 88 printf("\"%s\"\n", buf); 89 free(buf); buf = NULL; 90 } else if (CFGetTypeID(kVal) == CFNumberGetTypeID()) { 91 if (!CFNumberGetValue(kVal, kCFNumberSInt32Type, &val)) { 92 warnx("PrintDictionary: unable to get value as 32-bit number"); 93 printf("* * * ERROR * * *\n"); 94 goto out; 95 } 96 printf(intFmt, val); 97 } 98 99out: 100 if (buf) 101 free(buf); 102 return; 103} 104 105void 106doProps(const char *dev, char **args) { 107 CFMutableDictionaryRef md = nil; 108 CFDictionaryRef old; 109 CFStringRef cfStr = nil; 110 CFNumberRef cfNum = nil; 111 int changes = 0; 112 113 int i; 114 115 old = ReadMetadata(dev); 116 if (old == nil) { 117 warnx("doProps: cannot get metadata for device %s", dev); 118 goto out; 119 } 120 121 md = CFDictionaryCreateMutableCopy(nil, 0, old); 122 123 if (md == nil) { 124 warnx("cannot create dictionary in doProps"); 125 goto out; 126 } 127 128 if (args[0] == NULL) { 129 CFDictionaryApplyFunction(old, &PrintValue, NULL); 130 goto out; 131 } 132 133 for (i = 0; args[i]; i++) { 134 char *arg = args[i]; 135 CFTypeRef v; 136 CFStringRef k; 137 138 if (parseProperty(arg, &k, &v) > 0) { 139 if (v == nil) { 140 /* No value, so just print it out */ 141 v = CFDictionaryGetValue(old, k); 142 if (v == nil) { 143 warnx("Property `%s' does not exist in metadata", arg); 144 } else { 145 PrintValue(k, v, NULL); 146 } 147 CFRelease(k); 148 continue; 149 } 150 // We have a key and a value, so we set them 151 CFDictionarySetValue(md, k, v); 152 printf("\tProperty %s\n", arg); 153 CFRelease(k); 154 CFRelease(v); 155 changes++; 156 } 157 } 158 159 if (gDebug) { 160 CFDataRef data; 161 int len; 162 char *cp; 163 data = CFPropertyListCreateXMLData(nil, (CFPropertyListRef)md); 164 len = CFDataGetLength(data); 165 cp = (char*)CFDataGetBytePtr(data); 166 write (2, cp, len); 167 CFRelease(data); 168 169 } 170 if (changes) { 171 if (WriteMetadata(dev, md) != 1) { 172 errx(3, "doProps: cannot write metadata"); 173 } 174 } 175out: 176 if (old) 177 CFRelease(old); 178 if (md) 179 CFRelease(md); 180 if (cfStr) 181 CFRelease(cfStr); 182 if (cfNum) 183 CFRelease(cfNum); 184 185 return; 186} 187 188