Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 May 2014 19:19:58 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r266176 - head/usr.bin/mkimg
Message-ID:  <201405151919.s4FJJwmt056261@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Thu May 15 19:19:57 2014
New Revision: 266176
URL: http://svnweb.freebsd.org/changeset/base/266176

Log:
  MFuser/marcel/mkimg:
  Add support for different output formats:
  1.  The output file that was previously written is now called the raw format.
  2.  Add the vmdk output format to create VMDK images.
  
  When the format is not given, the raw output format is assumed.

Added:
  head/usr.bin/mkimg/format.c
     - copied unchanged from r266175, user/marcel/mkimg/format.c
  head/usr.bin/mkimg/format.h
     - copied unchanged from r266175, user/marcel/mkimg/format.h
  head/usr.bin/mkimg/image.c
     - copied unchanged from r266175, user/marcel/mkimg/image.c
  head/usr.bin/mkimg/image.h
     - copied unchanged from r266175, user/marcel/mkimg/image.h
  head/usr.bin/mkimg/raw.c
     - copied unchanged from r266175, user/marcel/mkimg/raw.c
  head/usr.bin/mkimg/vmdk.c
     - copied unchanged from r266175, user/marcel/mkimg/vmdk.c
Modified:
  head/usr.bin/mkimg/Makefile   (contents, props changed)
  head/usr.bin/mkimg/apm.c
  head/usr.bin/mkimg/bsd.c
  head/usr.bin/mkimg/ebr.c
  head/usr.bin/mkimg/gpt.c
  head/usr.bin/mkimg/mbr.c
  head/usr.bin/mkimg/mkimg.1   (contents, props changed)
  head/usr.bin/mkimg/mkimg.c
  head/usr.bin/mkimg/mkimg.h
  head/usr.bin/mkimg/pc98.c
  head/usr.bin/mkimg/scheme.c   (contents, props changed)
  head/usr.bin/mkimg/scheme.h   (contents, props changed)
  head/usr.bin/mkimg/vtoc8.c
Directory Properties:
  head/usr.bin/mkimg/   (props changed)

Modified: head/usr.bin/mkimg/Makefile
==============================================================================
--- head/usr.bin/mkimg/Makefile	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/Makefile	Thu May 15 19:19:57 2014	(r266176)
@@ -1,11 +1,16 @@
 # $FreeBSD$
 
 PROG=	mkimg
-SRCS=	mkimg.c scheme.c
+SRCS=	format.c image.c mkimg.c scheme.c
 MAN=	mkimg.1
 
 CFLAGS+=-DSPARSE_WRITE
 
+# List of formats to support
+SRCS+= \
+	raw.c \
+	vmdk.c
+
 # List of schemes to support
 SRCS+=	\
 	apm.c \

Modified: head/usr.bin/mkimg/apm.c
==============================================================================
--- head/usr.bin/mkimg/apm.c	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/apm.c	Thu May 15 19:19:57 2014	(r266176)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <unistd.h>
 
+#include "image.h"
 #include "mkimg.h"
 #include "scheme.h"
 
@@ -63,7 +64,7 @@ apm_metadata(u_int where)
 }
 
 static int
-apm_write(int fd, lba_t imgsz, void *bootcode __unused)
+apm_write(lba_t imgsz, void *bootcode __unused)
 {
 	u_char *buf;
 	struct apm_ddr *ddr;
@@ -99,7 +100,7 @@ apm_write(int fd, lba_t imgsz, void *boo
 			strcpy(ent->ent_name, part->label);
 	}
 
-	error = mkimg_write(fd, 0, buf, nparts + 2);
+	error = image_write(0, buf, nparts + 2);
 	free(buf);
 	return (error);
 }

Modified: head/usr.bin/mkimg/bsd.c
==============================================================================
--- head/usr.bin/mkimg/bsd.c	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/bsd.c	Thu May 15 19:19:57 2014	(r266176)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <unistd.h>
 
+#include "image.h"
 #include "mkimg.h"
 #include "scheme.h"
 
@@ -61,7 +62,7 @@ bsd_metadata(u_int where)
 }
 
 static int
-bsd_write(int fd, lba_t imgsz, void *bootcode)
+bsd_write(lba_t imgsz, void *bootcode)
 {
 	u_char *buf, *p;
 	struct disklabel *d;
@@ -80,7 +81,9 @@ bsd_write(int fd, lba_t imgsz, void *boo
 		memset(buf, 0, BBSIZE);
 
 	imgsz = ncyls * nheads * nsecs;
-	ftruncate(fd, imgsz * secsz);
+	error = image_set_size(imgsz);
+	if (error)
+		return (error);
 
 	d = (void *)(buf + secsz);
 	le32enc(&d->d_magic, DISKMAGIC);
@@ -111,7 +114,7 @@ bsd_write(int fd, lba_t imgsz, void *boo
 		checksum ^= le16dec(p);
 	le16enc(&d->d_checksum, checksum);
 
-	error = mkimg_write(fd, 0, buf, BBSIZE / secsz);
+	error = image_write(0, buf, BBSIZE / secsz);
 	free(buf);
 	return (error);
 }

Modified: head/usr.bin/mkimg/ebr.c
==============================================================================
--- head/usr.bin/mkimg/ebr.c	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/ebr.c	Thu May 15 19:19:57 2014	(r266176)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <unistd.h>
 
+#include "image.h"
 #include "mkimg.h"
 #include "scheme.h"
 
@@ -67,7 +68,7 @@ ebr_chs(u_char *cyl, u_char *hd, u_char 
 }
 
 static int
-ebr_write(int fd, lba_t imgsz __unused, void *bootcode __unused)
+ebr_write(lba_t imgsz __unused, void *bootcode __unused)
 {
 	u_char *ebr;
 	struct dos_partition *dp;
@@ -104,7 +105,7 @@ ebr_write(int fd, lba_t imgsz __unused, 
 			le32enc(&dp->dp_size, next->size + nsecs);
 		}
 
-		error = mkimg_write(fd, block, ebr, 1);
+		error = image_write(block, ebr, 1);
 		if (error)
 			break;
 

Copied: head/usr.bin/mkimg/format.c (from r266175, user/marcel/mkimg/format.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.bin/mkimg/format.c	Thu May 15 19:19:57 2014	(r266176, copy of r266175, user/marcel/mkimg/format.c)
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/linker_set.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "format.h"
+#include "mkimg.h"
+
+static struct mkimg_format *format;
+
+int
+format_resize(lba_t end)
+{
+
+	if (format == NULL)
+		return (ENOSYS);
+	return (format->resize(end));
+}
+
+int
+format_select(const char *spec)
+{
+	struct mkimg_format *f, **iter;
+
+	SET_FOREACH(iter, formats) {
+		f = *iter;
+		if (strcasecmp(spec, f->name) == 0) {
+			format = f;
+			return (0);
+		}
+	}
+	return (EINVAL);
+}
+
+struct mkimg_format *
+format_selected(void)
+{
+
+	return (format);
+}
+
+int
+format_write(int fd)
+{
+	lba_t size;
+	int error;
+
+	if (format == NULL)
+		return (ENOSYS);
+	size = image_get_size();
+	error = format->resize(size);
+	if (!error)
+		error = format->write(fd);
+	return (error);
+}

Copied: head/usr.bin/mkimg/format.h (from r266175, user/marcel/mkimg/format.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.bin/mkimg/format.h	Thu May 15 19:19:57 2014	(r266176, copy of r266175, user/marcel/mkimg/format.h)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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 AUTHOR 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 AUTHOR 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 _MKIMG_FORMAT_H_
+#define	_MKIMG_FORMAT_H_
+
+#include <sys/linker_set.h>
+
+struct mkimg_format {
+	const char	*name;
+	const char	*description;
+	int		(*resize)(lba_t);
+	int		(*write)(int);
+};
+
+SET_DECLARE(formats, struct mkimg_format);
+#define	FORMAT_DEFINE(nm)	DATA_SET(formats, nm)
+
+int	format_resize(lba_t);
+int	format_select(const char *);
+struct mkimg_format *format_selected(void);
+int	format_write(int);
+
+#endif /* _MKIMG_FORMAT_H_ */

Modified: head/usr.bin/mkimg/gpt.c
==============================================================================
--- head/usr.bin/mkimg/gpt.c	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/gpt.c	Thu May 15 19:19:57 2014	(r266176)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <unistd.h>
 #include <uuid.h>
 
+#include "image.h"
 #include "mkimg.h"
 #include "scheme.h"
 
@@ -166,7 +167,7 @@ gpt_metadata(u_int where)
 }
 
 static int
-gpt_write_pmbr(int fd, lba_t blks, void *bootcode)
+gpt_write_pmbr(lba_t blks, void *bootcode)
 {
 	u_char *pmbr;
 	uint32_t secs;
@@ -190,7 +191,7 @@ gpt_write_pmbr(int fd, lba_t blks, void 
 	le32enc(pmbr + DOSPARTOFF + 8, 1);
 	le32enc(pmbr + DOSPARTOFF + 12, secs);
 	le16enc(pmbr + DOSMAGICOFFSET, DOSMAGIC);
-	error = mkimg_write(fd, 0, pmbr, 1);
+	error = image_write(0, pmbr, 1);
 	free(pmbr);
 	return (error);
 }
@@ -226,8 +227,7 @@ gpt_mktbl(u_int tblsz)
 }
 
 static int
-gpt_write_hdr(int fd, struct gpt_hdr *hdr, uint64_t self, uint64_t alt,
-    uint64_t tbl)
+gpt_write_hdr(struct gpt_hdr *hdr, uint64_t self, uint64_t alt, uint64_t tbl)
 {
 	uint32_t crc;
 
@@ -237,11 +237,11 @@ gpt_write_hdr(int fd, struct gpt_hdr *hd
 	hdr->hdr_crc_self = 0;
 	crc = crc32(hdr, offsetof(struct gpt_hdr, padding));
 	le64enc(&hdr->hdr_crc_self, crc);
-	return (mkimg_write(fd, self, hdr, 1));
+	return (image_write(self, hdr, 1));
 }
 
 static int
-gpt_write(int fd, lba_t imgsz, void *bootcode)
+gpt_write(lba_t imgsz, void *bootcode)
 {
 	uuid_t uuid;
 	struct gpt_ent *tbl;
@@ -251,7 +251,7 @@ gpt_write(int fd, lba_t imgsz, void *boo
 	int error;
 
 	/* PMBR */
-	error = gpt_write_pmbr(fd, imgsz, bootcode);
+	error = gpt_write_pmbr(imgsz, bootcode);
 	if (error)
 		return (error);
 
@@ -260,10 +260,10 @@ gpt_write(int fd, lba_t imgsz, void *boo
 	tbl = gpt_mktbl(tblsz);
 	if (tbl == NULL)
 		return (errno);
-	error = mkimg_write(fd, 2, tbl, tblsz);
+	error = image_write(2, tbl, tblsz);
 	if (error)
 		goto out;
-	error = mkimg_write(fd, imgsz - (tblsz + 1), tbl, tblsz);
+	error = image_write(imgsz - (tblsz + 1), tbl, tblsz);
 	if (error)
 		goto out;
 
@@ -285,9 +285,9 @@ gpt_write(int fd, lba_t imgsz, void *boo
 	le32enc(&hdr->hdr_entsz, sizeof(struct gpt_ent));
 	crc = crc32(tbl, nparts * sizeof(struct gpt_ent));
 	le32enc(&hdr->hdr_crc_table, crc);
-	error = gpt_write_hdr(fd, hdr, 1, imgsz - 1, 2);
+	error = gpt_write_hdr(hdr, 1, imgsz - 1, 2);
 	if (!error)
-		error = gpt_write_hdr(fd, hdr, imgsz - 1, 1, imgsz - tblsz - 1);
+		error = gpt_write_hdr(hdr, imgsz - 1, 1, imgsz - tblsz - 1);
 	free(hdr);
 
  out:

Copied: head/usr.bin/mkimg/image.c (from r266175, user/marcel/mkimg/image.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.bin/mkimg/image.c	Thu May 15 19:19:57 2014	(r266176, copy of r266175, user/marcel/mkimg/image.c)
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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 AUTHOR 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 AUTHOR 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "mkimg.h"
+
+#define	BUFFER_SIZE	(1024*1024)
+
+static char image_tmpfile[] = "/tmp/mkimg-XXXXXX";
+static int image_fd = -1;
+static lba_t image_size;
+
+static void
+cleanup(void)
+{
+
+	if (image_fd != -1)
+		close(image_fd);
+	unlink(image_tmpfile);
+}
+
+int
+image_copyin(lba_t blk, int fd, uint64_t *sizep)
+{
+	char *buffer;
+	uint64_t bytesize;
+	ssize_t bcnt, rdsz;
+	int error, partial;
+
+	assert(BUFFER_SIZE % secsz == 0);
+
+	buffer = malloc(BUFFER_SIZE);
+	if (buffer == NULL)
+		return (ENOMEM);
+	bytesize = 0;
+	partial = 0;
+	while (1) {
+		rdsz = read(fd, buffer, BUFFER_SIZE);
+		if (rdsz <= 0) {
+			error = (rdsz < 0) ? errno : 0;
+			break;
+		}
+		if (partial)
+			abort();
+		bytesize += rdsz;
+		bcnt = (rdsz + secsz - 1) / secsz;
+		error = image_write(blk, buffer, bcnt);
+		if (error)
+			break;
+		blk += bcnt;
+		partial = ((ssize_t)(bcnt * secsz) != rdsz) ? 1 : 0;
+	}
+	free(buffer);
+	if (sizep != NULL)
+		*sizep = bytesize;
+	return (error);
+}
+
+int
+image_copyout(int fd)
+{
+	char *buffer;
+	off_t ofs;
+	ssize_t rdsz, wrsz;
+	int error;
+
+	ofs = lseek(fd, 0L, SEEK_CUR);
+
+	buffer = malloc(BUFFER_SIZE);
+	if (buffer == NULL)
+		return (errno);
+	if (lseek(image_fd, 0, SEEK_SET) != 0)
+		return (errno);
+	error = 0;
+	while (1) {
+		rdsz = read(image_fd, buffer, BUFFER_SIZE);
+		if (rdsz <= 0) {
+			error = (rdsz < 0) ? errno : 0;
+			break;
+		}
+		wrsz = (ofs == -1) ?
+		    write(fd, buffer, rdsz) :
+		    sparse_write(fd, buffer, rdsz);
+		if (wrsz < 0) {
+			error = errno;
+			break;
+		}
+	}
+	free(buffer);
+	ofs = lseek(fd, 0L, SEEK_CUR);
+	ftruncate(fd, ofs);
+	return (error);
+}
+
+lba_t
+image_get_size(void)
+{
+
+	return (image_size);
+}
+
+int
+image_set_size(lba_t blk)
+{
+
+	image_size = blk;
+	if (ftruncate(image_fd, blk * secsz) == -1)
+		return (errno);
+	return (0);
+}
+
+int
+image_write(lba_t blk, void *buf, ssize_t len)
+{
+
+	blk *= secsz;
+	if (lseek(image_fd, blk, SEEK_SET) != blk)
+		return (errno);
+	len *= secsz;
+	if (sparse_write(image_fd, buf, len) != len)
+		return (errno);
+	return (0);
+}
+
+int
+image_init(void)
+{
+
+	if (atexit(cleanup) == -1)
+		return (errno);
+	image_fd = mkstemp(image_tmpfile);
+	if (image_fd == -1)
+		return (errno);
+	return (0);
+}

Copied: head/usr.bin/mkimg/image.h (from r266175, user/marcel/mkimg/image.h)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.bin/mkimg/image.h	Thu May 15 19:19:57 2014	(r266176, copy of r266175, user/marcel/mkimg/image.h)
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2014 Juniper Networks, Inc.
+ * 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 AUTHOR 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 AUTHOR 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 _MKIMG_IMAGE_H_
+#define	_MKIMG_IMAGE_H_
+
+typedef int64_t lba_t;
+
+int image_copyin(lba_t blk, int fd, uint64_t *sizep);
+int image_copyout(int fd);
+lba_t image_get_size(void);
+int image_init(void);
+int image_set_size(lba_t blk);
+int image_write(lba_t blk, void *buf, ssize_t len);
+
+#endif /* _MKIMG_IMAGE_H_ */

Modified: head/usr.bin/mkimg/mbr.c
==============================================================================
--- head/usr.bin/mkimg/mbr.c	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/mbr.c	Thu May 15 19:19:57 2014	(r266176)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <unistd.h>
 
+#include "image.h"
 #include "mkimg.h"
 #include "scheme.h"
 
@@ -68,7 +69,7 @@ mbr_chs(u_char *cyl, u_char *hd, u_char 
 }
 
 static int
-mbr_write(int fd, lba_t imgsz __unused, void *bootcode)
+mbr_write(lba_t imgsz __unused, void *bootcode)
 {
 	u_char *mbr;
 	struct dos_partition *dpbase, *dp;
@@ -96,7 +97,7 @@ mbr_write(int fd, lba_t imgsz __unused, 
 		le32enc(&dp->dp_start, part->block);
 		le32enc(&dp->dp_size, part->size);
 	}
-	error = mkimg_write(fd, 0, mbr, 1);
+	error = image_write(0, mbr, 1);
 	free(mbr);
 	return (error);
 }

Modified: head/usr.bin/mkimg/mkimg.1
==============================================================================
--- head/usr.bin/mkimg/mkimg.1	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/mkimg.1	Thu May 15 19:19:57 2014	(r266176)
@@ -37,6 +37,7 @@
 .Op Fl S Ar secsz
 .Op Fl T Ar tracksz
 .Op Fl b Ar bootcode
+.Op Fl f Ar format
 .Op Fl o Ar outfile
 .Op Fl v
 .Fl s Ar scheme
@@ -56,6 +57,10 @@ The disk image is written to
 by default or the file specified with the
 .Ar outfile
 argument.
+The image file is a raw disk image by default, but the format of the
+image file can be specified with the
+.Ar format
+argument.
 .Pp
 The disk image can be made bootable by specifying the scheme-specific boot
 block contents with the
@@ -106,8 +111,8 @@ option increases the level of output tha
 .Nm
 utility prints.
 .Pp
-For a complete list of supported partitioning schemes or for a detailed
-description of how to specify partitions, run the
+For a complete list of supported partitioning schemes or supported output
+format, or for a detailed description of how to specify partitions, run the
 .Nm
 utility without any arguments.
 .Sh EXAMPLES
@@ -121,6 +126,14 @@ utility as follows:
 -p freebsd-ufs:=root-file-system.ufs -p freebsd-swap::1G \
 -o gpt.img
 .Pp
+The command line given above results in a raw image file.
+This is because no output format was given.
+To create a VMDK image for example, add the
+.Fl f Ar vmdk
+argument to the
+.Nm
+utility and name the output file accordingly.
+.Pp
 A nested partitioning scheme is created by running the
 .Nm
 utility twice.

Modified: head/usr.bin/mkimg/mkimg.c
==============================================================================
--- head/usr.bin/mkimg/mkimg.c	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/mkimg.c	Thu May 15 19:19:57 2014	(r266176)
@@ -42,15 +42,11 @@ __FBSDID("$FreeBSD$");
 #include <sysexits.h>
 #include <unistd.h>
 
+#include "image.h"
+#include "format.h"
 #include "mkimg.h"
 #include "scheme.h"
 
-#if !defined(SPARSE_WRITE)
-#define	sparse_write	write
-#endif
-
-#define	BUFFER_SIZE	(1024*1024)
-
 struct partlisthead partlist = STAILQ_HEAD_INITIALIZER(partlist);
 u_int nparts = 0;
 
@@ -62,31 +58,18 @@ u_int nsecs = 1;
 u_int secsz = 512;
 u_int blksz = 0;
 
-static int bcfd = -1;
-static int outfd = 0;
-static int tmpfd = -1;
-
-static char tmpfname[] = "/tmp/mkimg-XXXXXX";
-
-static void
-cleanup(void)
-{
-
-	if (tmpfd != -1)
-		close(tmpfd);
-	unlink(tmpfname);
-}
-
 static void
 usage(const char *why)
 {
-	struct mkimg_scheme *s, **iter;
+	struct mkimg_format *f, **f_iter;
+	struct mkimg_scheme *s, **s_iter;
 
 	warnx("error: %s", why);
 	fprintf(stderr, "\nusage: %s <options>\n", getprogname());
 
 	fprintf(stderr, "    options:\n");
 	fprintf(stderr, "\t-b <file>\t-  file containing boot code\n");
+	fprintf(stderr, "\t-f <format>\n");
 	fprintf(stderr, "\t-o <file>\t-  file to write image into\n");
 	fprintf(stderr, "\t-p <partition>\n");
 	fprintf(stderr, "\t-s <scheme>\n");
@@ -95,13 +78,19 @@ usage(const char *why)
 	fprintf(stderr, "\t-S <num>\t-  logical sector size\n");
 	fprintf(stderr, "\t-T <num>\t-  number of tracks to simulate\n");
 
-	fprintf(stderr, "    schemes:\n");
-	SET_FOREACH(iter, schemes) {
-		s = *iter;
+	fprintf(stderr, "\n    formats:\n");
+	SET_FOREACH(f_iter, formats) {
+		f = *f_iter;
+		fprintf(stderr, "\t%s\t-  %s\n", f->name, f->description);
+	}
+
+	fprintf(stderr, "\n    schemes:\n");
+	SET_FOREACH(s_iter, schemes) {
+		s = *s_iter;
 		fprintf(stderr, "\t%s\t-  %s\n", s->name, s->description);
 	}
 
-	fprintf(stderr, "    partition specification:\n");
+	fprintf(stderr, "\n    partition specification:\n");
 	fprintf(stderr, "\t<t>[/<l>]::<size>\t-  empty partition of given "
 	    "size\n");
 	fprintf(stderr, "\t<t>[/<l>]:=<file>\t-  partition content and size "
@@ -228,14 +217,15 @@ parse_part(const char *spec)
 }
 
 #if defined(SPARSE_WRITE)
-static ssize_t
-sparse_write(int fd, const char *buf, size_t sz)
+ssize_t
+sparse_write(int fd, const void *ptr, size_t sz)
 {
-	const char *p;
+	const char *buf, *p;
 	off_t ofs;
 	size_t len;
 	ssize_t wr, wrsz;
 
+	buf = ptr;
 	wrsz = 0;
 	p = memchr(buf, 0, sz);
 	while (sz > 0) {
@@ -268,66 +258,8 @@ sparse_write(int fd, const char *buf, si
 }
 #endif /* SPARSE_WRITE */
 
-static int
-fdcopy(int src, int dst, uint64_t *count)
-{
-	char *buffer;
-	off_t ofs;
-	ssize_t rdsz, wrsz;
-
-	/* A return value of -1 means that we can't write a sparse file. */
-	ofs = lseek(dst, 0L, SEEK_CUR);
-
-	if (count != NULL)
-		*count = 0;
-
-	buffer = malloc(BUFFER_SIZE);
-	if (buffer == NULL)
-		return (errno);
-	while (1) {
-		rdsz = read(src, buffer, BUFFER_SIZE);
-		if (rdsz <= 0) {
-			free(buffer);
-			return ((rdsz < 0) ? errno : 0);
-		}
-		if (count != NULL)
-			*count += rdsz;
-		wrsz = (ofs == -1) ?
-		    write(dst, buffer, rdsz) :
-		    sparse_write(dst, buffer, rdsz);
-		if (wrsz < 0)
-			break;
-	}
-	free(buffer);
-	return (errno);
-}
-
-static int
-mkimg_seek(int fd, lba_t blk)
-{
-	off_t off;
-
-	off = blk * secsz;
-	if (lseek(fd, off, SEEK_SET) != off)
-		return (errno);
-	return (0);
-}
-
-int
-mkimg_write(int fd, lba_t blk, void *buf, ssize_t len)
-{
-
-	blk *= secsz;
-	if (lseek(fd, blk, SEEK_SET) != blk)
-		return (errno);
-	len *= secsz;
-	if (write(fd, buf, len) != len)
-		return (errno);
-	return (0);
-}
-
 static void
-mkimg(int bfd)
+mkimg(void)
 {
 	FILE *fp;
 	struct part *part;
@@ -335,10 +267,6 @@ mkimg(int bfd)
 	off_t bytesize;
 	int error, fd;
 
-	error = scheme_bootcode(bfd);
-	if (error)
-		errc(EX_DATAERR, error, "boot code");
-
 	/* First check partition information */
 	STAILQ_FOREACH(part, &partlist, link) {
 		error = scheme_check_part(part);
@@ -353,7 +281,6 @@ mkimg(int bfd)
 			fprintf(stderr, "partition %d: starting block %llu "
 			    "... ", part->index + 1, (long long)block);
 		part->block = block;
-		error = mkimg_seek(tmpfd, block);
 		switch (part->kind) {
 		case PART_KIND_SIZE:
 			if (expand_number(part->contents, &bytesize) == -1)
@@ -362,7 +289,7 @@ mkimg(int bfd)
 		case PART_KIND_FILE:
 			fd = open(part->contents, O_RDONLY, 0);
 			if (fd != -1) {
-				error = fdcopy(fd, tmpfd, &bytesize);
+				error = image_copyin(block, fd, &bytesize);
 				close(fd);
 			} else
 				error = errno;
@@ -370,7 +297,8 @@ mkimg(int bfd)
 		case PART_KIND_PIPE:
 			fp = popen(part->contents, "r");
 			if (fp != NULL) {
-				error = fdcopy(fileno(fp), tmpfd, &bytesize);
+				fd = fileno(fp);
+				error = image_copyin(block, fd, &bytesize);
 				pclose(fp);
 			} else
 				error = errno;
@@ -389,15 +317,27 @@ mkimg(int bfd)
 	}
 
 	block = scheme_metadata(SCHEME_META_IMG_END, block);
-	error = (scheme_write(tmpfd, block));
+	error = image_set_size(block);
+	if (!error)
+		error = format_resize(block);
+	if (error)
+		errc(EX_IOERR, error, "image sizing");
+	block = image_get_size();
+	ncyls = block / (nsecs * nheads);
+	error = (scheme_write(block));
+	if (error)
+		errc(EX_IOERR, error, "writing metadata");
 }
 
 int
 main(int argc, char *argv[])
 {
+	int bcfd, outfd;
 	int c, error;
 
-	while ((c = getopt(argc, argv, "b:o:p:s:vH:P:S:T:")) != -1) {
+	bcfd = -1;
+	outfd = 1;	/* Write to stdout by default */
+	while ((c = getopt(argc, argv, "b:f:o:p:s:vH:P:S:T:")) != -1) {
 		switch (c) {
 		case 'b':	/* BOOT CODE */
 			if (bcfd != -1)
@@ -406,8 +346,15 @@ main(int argc, char *argv[])
 			if (bcfd == -1)
 				err(EX_UNAVAILABLE, "%s", optarg);
 			break;
+		case 'f':	/* OUTPUT FORMAT */
+			if (format_selected() != NULL)
+				usage("multiple formats given");
+			error = format_select(optarg);
+			if (error)
+				errc(EX_DATAERR, error, "format");
+			break;
 		case 'o':	/* OUTPUT FILE */
-			if (outfd != 0)
+			if (outfd != 1)
 				usage("multiple output files given");
 			outfd = open(optarg, O_WRONLY | O_CREAT | O_TRUNC,
 			    S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
@@ -480,35 +427,43 @@ main(int argc, char *argv[])
 		errx(EX_DATAERR, "%d partitions supported; %d given",
 		    scheme_max_parts(), nparts);
 
-	if (outfd == 0) {
-		if (atexit(cleanup) == -1)
-			err(EX_OSERR, "cannot register cleanup function");
-		outfd = 1;
-		tmpfd = mkstemp(tmpfname);
-		if (tmpfd == -1)
-			err(EX_OSERR, "cannot create temporary file");
-	} else
-		tmpfd = outfd;
+	if (format_selected() == NULL)
+		format_select("raw");
+
+	if (bcfd != -1) {
+		error = scheme_bootcode(bcfd);
+		close(bcfd);
+		if (error)
+			errc(EX_DATAERR, error, "boot code");
+	}
 
 	if (verbose) {
 		fprintf(stderr, "Logical sector size: %u\n", secsz);
 		fprintf(stderr, "Physical block size: %u\n", blksz);
 		fprintf(stderr, "Sectors per track:   %u\n", nsecs);
 		fprintf(stderr, "Number of heads:     %u\n", nheads);
+		fputc('\n', stderr);
+		fprintf(stderr, "Partitioning scheme: %s\n",
+		    scheme_selected()->name);
+		fprintf(stderr, "Output file format:  %s\n",
+		    format_selected()->name);
+		fputc('\n', stderr);
 	}
 
-	mkimg(bcfd);
+	error = image_init();
+	if (error)
+		errc(EX_OSERR, error, "cannot initialize");
 
-	if (verbose)
-		fprintf(stderr, "Number of cylinders: %u\n", ncyls);
+	mkimg();
 
-	if (tmpfd != outfd) {
-		error = mkimg_seek(tmpfd, 0);
-		if (error == 0)
-			error = fdcopy(tmpfd, outfd, NULL);
-		if (error)
-			errc(EX_IOERR, error, "writing to stdout");
+	if (verbose) {
+		fputc('\n', stderr);
+		fprintf(stderr, "Number of cylinders: %u\n", ncyls);
 	}
 
+	error = format_write(outfd);
+	if (error)
+		errc(EX_IOERR, error, "writing image");
+
 	return (0);
 }

Modified: head/usr.bin/mkimg/mkimg.h
==============================================================================
--- head/usr.bin/mkimg/mkimg.h	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/mkimg.h	Thu May 15 19:19:57 2014	(r266176)
@@ -31,8 +31,6 @@
 
 #include <sys/queue.h>
 
-typedef int64_t	lba_t;
-
 struct part {
 	STAILQ_ENTRY(part) link;
 	char	*alias;		/* Partition type alias. */
@@ -67,6 +65,10 @@ round_block(lba_t n)
 	return ((n + b - 1) & ~(b - 1));
 }
 
-int mkimg_write(int fd, lba_t blk, void *buf, ssize_t len);
+#if !defined(SPARSE_WRITE)
+#define	sparse_write	write
+#else
+ssize_t sparse_write(int, const void *, size_t);
+#endif
 
 #endif /* _MKIMG_MKIMG_H_ */

Modified: head/usr.bin/mkimg/pc98.c
==============================================================================
--- head/usr.bin/mkimg/pc98.c	Thu May 15 19:09:31 2014	(r266175)
+++ head/usr.bin/mkimg/pc98.c	Thu May 15 19:19:57 2014	(r266176)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <string.h>
 #include <unistd.h>
 
+#include "image.h"
 #include "mkimg.h"
 #include "scheme.h"
 
@@ -77,7 +78,7 @@ pc98_chs(u_short *cyl, u_char *hd, u_cha
 }
 
 static int
-pc98_write(int fd, lba_t imgsz __unused, void *bootcode)
+pc98_write(lba_t imgsz __unused, void *bootcode)
 {
 	struct part *part;
 	struct pc98_partition *dpbase, *dp;
@@ -106,7 +107,7 @@ pc98_write(int fd, lba_t imgsz __unused,
 		if (part->label != NULL)
 			memcpy(dp->dp_name, part->label, strlen(part->label));
 	}
-	error = mkimg_write(fd, 0, buf, PC98_BOOTCODESZ / secsz);
+	error = image_write(0, buf, PC98_BOOTCODESZ / secsz);
 	free(buf);
 	return (error);
 }

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405151919.s4FJJwmt056261>