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 41static uint64_t 42ParseSize(char *str) { 43 uint64_t size, retval; 44 char *endptr; 45 uint64_t mult = 1; 46 47 fprintf(stderr, "ParseSize(%s)\n", str); 48 49 errno = 0; 50 size = strtoq(str, &endptr, 10); 51 if (errno != 0) { 52 warn("cannot parse `%s': ", str); 53 return -1; 54 } 55 56 if (endptr && *endptr != 0) { 57 if (strlen(endptr) != 1) { 58 warnx("cannot parse `%s': unknown suffix `%s'", 59 str, endptr); 60 return -1; 61 } 62 switch (*endptr) { 63 case 'b': case 'B': 64 mult = 512; break; 65 case 'k': case 'K': 66 mult = 1024; break; 67 case 'm': case 'M': 68 mult = 1024 * 1024; break; 69 case 'g': case 'G': 70 mult = 1024 * 1024 * 1024; break; 71 default: 72 warnx("cannot parse `%s': unknown suffix `%s'", 73 str, endptr); 74 return -1; 75 } 76 } 77 retval = size * mult; 78 return retval; 79} 80 81void 82doCreate(const char *dev, char **args) { 83 uint64_t size = 128 * 1024; // Default size of metadata area 84 CFMutableDictionaryRef md = nil; 85 CFStringRef cfStr = nil; 86 CFNumberRef cfNum = nil; 87 int blocksize = GetBlockSize(dev); 88 uint64_t disksize = GetDiskSize(dev); 89 90 int i; 91 92 if (blocksize == 0) { 93 errx(4, "doCreate: Cannot get valid blocksize for device %s", dev); 94 } 95 if (disksize == 0) { 96 errx(5, "doCreate: Cannot get valid disk size for device %s", dev); 97 } 98 99 100 md = CFDictionaryCreateMutable(nil, 0, nil, nil); 101 if (md == nil) { 102 warnx("cannot create dictionary in doCreate"); 103 goto out; 104 } 105 106 for (i = 0; args[i]; i++) { 107 char *arg = args[i]; 108 CFTypeRef v; 109 CFStringRef k; 110 111 if (parseProperty(arg, &k, &v) > 0) { 112 if (v == nil) { 113 warnx("cannot parse `%s': tag must have a value", arg); 114bad: 115 CFRelease(k); 116 continue; 117 } 118 if (CFStringCompare(k, CFSTR("-msize"), 0) 119 == kCFCompareEqualTo) { 120 if (CFGetTypeID(v) == CFStringGetTypeID()) { 121 int len = CFStringGetLength(v); 122 char buf[len*2]; 123 124 memset(buf, 0, sizeof(buf)); 125 if (CFStringGetCString(v, buf, sizeof(buf), kCFStringEncodingASCII) == FALSE) { 126 warnx("cannot convert msize to string!"); 127 goto bad; 128 } 129 size = ParseSize(buf); 130 } else if (CFGetTypeID(v) != CFNumberGetTypeID()) { 131 warnx("-msize value must be a number"); 132 goto bad; 133 } else { 134 CFNumberGetValue(v, kCFNumberSInt64Type, &size); 135 } 136 CFRelease(k); 137 CFRelease(v); 138 continue; 139 } 140 CFDictionaryAddValue(md, k, v); 141 } 142 } 143 144 if (size > 0) { 145 disksize = disksize - size; 146 cfNum = CFNumberCreate(NULL, kCFNumberSInt64Type, &size); 147 if (cfNum == NULL) { 148 errx(6, "doCreate: cannot create base number"); 149 } 150 CFDictionaryAddValue(md, CFSTR("Base"), cfNum); 151 CFRelease(cfNum); 152 cfNum = CFNumberCreate(NULL, kCFNumberSInt64Type, &disksize); 153 if (cfNum == NULL) { 154 errx(7, "doCreate: cannot create size number"); 155 } 156 CFDictionaryAddValue(md, CFSTR("Size"), cfNum); 157 if (gDebug) { 158 CFDataRef data; 159 int len; 160 char *cp; 161 data = CFPropertyListCreateXMLData(nil, (CFPropertyListRef)md); 162 len = CFDataGetLength(data); 163 cp = (char*)CFDataGetBytePtr(data); 164 fprintf(stderr, "Size = %qu bytes\n", size); 165 write (2, cp, len); 166 CFRelease(data); 167 168 } 169 // Now need to put the metadata in the partition 170 if (InitialMetadata(dev, md, size) == -1) { 171 errx(3, "Cannot write initial metadata to device %s", dev); 172 } 173 } 174out: 175 if (md) 176 CFRelease(md); 177 if (cfStr) 178 CFRelease(cfStr); 179 if (cfNum) 180 CFRelease(cfNum); 181 182 return; 183} 184 185