Date: Sun, 6 Jan 2013 02:52:24 +0000 (UTC) From: Hiroki Sato <hrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r245092 - user/hrs/releng/usr.sbin/makevd Message-ID: <201301060252.r062qOto066845@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hrs Date: Sun Jan 6 02:52:23 2013 New Revision: 245092 URL: http://svnweb.freebsd.org/changeset/base/245092 Log: Add Microsoft Virtual Hard Disk (VHD) Image Format support. At this moment, it generates a Fixed Hard Disk Image with CreatorVersion=0x00050000. Added: user/hrs/releng/usr.sbin/makevd/vhd.c (contents, props changed) user/hrs/releng/usr.sbin/makevd/vhd.h (contents, props changed) Modified: user/hrs/releng/usr.sbin/makevd/Makefile user/hrs/releng/usr.sbin/makevd/makevd.8 user/hrs/releng/usr.sbin/makevd/makevd.c user/hrs/releng/usr.sbin/makevd/makevd.h Modified: user/hrs/releng/usr.sbin/makevd/Makefile ============================================================================== --- user/hrs/releng/usr.sbin/makevd/Makefile Sun Jan 6 02:50:38 2013 (r245091) +++ user/hrs/releng/usr.sbin/makevd/Makefile Sun Jan 6 02:52:23 2013 (r245092) @@ -4,6 +4,7 @@ PROG= makevd MAN= makevd.8 SRCS= makevd.c \ raw.c \ + vhd.c \ vmdk.c WARNS?= 6 CFLAGS+= -I${.CURDIR} Modified: user/hrs/releng/usr.sbin/makevd/makevd.8 ============================================================================== --- user/hrs/releng/usr.sbin/makevd/makevd.8 Sun Jan 6 02:50:38 2013 (r245091) +++ user/hrs/releng/usr.sbin/makevd/makevd.8 Sun Jan 6 02:52:23 2013 (r245092) @@ -74,6 +74,8 @@ Create an virtual disk image. The following image types are supported: .Bl -tag -width cd9660 -offset indent +.It Sy vhd +Microsoft Virtual Hard Disk (VHD) Image Format. .It Sy vmdk VMWare Virtual Machine DisK (VMDK) Format. .It Sy raw @@ -82,6 +84,19 @@ No conversion (default). .El .\" .\" +.Ss VHD-specific options +.Sy vhd +images have VHD-specific parameters that may be provided. +Some are optional, and some are mandatory. +Each of the options consists of a keyword, an equal sign +.Pq Ql = , +and a value. +The following keywords are supported: +.Pp +.Bl -tag -width optimization -offset indent -compact +.It Fl o Sy uuid +UUID for the image. Mandatory. +.El .Ss VMDK-specific options .Sy vmdk images have VMDK-specific parameters that may be provided. Modified: user/hrs/releng/usr.sbin/makevd/makevd.c ============================================================================== --- user/hrs/releng/usr.sbin/makevd/makevd.c Sun Jan 6 02:50:38 2013 (r245091) +++ user/hrs/releng/usr.sbin/makevd/makevd.c Sun Jan 6 02:52:23 2013 (r245092) @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include "makevd.h" #include "vmdk.h" +#include "vhd.h" static LIST_HEAD(optlisthead_t, optlist) oplhead; @@ -50,6 +51,7 @@ static struct imtype { const char *imt_type; int (*imt_makeim)(struct iminfo *); } imtypes[] = { + { "vhd", vhd_makeim }, { "vmdk", vmdk_makeim }, { "none", raw_makeim }, { "raw", raw_makeim }, Modified: user/hrs/releng/usr.sbin/makevd/makevd.h ============================================================================== --- user/hrs/releng/usr.sbin/makevd/makevd.h Sun Jan 6 02:50:38 2013 (r245091) +++ user/hrs/releng/usr.sbin/makevd/makevd.h Sun Jan 6 02:52:23 2013 (r245092) @@ -49,6 +49,7 @@ struct optlist { char *opl_val; }; +int vhd_makeim(struct iminfo *); int vmdk_makeim(struct iminfo *); int raw_makeim(struct iminfo *); Added: user/hrs/releng/usr.sbin/makevd/vhd.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/hrs/releng/usr.sbin/makevd/vhd.c Sun Jan 6 02:52:23 2013 (r245092) @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 2011-2013 + * Hiroki Sato <hrs@FreeBSD.org> All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/uio.h> + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sysexits.h> +#include <unistd.h> + +#include "makevd.h" +#include "vhd.h" + +static uint32_t vhd_checksum(struct HardDiskFooter *); + +int +vhd_makeim(struct iminfo *imi) +{ + struct HardDiskFooter DHF, *imh; + uint64_t sectors, heads, cylinders, imagesize; + uint8_t uuid[16]; + char vhdfile[PATH_MAX + 10]; + char buf[BUFSIZ]; + char *p, *q; + ssize_t len0, len = 0; + int ifd, ofd; + + imh = &DHF; + ifd = imi->imi_fd; + imagesize = imi->imi_size; + + memset(imh, 0, sizeof(*imh)); + if (imi->imi_uuid == NULL) + errx(EX_USAGE, "-o uuid option must be specified."); + + p = imi->imi_uuid; +#if _BYTE_ORDER == _BIG_ENDIAN + q = (uint8_t *)&uuid + 16; +#else + q = (uint8_t *)&uuid; +#endif + while (len < 16 && strlen(p) > 1) { + long digit; + char *endptr; + + if (*p == '-') { + p++; + continue; + } + buf[0] = p[0]; + buf[1] = p[1]; + buf[2] = '\0'; + errno = 0; + digit = strtol(buf, &endptr, 16); + if (errno == 0 && *endptr != '\0') + errno = EINVAL; + if (errno) + errx(EX_DATAERR, "invalid UUID"); +#if _BYTE_ORDER == _BIG_ENDIAN + *q-- = digit; +#else + *q++ = digit; +#endif + len++; + p += 2; + } +#if 0 + { + int i; + + printf("uuid = "); + for (i = 0; i < 16; i++) + printf("%02x", uuid[i]); + printf("\n"); + } +#endif + snprintf(vhdfile, sizeof(vhdfile), "%s.vhd", imi->imi_imagename); + ofd = open(vhdfile, O_WRONLY|O_CREAT|O_TRUNC, + S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + if (ofd < 0) + err(EX_CANTCREAT, "%s", vhdfile); + + /* All of the fields are in BE byte order. */ + imh->Cookie = htobe64(HDF_COOKIE); + imh->Features = htobe32(HDF_FEATURES_RES); + imh->FileFormatVersion = htobe32(HDF_FILEFORMATVERSION_DEFAULT); + imh->DataOffset = htobe32(HDF_DATAOFFSET_FIXEDHDD); + imh->TimeStamp = 0; /* XXX */ + imh->CreatorApplication = htobe32(HDF_CREATORAPP_VPC); + imh->CreatorVersion = htobe32(HDF_CREATORVERSION_VPC2004); + imh->CreatorHostOS = htobe32(HDF_CREATORHOSTOS_WIN); + imh->OriginalSize = htobe64(imagesize); + imh->CurrentSize = htobe64(imagesize); + + sectors = 63; + heads = 16; + cylinders = imagesize / (sectors * heads * 512); + while (cylinders > 1024) { + cylinders >>= 1; + heads <<= 1; + } + imh->DiskGeometry.cylinder = htobe16(cylinders); + imh->DiskGeometry.heads = heads; + imh->DiskGeometry.sectcyl = sectors; + + imh->DiskType = htobe32(HDF_DISKTYPE_FIXEDHDD); + memcpy((char *)imh->UniqueId, (char *)&uuid, sizeof(imh->UniqueId)); + imh->SavedState = 0; + + imh->Checksum = htobe32(vhd_checksum(imh)); + + for (;;) { + len0 = read(ifd, buf, sizeof(buf)); + if (len0 == 0) + break; + if (len0 < 0) { + warn("read error"); + return (1); + } + len = write(ofd, buf, len0); + if (len < 0) { + warn("write error"); + return (1); + } + } + len0 = write(ofd, imh, sizeof(*imh)); + if (len0 != sizeof(*imh)) { + warn("write error"); + return (1); + } + + return (0); +} + +static uint32_t +vhd_checksum(struct HardDiskFooter *imh) +{ + uint32_t sum; + size_t len; + + sum = 0; + for (len = 0; len < sizeof(*imh); len++) + sum += ((uint8_t *)imh)[0]; + + return (~sum); +} Added: user/hrs/releng/usr.sbin/makevd/vhd.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/hrs/releng/usr.sbin/makevd/vhd.h Sun Jan 6 02:52:23 2013 (r245092) @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2011-2013 + * Hiroki Sato <hrs@FreeBSD.org> All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ +#ifndef _VHD_H +#define _VHD_H + +#include <sys/endian.h> +#include <stdint.h> + +/* All of the fields are in BE byte order. */ +struct HardDiskFooter { + uint64_t Cookie; +#define HDF_COOKIE (0x636f6e6563746978) /* "conectix" */ + uint32_t Features; +#define HDF_FEATURES_TEMP (0x00000001) +#define HDF_FEATURES_RES (0x00000002) + uint32_t FileFormatVersion; +#define HDF_FILEFORMATVERSION_DEFAULT (0x00010000) + uint64_t DataOffset; +#define HDF_DATAOFFSET_FIXEDHDD (0xFFFFFFFF) + uint32_t TimeStamp; + uint32_t CreatorApplication; +#define HDF_CREATORAPP_VPC (0x76707320) /* "vpc " */ +#define HDF_CREATORAPP_VS (0x76732020) /* "vs " */ + uint32_t CreatorVersion; +#define HDF_CREATORVERSION_VS2004 (0x00010000) +#define HDF_CREATORVERSION_VPC2004 (0x00050000) + uint32_t CreatorHostOS; +#define HDF_CREATORHOSTOS_WIN (0x5769326b) /* "Wi2k" */ +#define HDF_CREATORHOSTOS_MAC (0x4d616320) /* "Mac " */ + uint64_t OriginalSize; + uint64_t CurrentSize; + struct { + uint16_t cylinder; + uint8_t heads; + uint8_t sectcyl; + } DiskGeometry; + uint32_t DiskType; +#define HDF_DISKTYPE_FIXEDHDD (2) +#define HDF_DISKTYPE_DYNAMICHDD (3) +#define HDF_DISKTYPE_DIFFHDD (4) + uint32_t Checksum; + uint8_t UniqueId[16]; + uint8_t SavedState; + char Reserved[427]; +} __attribute__((__packed__)); + +struct DynamicDiskHeader { + uint64_t Cookie; +#define DDH_COOKIE (0x6378737061727365) /* "cxsparse" */ + uint64_t DataOffset; +#define DDH_DATAOFFSET (0xffffffff) + uint64_t TableOffset; + uint32_t HeaderVersion; +#define DDH_HEADERVERSION (0x00010000) + uint32_t MaxTableEntries; + uint32_t BlockSize; +#define DDH_BLOCKSIZE_DEFAULT (0x00200000) + uint32_t Checksum; + uint8_t ParentUniqueID[16]; + uint32_t ParentTimeStamp; + uint32_t Reserved1; + uint8_t ParentUnicodeName[512]; + uint8_t ParentLocatorEntry1[24]; + uint8_t ParentLocatorEntry2[24]; + uint8_t ParentLocatorEntry3[24]; + uint8_t ParentLocatorEntry4[24]; + uint8_t ParentLocatorEntry5[24]; + uint8_t ParentLocatorEntry6[24]; + uint8_t ParentLocatorEntry7[24]; + uint8_t ParentLocatorEntry8[24]; + uint8_t Reserved2[256]; +} __attribute__((__packed__)); + +#endif /* _VHD_H */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301060252.r062qOto066845>