#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <err.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <CoreFoundation/CoreFoundation.h>
#include "util.h"
static u_int64_t
ParseSize(char *str) {
u_int64_t size, retval;
char *endptr;
u_int64_t mult = 1;
fprintf(stderr, "ParseSize(%s)\n", str);
errno = 0;
size = strtoq(str, &endptr, 10);
if (errno != 0) {
warn("cannot parse `%s': ", str);
return -1;
}
if (endptr && *endptr != 0) {
if (strlen(endptr) != 1) {
warnx("cannot parse `%s': unknown suffix `%s'",
str, endptr);
return -1;
}
switch (*endptr) {
case 'b': case 'B':
mult = 512; break;
case 'k': case 'K':
mult = 1024; break;
case 'm': case 'M':
mult = 1024 * 1024; break;
case 'g': case 'G':
mult = 1024 * 1024 * 1024; break;
default:
warnx("cannot parse `%s': unknown suffix `%s'",
str, endptr);
return -1;
}
}
retval = size * mult;
return retval;
}
void
doCreate(const char *dev, char **args) {
u_int64_t size = 128 * 1024; CFMutableDictionaryRef md = nil;
CFStringRef cfStr = nil;
CFNumberRef cfNum = nil;
int blocksize = GetBlockSize(dev);
uint64_t disksize = GetDiskSize(dev);
int i;
if (blocksize == 0) {
errx(4, "doCreate: Cannot get valid blocksize for device %s", dev);
}
if (disksize == 0) {
errx(5, "doCreate: Cannot get valid disk size for device %s", dev);
}
md = CFDictionaryCreateMutable(nil, 0, nil, nil);
if (md == nil) {
warnx("cannot create dictionary in doCreate");
goto out;
}
for (i = 0; args[i]; i++) {
char *arg = args[i];
CFTypeRef v;
CFStringRef k;
if (parseProperty(arg, &k, &v) > 0) {
if (v == nil) {
warnx("cannot parse `%s': tag must have a value", arg);
bad:
CFRelease(v);
CFRelease(k);
continue;
}
if (CFStringCompare(k, CFSTR("-msize"), 0)
== kCFCompareEqualTo) {
if (CFGetTypeID(v) == CFStringGetTypeID()) {
int len = CFStringGetLength(v);
char buf[len*2];
memset(buf, 0, sizeof(buf));
if (CFStringGetCString(v, buf, sizeof(buf), kCFStringEncodingASCII) == FALSE) {
warnx("cannot convert msize to string!");
goto bad;
}
size = ParseSize(buf);
} else if (CFGetTypeID(v) != CFNumberGetTypeID()) {
warnx("-msize value must be a number");
goto bad;
} else {
CFNumberGetValue(v, kCFNumberSInt64Type, &size);
}
CFRelease(k);
CFRelease(v);
continue;
}
CFDictionaryAddValue(md, k, v);
}
}
if (size > 0) {
disksize = disksize - size;
cfNum = CFNumberCreate(NULL, kCFNumberSInt64Type, &size);
if (cfNum == NULL) {
errx(6, "doCreate: cannot create base number");
}
CFDictionaryAddValue(md, CFSTR("Base"), cfNum);
cfNum = CFNumberCreate(NULL, kCFNumberSInt64Type, &disksize);
if (cfNum == NULL) {
errx(7, "doCreate: cannot create size number");
}
CFDictionaryAddValue(md, CFSTR("Size"), cfNum);
if (gDebug) {
CFDataRef data;
int len;
char *cp;
data = CFPropertyListCreateXMLData(nil, (CFPropertyListRef)md);
len = CFDataGetLength(data);
cp = (char*)CFDataGetBytePtr(data);
fprintf(stderr, "Size = %qu bytes\n", size);
write (2, cp, len);
CFRelease(data);
}
if (InitialMetadata(dev, md, size) == -1) {
errx(3, "Cannot write initial metadata to device %s", dev);
}
}
out:
if (md)
CFRelease(md);
if (cfStr)
CFRelease(cfStr);
if (cfNum)
CFRelease(cfNum);
return;
}