svn commit: r245092 - user/hrs/releng/usr.sbin/makevd

Hiroki Sato hrs at FreeBSD.org
Sun Jan 6 02:52:25 UTC 2013


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 at 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 at 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 */


More information about the svn-src-user mailing list