Module Name:    src
Committed By:   christos
Date:           Tue Dec  1 09:05:33 UTC 2015

Modified Files:
        src/sbin/gpt: Makefile add.c backup.c biosboot.c create.c destroy.c
            gpt.8 gpt.c gpt.h header.c label.c main.c map.c map.h migrate.c
            recover.c remove.c resize.c resizedisk.c restore.c set.c show.c
            type.c unset.c
Added Files:
        src/sbin/gpt: gpt_private.h

Log Message:
Firs step of refactoring, remove all globals, factor out some common code,
handle alternate usage but not advertise it.


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sbin/gpt/Makefile
cvs rdiff -u -r1.30 -r1.31 src/sbin/gpt/add.c
cvs rdiff -u -r1.9 -r1.10 src/sbin/gpt/backup.c src/sbin/gpt/restore.c
cvs rdiff -u -r1.15 -r1.16 src/sbin/gpt/biosboot.c
cvs rdiff -u -r1.13 -r1.14 src/sbin/gpt/create.c
cvs rdiff -u -r1.7 -r1.8 src/sbin/gpt/destroy.c src/sbin/gpt/recover.c \
    src/sbin/gpt/resizedisk.c src/sbin/gpt/type.c
cvs rdiff -u -r1.38 -r1.39 src/sbin/gpt/gpt.8
cvs rdiff -u -r1.48 -r1.49 src/sbin/gpt/gpt.c
cvs rdiff -u -r1.22 -r1.23 src/sbin/gpt/gpt.h src/sbin/gpt/migrate.c
cvs rdiff -u -r0 -r1.1 src/sbin/gpt/gpt_private.h
cvs rdiff -u -r1.3 -r1.4 src/sbin/gpt/header.c src/sbin/gpt/map.h
cvs rdiff -u -r1.19 -r1.20 src/sbin/gpt/label.c
cvs rdiff -u -r1.1 -r1.2 src/sbin/gpt/main.c
cvs rdiff -u -r1.10 -r1.11 src/sbin/gpt/map.c
cvs rdiff -u -r1.17 -r1.18 src/sbin/gpt/remove.c
cvs rdiff -u -r1.14 -r1.15 src/sbin/gpt/resize.c
cvs rdiff -u -r1.6 -r1.7 src/sbin/gpt/set.c src/sbin/gpt/unset.c
cvs rdiff -u -r1.23 -r1.24 src/sbin/gpt/show.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/gpt/Makefile
diff -u src/sbin/gpt/Makefile:1.16 src/sbin/gpt/Makefile:1.17
--- src/sbin/gpt/Makefile:1.16	Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/Makefile	Tue Dec  1 04:05:33 2015
@@ -1,12 +1,17 @@
-# $NetBSD: Makefile,v 1.16 2015/11/30 19:59:34 christos Exp $
+# $NetBSD: Makefile,v 1.17 2015/12/01 09:05:33 christos Exp $
 # $FreeBSD: src/sbin/gpt/Makefile,v 1.7 2005/09/01 02:49:20 marcel Exp $
 
+.include <bsd.own.mk>
+
 PROG=	gpt
 SRCS=	add.c biosboot.c create.c destroy.c gpt.c header.c label.c map.c \
 	main.c migrate.c recover.c remove.c resize.c resizedisk.c \
 	set.c show.c type.c unset.c gpt_uuid.c
 MAN=	gpt.8
 
+#LINKS=  ${BINDIR}/gpt ${BINDIR}/gptlabel
+#MLINKS= gpt.8 gptlabel.8
+
 .if (${HOSTPROG:U} == "")
 SRCS+= backup.c restore.c
 LDADD+=	-lprop -lutil

Index: src/sbin/gpt/add.c
diff -u src/sbin/gpt/add.c:1.30 src/sbin/gpt/add.c:1.31
--- src/sbin/gpt/add.c:1.30	Mon Nov 30 21:03:55 2015
+++ src/sbin/gpt/add.c	Tue Dec  1 04:05:33 2015
@@ -33,10 +33,12 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: add.c,v 1.30 2015/12/01 02:03:55 christos Exp $");
+__RCSID("$NetBSD: add.c,v 1.31 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
 
 #include <err.h>
 #include <stddef.h>
@@ -47,6 +49,7 @@ __RCSID("$NetBSD: add.c,v 1.30 2015/12/0
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static gpt_uuid_t type;
 static off_t alignment, block, sectors, size;
@@ -54,9 +57,9 @@ static unsigned int entry;
 static uint8_t *name;
 
 const char addmsg1[] = "add [-a alignment] [-b blocknr] [-i index] [-l label]";
-const char addmsg2[] = "    [-s size] [-t type] device ...";
+const char addmsg2[] = "    [-s size] [-t type]";
 
-__dead static void
+static int
 usage_add(void)
 {
 
@@ -64,131 +67,89 @@ usage_add(void)
 	    "usage: %s %s\n"
 	    "       %*s %s\n", getprogname(), addmsg1,
 	    (int)strlen(getprogname()), "", addmsg2);
-	exit(1);
+	return -1;
 }
 
-static void
-add(int fd)
+static int
+add(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *map;
+	map_t map;
 	struct gpt_hdr *hdr;
-	struct gpt_ent *ent;
+	struct gpt_ent *ent, e;
 	unsigned int i;
 	off_t alignsecs;
 	
+	if ((hdr = gpt_hdr(gpt)) == NULL)
+		return -1;
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
 	ent = NULL;
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
-
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
 
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
-
-	hdr = gpt->map_data;
 	if (entry > le32toh(hdr->hdr_entries)) {
-		warnx("%s: error: index %u out of range (%u max)", device_name,
+		gpt_warnx(gpt, "index %u out of range (%u max)",
 		    entry, le32toh(hdr->hdr_entries));
-		return;
+		return -1;
 	}
 
 	if (entry > 0) {
 		i = entry - 1;
-		ent = (void*)((char*)tbl->map_data + i *
-		    le32toh(hdr->hdr_entsz));
+		ent = gpt_ent_primary(gpt, i);
 		if (!gpt_uuid_is_nil(ent->ent_type)) {
-			warnx("%s: error: entry at index %u is not free",
-			    device_name, entry);
-			return;
+			gpt_warnx(gpt, "Entry at index %u is not free", entry);
+			return -1;
 		}
 	} else {
 		/* Find empty slot in GPT table. */
 		for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
-			ent = (void*)((char*)tbl->map_data + i *
-			    le32toh(hdr->hdr_entsz));
+			ent = gpt_ent_primary(gpt, i);
 			if (gpt_uuid_is_nil(ent->ent_type))
 				break;
 		}
 		if (i == le32toh(hdr->hdr_entries)) {
-			warnx("%s: error: no available table entries",
-			    device_name);
-			return;
+			gpt_warnx(gpt, "No available table entries");
+			return -1;
 		}
 	}
 
 	if (alignment > 0) {
-		alignsecs = alignment / secsz;
-		map = map_alloc(block, sectors, alignsecs);
+		alignsecs = alignment / gpt->secsz;
+		map = map_alloc(gpt, block, sectors, alignsecs);
 		if (map == NULL) {
-			warnx("%s: error: not enough space available on "
-			      "device for an aligned partition", device_name);
-			return;
+			gpt_warnx(gpt, "Not enough space available on "
+			      "device for an aligned partition");
+			return -1;
 		}
 	} else {
-		map = map_alloc(block, sectors, 0);
+		map = map_alloc(gpt, block, sectors, 0);
 		if (map == NULL) {
-			warnx("%s: error: not enough space available on "
-			      "device", device_name);
-			return;
+			gpt_warnx(gpt, "Not enough space available on device");
+			return -1;
 		}
 	}
 
-	gpt_uuid_copy(ent->ent_type, type);
-	ent->ent_lba_start = htole64(map->map_start);
-	ent->ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
-	if (name != NULL)
-		utf8_to_utf16(name, ent->ent_name, 36);
-
-	hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, gpt);
-	gpt_write(fd, tbl);
-
-	hdr = tpg->map_data;
-	ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
-
-	gpt_uuid_copy(ent->ent_type, type);
-	ent->ent_lba_start = htole64(map->map_start);
-	ent->ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
+	memset(&e, 0, sizeof(e));
+	gpt_uuid_copy(e.ent_type, type);
+	e.ent_lba_start = htole64(map->map_start);
+	e.ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
 	if (name != NULL)
-		utf8_to_utf16(name, ent->ent_name, 36);
+		utf8_to_utf16(name, e.ent_name, 36);
 
-	hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+	memcpy(ent, &e, sizeof(e));
+	gpt_write_primary(gpt);
 
-	gpt_write(fd, lbt);
-	gpt_write(fd, tpg);
+	ent = gpt_ent_backup(gpt, i);
+	memcpy(ent, &e, sizeof(e));
+	gpt_write_backup(gpt);
 
-	gpt_msg("Partition %d added: %s %" PRIu64 " %" PRIu64 "\n", i + 1,
+	gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64 "\n", i + 1,
 	    type, map->map_start, map->map_size);
+	return 0;
 }
 
 int
-cmd_add(int argc, char *argv[])
+cmd_add(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 	int64_t human_num;
 
 	while ((ch = getopt(argc, argv, "a:b:i:l:s:t:")) != -1) {
@@ -257,44 +218,23 @@ cmd_add(int argc, char *argv[])
 				usage_add();
 			break;
 		default:
-			usage_add();
+			return usage_add();
 		}
 	}
 
 	if (argc == optind)
-		usage_add();
+		return usage_add();
 
 	/* Create NetBSD FFS partitions by default. */
 	if (gpt_uuid_is_nil(type)) {
 		gpt_uuid_create(GPT_TYPE_NETBSD_FFS, type, NULL, 0);
 	}
 
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		if (alignment % secsz != 0) {
-			warnx("Alignment must be a multiple of sector size;");
-			warnx("the sector size for %s is %d bytes.",
-			    device_name, secsz);
-			continue;
-		}
-
-		if (size % secsz != 0) {
-			warnx("Size in bytes must be a multiple of sector "
-			      "size;");
-			warnx("the sector size for %s is %d bytes.",
-			    device_name, secsz);
-			continue;
-		}
-		if (size > 0)
-			sectors = size / secsz;
-
-		add(fd);
+	if (optind != argc)
+		return usage_add();
 
-		gpt_close(fd);
-	}
+	if ((sectors = gpt_check(gpt, alignment, size)) == -1)
+		return -1;
 
-	return (0);
+	return add(gpt);
 }

Index: src/sbin/gpt/backup.c
diff -u src/sbin/gpt/backup.c:1.9 src/sbin/gpt/backup.c:1.10
--- src/sbin/gpt/backup.c:1.9	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/backup.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: backup.c,v 1.9 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: backup.c,v 1.10 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/bootblock.h>
@@ -49,31 +49,32 @@ __RCSID("$NetBSD: backup.c,v 1.9 2015/11
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 
-const char backupmsg[] = "backup device ...";
+const char backupmsg[] = "backup";
 
-__dead static void
+static int
 usage_backup(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), backupmsg);
-	exit(1);
+	return -1;
 }
 
-#define PROP_ERR(x)	if (!(x)) {		\
-		warn("proplib failure");	\
-		return;				\
+#define PROP_ERR(x)	if (!(x)) {			\
+		gpt_warnx(gpt, "proplib failure");	\
+		return -1;				\
 	}
 
-static void
-backup(void)
+static int
+backup(gpt_t gpt)
 {
-	map_t *m;
+	map_t m;
 	struct mbr *mbr;
-	struct gpt_ent *ent;
 	struct gpt_hdr *hdr;
+	struct gpt_ent *ent;
 	unsigned int i;
 	prop_dictionary_t props, mbr_dict, gpt_dict, type_dict;
 	prop_array_t mbr_array, gpt_array;
@@ -85,11 +86,11 @@ backup(void)
 
 	props = prop_dictionary_create();
 	PROP_ERR(props);
-	propnum = prop_number_create_integer(secsz);
+	propnum = prop_number_create_integer(gpt->secsz);
 	PROP_ERR(propnum);
 	rc = prop_dictionary_set(props, "sector_size", propnum);
 	PROP_ERR(rc);
-	m = map_first();
+	m = map_first(gpt);
 	while (m != NULL) {
 		switch (m->map_type) {
 		case MAP_TYPE_MBR:
@@ -222,7 +223,7 @@ backup(void)
 			PROP_ERR(gpt_array);
 			for (i = 1, ent = m->map_data;
 			    (char *)ent < (char *)(m->map_data) +
-			    m->map_size * secsz; i++, ent++) {
+			    m->map_size * gpt->secsz; i++, ent++) {
 				gpt_dict = prop_dictionary_create();
 				PROP_ERR(gpt_dict);
 				propnum = prop_number_create_integer(i);
@@ -285,24 +286,14 @@ backup(void)
 	prop_object_release(props);
 	fputs(propext, stdout);
 	free(propext);
+	return 0;
 }
 
 int
-cmd_backup(int argc, char *argv[])
+cmd_backup(gpt_t gpt, int argc, char *argv[])
 {
-	int fd;
-
-	if (argc == optind)
+	if (argc != optind)
 		usage_backup();
 
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-		backup();
-
-		gpt_close(fd);
-	}
-
-	return (0);
+	return backup(gpt);
 }
Index: src/sbin/gpt/restore.c
diff -u src/sbin/gpt/restore.c:1.9 src/sbin/gpt/restore.c:1.10
--- src/sbin/gpt/restore.c:1.9	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/restore.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/create.c,v 1.11 2005/08/31 01:47:19 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: restore.c,v 1.9 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: restore.c,v 1.10 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -50,31 +50,32 @@ __RCSID("$NetBSD: restore.c,v 1.9 2015/1
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static int force;
 
-const char restoremsg[] = "restore [-F] device ...";
+const char restoremsg[] = "restore [-F]";
 
-__dead static void
+static int
 usage_restore(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), restoremsg);
-	exit(1);
+	return -1;
 }
 
-#define PROP_ERR(x)     if (!(x)) {             \
-                warn("proplib failure");        \
-                return;                         \
-        }
+#define PROP_ERR(x)     if (!(x)) {		\
+	gpt_warnx(gpt, "proplib failure");	\
+	return -1;				\
+}
 
-static void
-restore(int fd)
+static int
+restore(gpt_t gpt)
 {
 	gpt_uuid_t gpt_guid, uuid;
 	off_t firstdata, last, lastdata, gpe_start, gpe_end;
-	map_t *map;
+	map_t map;
 	struct mbr *mbr;
 	struct gpt_hdr *hdr;
 	struct gpt_ent ent;
@@ -89,20 +90,20 @@ restore(int fd)
 	const char *s;
 	void *secbuf;
 
-	last = mediasz / secsz - 1LL;
+	last = gpt->mediasz / gpt->secsz - 1LL;
 
-	if (map_find(MAP_TYPE_PRI_GPT_HDR) != NULL ||
-	    map_find(MAP_TYPE_SEC_GPT_HDR) != NULL) {
+	if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL ||
+	    map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) {
 		if (!force) {
-			warnx("%s: error: device contains a GPT", device_name);
-			return;
+			gpt_warnx(gpt, "Device contains a GPT");
+			return -1;
 		}
 	}
-	map = map_find(MAP_TYPE_MBR);
+	map = map_find(gpt, MAP_TYPE_MBR);
 	if (map != NULL) {
 		if (!force) {
-			warnx("%s: error: device contains a MBR", device_name);
-			return;
+			gpt_warnx(gpt, "Device contains an MBR");
+			return -1;
 		}
 		/* Nuke the MBR in our internal map. */
 		map->map_type = MAP_TYPE_UNUSED;
@@ -110,17 +111,16 @@ restore(int fd)
 
 	props = prop_dictionary_internalize_from_file("/dev/stdin");
 	if (props == NULL) {
-		warnx("error: unable to read/parse backup file");
-		return;
+		gpt_warnx(gpt, "Unable to read/parse backup file");
+		return -1;
 	}
 
 	propnum = prop_dictionary_get(props, "sector_size");
 	PROP_ERR(propnum);
-	if (!prop_number_equals_integer(propnum, secsz)) {
-		warnx("%s: error: sector size does not match backup",
-		    device_name);
+	if (!prop_number_equals_integer(propnum, gpt->secsz)) {
+		gpt_warnx(gpt, "Sector size does not match backup");
 		prop_object_release(props);
-		return;
+		return -1;
 	}
 
 	gpt_dict = prop_dictionary_get(props, "GPT_HDR");
@@ -129,25 +129,26 @@ restore(int fd)
 	propnum = prop_dictionary_get(gpt_dict, "revision");
 	PROP_ERR(propnum);
 	if (!prop_number_equals_unsigned_integer(propnum, 0x10000)) {
-		warnx("backup is not revision 1.0");
+		gpt_warnx(gpt, "backup is not revision 1.0");
 		prop_object_release(gpt_dict);
 		prop_object_release(props);
-		return;
+		return -1;
 	}
 
 	propnum = prop_dictionary_get(gpt_dict, "entries");
 	PROP_ERR(propnum);
 	entries = prop_number_integer_value(propnum);
-	gpt_size = entries * sizeof(struct gpt_ent) / secsz;
-	if (gpt_size * sizeof(struct gpt_ent) % secsz)
+	gpt_size = entries * sizeof(struct gpt_ent) / gpt->secsz;
+	if (gpt_size * sizeof(struct gpt_ent) % gpt->secsz)
 		gpt_size++;
 
 	propstr = prop_dictionary_get(gpt_dict, "guid");
 	PROP_ERR(propstr);
 	s = prop_string_cstring_nocopy(propstr);
 	if (gpt_uuid_parse(s, gpt_guid) != 0) {
-		warnx("%s: not able to convert to an UUID", s);
-		return;
+		gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+		// XXX: leak
+		return -1;
 	}
 	firstdata = gpt_size + 2;		/* PMBR and GPT header */
 	lastdata = last - gpt_size - 1;		/* alt. GPT table and header */
@@ -163,8 +164,8 @@ restore(int fd)
 		PROP_ERR(propstr);
 		s = prop_string_cstring_nocopy(propstr);
 		if (gpt_uuid_parse(s, uuid) != 0) {
-			warnx("%s: not able to convert to an UUID", s);
-			return;
+			gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+			return -1;
 		}
 		if (gpt_uuid_is_nil(uuid))
 			continue;
@@ -175,36 +176,36 @@ restore(int fd)
 		PROP_ERR(propnum);
 		gpe_end = prop_number_unsigned_integer_value(propnum);
 		if (gpe_start < firstdata || gpe_end > lastdata) {
-			warnx("%s: error: backup GPT doesn't fit", device_name);
-			return;
+			gpt_warnx(gpt, "Backup GPT doesn't fit");
+			return -1;
 		}
 	}
 	prop_object_iterator_release(propiter);
 
-	secbuf = calloc(gpt_size + 1, secsz);	/* GPT TABLE + GPT HEADER */
+	secbuf = calloc(gpt_size + 1, gpt->secsz);	/* GPT TABLE + GPT HEADER */
 	if (secbuf == NULL) {
-		warnx("not enough memory to create a sector buffer");
-		return;
+		gpt_warnx(gpt, "not enough memory to create a sector buffer");
+		return -1;
 	}
 
-	if (lseek(fd, 0LL, SEEK_SET) == -1) {
-		warnx("%s: error: can't seek to beginning", device_name);
-		return;
+	if (lseek(gpt->fd, 0LL, SEEK_SET) == -1) {
+		gpt_warnx(gpt, "Can't seek to beginning");
+		return -1;
 	}
 	for (i = 0; i < firstdata; i++) {
-		if (write(fd, secbuf, secsz) == -1) {
-			warnx("%s: error: can't write", device_name);
-			return;
+		if (write(gpt->fd, secbuf, gpt->secsz) == -1) {
+			gpt_warnx(gpt, "Error writing");
+			return -1;
 		}
 	}
-	if (lseek(fd, (lastdata + 1) * secsz, SEEK_SET) == -1) {
-		warnx("%s: error: can't seek to end", device_name);
-		return;
+	if (lseek(gpt->fd, (lastdata + 1) * gpt->secsz, SEEK_SET) == -1) {
+		gpt_warnx(gpt, "Can't seek to end");
+		return -1;
 	}
 	for (i = lastdata + 1; i <= last; i++) {
-		if (write(fd, secbuf, secsz) == -1) {
-			warnx("%s: error: can't write", device_name);
-			return;
+		if (write(gpt->fd, secbuf, gpt->secsz) == -1) {
+			gpt_warnx(gpt, "Error writing");
+			return -1;
 		}
 	}
 
@@ -287,10 +288,10 @@ restore(int fd)
 	}
 	prop_object_iterator_release(propiter);
 	mbr->mbr_sig = htole16(MBR_SIG);
-	if (lseek(fd, 0LL, SEEK_SET) == -1 ||
-	    write(fd, mbr, secsz) == -1) {
-		warnx("%s: error: unable to write MBR", device_name);
-		return;
+	if (lseek(gpt->fd, 0LL, SEEK_SET) == -1 ||
+	    write(gpt->fd, mbr, gpt->secsz) == -1) {
+		gpt_warnx(gpt, "Unable to write MBR");
+		return -1;
 	}
 	
 	propiter = prop_array_iterator(gpt_array);
@@ -301,15 +302,15 @@ restore(int fd)
 		PROP_ERR(propstr);
 		s = prop_string_cstring_nocopy(propstr);
 		if (gpt_uuid_parse(s, ent.ent_type) != 0) {
-			warnx("%s: not able to convert to an UUID", s);
-			return;
+			gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+			return -1;
 		}
 		propstr = prop_dictionary_get(gpt_dict, "guid");
 		PROP_ERR(propstr);
 		s = prop_string_cstring_nocopy(propstr);
 		if (gpt_uuid_parse(s, ent.ent_guid) != 0) {
-			warnx("%s: not able to convert to an UUID", s);
-			return;
+			gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+			return -1;
 		}
 		propnum = prop_dictionary_get(gpt_dict, "start");
 		PROP_ERR(propnum);
@@ -331,22 +332,24 @@ restore(int fd)
 		propnum = prop_dictionary_get(gpt_dict, "index");
 		PROP_ERR(propnum);
 		i = prop_number_integer_value(propnum);
-		memcpy((char *)secbuf + secsz + ((i - 1) * sizeof(ent)), &ent,
-		    sizeof(ent));
+		memcpy((char *)secbuf + gpt->secsz + ((i - 1) * sizeof(ent)),
+		    &ent, sizeof(ent));
 	}
 	prop_object_iterator_release(propiter);
-	if (lseek(fd, 2 * secsz, SEEK_SET) == -1 ||
-	    write(fd, (char *)secbuf + 1 * secsz, gpt_size * secsz) == -1) {
-		warnx("%s: error: unable to write primary GPT", device_name);
-		return;
-	}
-	if (lseek(fd, (lastdata + 1) * secsz, SEEK_SET) == -1 ||
-	    write(fd, (char *)secbuf + 1 * secsz, gpt_size * secsz) == -1) {
-		warnx("%s: error: unable to write secondary GPT", device_name);
-		return;
+	if (lseek(gpt->fd, 2 * gpt->secsz, SEEK_SET) == -1 ||
+	    write(gpt->fd, (char *)secbuf + 1 * gpt->secsz,
+	    gpt_size * gpt->secsz) == -1) {
+		gpt_warnx(gpt, "Unable to write primary GPT");
+		return -1;
+	}
+	if (lseek(gpt->fd, (lastdata + 1) * gpt->secsz, SEEK_SET) == -1 ||
+	    write(gpt->fd, (char *)secbuf + 1 * gpt->secsz,
+	    gpt_size * gpt->secsz) == -1) {
+		gpt_warnx(gpt, "Unable to write secondary GPT");
+		return -1;
 	}
 
-	memset(secbuf, 0, secsz);
+	memset(secbuf, 0, gpt->secsz);
 	hdr = (struct gpt_hdr *)secbuf;
 	memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
 	hdr->hdr_revision = htole32(GPT_HDR_REVISION);
@@ -359,13 +362,13 @@ restore(int fd)
 	hdr->hdr_lba_table = htole64(2);
 	hdr->hdr_entries = htole32(entries);
 	hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));
-	hdr->hdr_crc_table =
-	    htole32(crc32((char *)secbuf + 1 * secsz, gpt_size * secsz));
+	hdr->hdr_crc_table = htole32(crc32((char *)secbuf + 1 * gpt->secsz,
+	    gpt_size * gpt->secsz));
 	hdr->hdr_crc_self = htole32(crc32(hdr, GPT_HDR_SIZE));
-	if (lseek(fd, 1 * secsz, SEEK_SET) == -1 ||
-	    write(fd, hdr, secsz) == -1) {
-		warnx("%s: error: unable to write primary header", device_name);
-		return;
+	if (lseek(gpt->fd, 1 * gpt->secsz, SEEK_SET) == -1 ||
+	    write(gpt->fd, hdr, gpt->secsz) == -1) {
+		gpt_warnx(gpt, "Unable to write primary header");
+		return -1;
 	}
 
 	hdr->hdr_lba_self = htole64(last);
@@ -373,21 +376,20 @@ restore(int fd)
 	hdr->hdr_lba_table = htole64(lastdata + 1);
 	hdr->hdr_crc_self = 0;
 	hdr->hdr_crc_self = htole32(crc32(hdr, GPT_HDR_SIZE));
-	if (lseek(fd, last * secsz, SEEK_SET) == -1 ||
-	    write(fd, hdr, secsz) == -1) {
-		warnx("%s: error: unable to write secondary header",
-		    device_name);
-		return;
+	if (lseek(gpt->fd, last * gpt->secsz, SEEK_SET) == -1 ||
+	    write(gpt->fd, hdr, gpt->secsz) == -1) {
+		gpt_warnx(gpt, "Unable to write secondary header");
+		return -1;
 	}
 
 	prop_object_release(props);
-	return;
+	return 0;
 }
 
 int
-cmd_restore(int argc, char *argv[])
+cmd_restore(gpt_t gpt, int argc, char *argv[])
 {
-	int ch, fd;
+	int ch;
 
 	while ((ch = getopt(argc, argv, "F")) != -1) {
 		switch(ch) {
@@ -395,22 +397,12 @@ cmd_restore(int argc, char *argv[])
 			force = 1;
 			break;
 		default:
-			usage_restore();
+			return usage_restore();
 		}
 	}
 
-	if (argc == optind)
-		usage_restore();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		restore(fd);
-
-		gpt_close(fd);
-	}
+	if (argc != optind)
+		return usage_restore();
 
-	return (0);
+	return restore(gpt);
 }

Index: src/sbin/gpt/biosboot.c
diff -u src/sbin/gpt/biosboot.c:1.15 src/sbin/gpt/biosboot.c:1.16
--- src/sbin/gpt/biosboot.c:1.15	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/biosboot.c	Tue Dec  1 04:05:33 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: biosboot.c,v 1.15 2015/11/29 00:14:46 christos Exp $ */
+/*	$NetBSD: biosboot.c,v 1.16 2015/12/01 09:05:33 christos Exp $ */
 
 /*
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #ifdef __RCSID
-__RCSID("$NetBSD: biosboot.c,v 1.15 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: biosboot.c,v 1.16 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/stat.h>
@@ -60,6 +60,7 @@ __RCSID("$NetBSD: biosboot.c,v 1.15 2015
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 #define DEFAULT_BOOTDIR		"/usr/mdec"
 #define DEFAULT_BOOTCODE	"gptmbr.bin"
@@ -72,61 +73,65 @@ static unsigned int entry;
 static uint8_t *label;
 
 const char biosbootmsg[] = "biosboot [-c bootcode] [-i index] "
-	"[-L label] device ...";
+	"[-L label]";
 
-__dead static void
+static int
 usage_biosboot(void)
 {
 	fprintf(stderr, "usage: %s %s\n", getprogname(), biosbootmsg);
-	exit(1);
+	return -1;
 }
 
 static struct mbr*
-read_boot(void)
+read_boot(gpt_t gpt)
 {
 	int bfd, ret = 0;
 	struct mbr *buf;
 	struct stat st;
 
-	/* XXX how to do the following better? */
-	if (bootpath == NULL) {
+	buf = NULL;
+	bfd = -1;
+
+	if (bootpath == NULL)
 		bootpath = strdup(DEFAULT_BOOTDIR "/" DEFAULT_BOOTCODE);
-	} else {
-		if (strchr(bootpath, '/') == 0) {
-			char *p;
-			if ((p = strdup(bootpath)) == NULL)
-				err(1, "Malloc failed");
-			free(bootpath);
-			(void)asprintf(&bootpath, "%s/%s", DEFAULT_BOOTDIR, p);
-			free(p);
-		}
+	else if (*bootpath == '/')
+		bootpath = strdup(bootpath);
+	else {
+		if (asprintf(&bootpath, "%s/%s", DEFAULT_BOOTDIR, bootpath) < 0)
+			bootpath = NULL;
+	}
+
+	if (bootpath == NULL) {
+		gpt_warn(gpt, "Can't allocate memory for bootpath");
+		goto fail;
+	}
+
+	if ((buf = malloc((size_t)gpt->secsz)) == NULL) {
+		gpt_warn(gpt, "Can't allocate memory for sector");
+		goto fail;
 	}
-	if (bootpath == NULL)
-		err(1, "Malloc failed");
 
-	if ((buf = malloc((size_t)secsz)) == NULL)
-		err(1, "Malloc failed");
 
 	if ((bfd = open(bootpath, O_RDONLY)) < 0 || fstat(bfd, &st) == -1) {
-		warn("%s", bootpath);
+		gpt_warn(gpt, "Can't open `%s'", bootpath);
 		goto fail;
 	}
 
 	if (st.st_size != MBR_DSN_OFFSET) {
-		warnx("%s: the bootcode does not match expected size",
-			bootpath);
+		gpt_warnx(gpt, "The bootcode in `%s' does not match the"
+		    " expected size %u", bootpath, MBR_DSN_OFFSET);
 		goto fail;
 	}
 
 	if (read(bfd, buf, st.st_size) != st.st_size) {
-		warn("%s", bootpath);
+		gpt_warn(gpt, "Error reading from `%s'", bootpath);
 		goto fail;
 	}
 
 	ret++;
 
     fail:
-	if (bfd >= 0)
+	if (bfd != -1)
 		close(bfd);
 	if (ret == 0) {
 		free(buf);
@@ -135,45 +140,43 @@ read_boot(void)
 	return buf;
 }
 
-static void
-biosboot(int fd)
+static int
+set_bootable(gpt_t gpt, map_t map, map_t tbl, unsigned int i)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *mbrmap, *m;
+	unsigned int j;
+	struct gpt_hdr *hdr = map->map_data;
+	struct gpt_ent *ent;
+	unsigned int ne = le32toh(hdr->hdr_entries);
+
+	for (j = 0; j < ne; j++) {
+		ent = gpt_ent(map, tbl, j);
+		ent->ent_attr &= ~GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
+	}
+
+	ent = gpt_ent(map, tbl, i);
+	ent->ent_attr |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
+
+	return gpt_write_crc(gpt, map, tbl);
+}
+
+static int
+biosboot(gpt_t gpt)
+{
+	map_t mbrmap, m;
 	struct mbr *mbr, *bootcode;
-	struct gpt_hdr *hdr;
+	unsigned int i;
 	struct gpt_ent *ent;
-	unsigned int i, j;
 
 	/*
 	 * Parse and validate partition maps
 	 */
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
+	if (gpt_hdr(gpt) == NULL)
+		return -1;
 
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
-
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
-
-	mbrmap = map_find(MAP_TYPE_PMBR);
+	mbrmap = map_find(gpt, MAP_TYPE_PMBR);
 	if (mbrmap == NULL || mbrmap->map_start != 0) {
-		warnx("%s: error: no valid Protective MBR found", device_name);
-		return;
+		gpt_warnx(gpt, "No valid Protective MBR found");
+		return -1;
 	}
 
 	mbr = mbrmap->map_data;
@@ -181,9 +184,9 @@ biosboot(int fd)
 	/*
 	 * Update the boot code
 	 */
-	if ((bootcode = read_boot()) == NULL) {
-		warnx("error reading bootcode");
-		return;
+	if ((bootcode = read_boot(gpt)) == NULL) {
+		gpt_warnx(gpt, "Error reading bootcode");
+		return -1;
 	}
 	(void)memcpy(&mbr->mbr_code, &bootcode->mbr_code,
 		sizeof(mbr->mbr_code));
@@ -192,7 +195,7 @@ biosboot(int fd)
 	/*
 	 * Walk through the GPT and see where we can boot from
 	 */
-	for (m = map_first(); m != NULL; m = m->map_next) {
+	for (m = map_first(gpt); m != NULL; m = m->map_next) {
 		if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
 			continue;
 
@@ -214,69 +217,37 @@ biosboot(int fd)
 	}
 
 	if (m == NULL) {
-		warnx("error: no bootable partition");
-		return;
+		gpt_warnx(gpt, "No bootable partition");
+		return -1;
 	}
 
 	i = m->map_index - 1;
 
 
-	hdr = gpt->map_data;
-
-	for (j = 0; j < le32toh(hdr->hdr_entries); j++) {
-		ent = (void*)((char*)tbl->map_data + j * le32toh(hdr->hdr_entsz));
-		ent->ent_attr &= ~GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-	}
-
-	ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz));
-	ent->ent_attr |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-
-	hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, gpt);
-	gpt_write(fd, tbl);
-
-
-	hdr = tpg->map_data;
-
-	for (j = 0; j < le32toh(hdr->hdr_entries); j++) {
-		ent = (void*)((char*)lbt->map_data + j * le32toh(hdr->hdr_entsz));
-		ent->ent_attr &= ~GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-	}
-
-	ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
-	ent->ent_attr |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-
-	hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, lbt);
-	gpt_write(fd, tpg);
+	if (set_bootable(gpt, gpt->gpt, gpt->tbl, i) == -1)
+		return -1;
 
+	if (set_bootable(gpt, gpt->tpg, gpt->lbt, i) == -1)
+		return -1;
 
-	if (gpt_write(fd, mbrmap) == -1) {
-		warnx("error: cannot update Protective MBR");
-		return;
+	if (gpt_write(gpt, mbrmap) == -1) {
+		gpt_warnx(gpt, "Cannot update Protective MBR");
+		return -1;
 	}
 
-	printf("partition %d marked as bootable\n", i + 1);
+	gpt_msg(gpt, "Partition %d marked as bootable", i + 1);
+	return 0;
 }
 
 int
-cmd_biosboot(int argc, char *argv[])
+cmd_biosboot(gpt_t gpt, int argc, char *argv[])
 {
 #ifdef DIOCGWEDGEINFO
 	struct dkwedge_info dkw;
 #endif
-	struct stat sb;
-	char devpath[MAXPATHLEN];
 	char *dev, *p;
-	int ch, fd;
+	int ch;
+	gpt_t ngpt = gpt;
 
 	while ((ch = getopt(argc, argv, "c:i:L:")) != -1) {
 		switch(ch) {
@@ -299,51 +270,34 @@ cmd_biosboot(int argc, char *argv[])
 			label = (uint8_t *)strdup(optarg);
 			break;
 		default:
-			usage_biosboot();
+			return usage_biosboot();
 		}
 	}
 
-	if (argc == optind)
-		usage_biosboot();
+	if (argc != optind)
+		return usage_biosboot();
 
-	while (optind < argc) {
-		dev = argv[optind++];
-		start = 0;
-		size = 0;
-
-		/*
-		 * If a dk wedge was specified, loader should be
-		 * installed onto parent device
-		 */
-		if ((fd = opendisk(dev, O_RDONLY, devpath, sizeof(devpath), 0))
-				== -1)
-			goto next;
-		if (fstat(fd, &sb) == -1)
-			goto close;
+	start = 0;
+	size = 0;
 
 #ifdef DIOCGWEDGEINFO
-		if ((sb.st_mode & S_IFMT) != S_IFREG &&
-		    ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
-			if (entry > 0)
-				/* wedges and indexes are mutually exclusive */
-				usage_biosboot();
-			dev = dkw.dkw_parent;
-			start = dkw.dkw_offset;
-			size = dkw.dkw_size;
-		}
-#endif
-	close:
-		close(fd);
-
-		fd = gpt_open(dev, 0);
-	next:
-		if (fd == -1)
-			continue;
-
-		biosboot(fd);
-
-		gpt_close(fd);
+	if ((gpt->sb.st_mode & S_IFMT) != S_IFREG &&
+	    ioctl(gpt->fd, DIOCGWEDGEINFO, &dkw) != -1) {
+		if (entry > 0)
+			/* wedges and indexes are mutually exclusive */
+			return usage_biosboot();
+		dev = dkw.dkw_parent;
+		start = dkw.dkw_offset;
+		size = dkw.dkw_size;
+		ngpt = gpt_open(dev, gpt->flags, gpt->verbose,
+		    gpt->mediasz, gpt->secsz);
+		if (ngpt == NULL)
+			return -1;
 	}
+#endif
+	biosboot(ngpt);
+	if (ngpt != gpt)
+		gpt_close(ngpt);
 
-	return (0);
+	return 0;
 }

Index: src/sbin/gpt/create.c
diff -u src/sbin/gpt/create.c:1.13 src/sbin/gpt/create.c:1.14
--- src/sbin/gpt/create.c:1.13	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/create.c	Tue Dec  1 04:05:33 2015
@@ -33,10 +33,12 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/create.c,v 1.11 2005/08/31 01:47:19 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: create.c,v 1.13 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: create.c,v 1.14 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
 #include <sys/bootblock.h>
 
 #include <err.h>
@@ -48,47 +50,47 @@ __RCSID("$NetBSD: create.c,v 1.13 2015/1
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static int force;
+static u_int parts;
 static int primary_only;
 
-const char createmsg[] = "create [-fp] device ...";
+const char createmsg[] = "create [-fP] [-p <partitions>]";
 
-__dead static void
+static int
 usage_create(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), createmsg);
-	exit(1);
+	return -1;
 }
 
-static void
-create(int fd)
+static int
+create(gpt_t gpt)
 {
 	off_t blocks, last;
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *map;
+	map_t map;
 	struct mbr *mbr;
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	unsigned int i;
+	void *p;
 
-	last = mediasz / secsz - 1LL;
+	last = gpt->mediasz / gpt->secsz - 1LL;
 
-	if (map_find(MAP_TYPE_PRI_GPT_HDR) != NULL ||
-	    map_find(MAP_TYPE_SEC_GPT_HDR) != NULL) {
-		warnx("%s: error: device already contains a GPT", device_name);
-		return;
+	if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL ||
+	    map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) {
+		gpt_warnx(gpt, "Device already contains a GPT");
+		return -1;
 	}
-	map = map_find(MAP_TYPE_MBR);
+	map = map_find(gpt, MAP_TYPE_MBR);
 	if (map != NULL) {
 		if (!force) {
-			warnx("%s: error: device contains a MBR", device_name);
-			return;
+			gpt_warnx(gpt, "Device contains a MBR");
+			return -1;
 		}
-
 		/* Nuke the MBR in our internal map. */
 		map->map_type = MAP_TYPE_UNUSED;
 	}
@@ -96,44 +98,36 @@ create(int fd)
 	/*
 	 * Create PMBR.
 	 */
-	if (map_find(MAP_TYPE_PMBR) == NULL) {
-		if (map_free(0LL, 1LL) == 0) {
-			warnx("%s: error: no room for the PMBR", device_name);
-			return;
+	if (map_find(gpt, MAP_TYPE_PMBR) == NULL) {
+		if (map_free(gpt, 0LL, 1LL) == 0) {
+			gpt_warnx(gpt, "No room for the PMBR");
+			return -1;
+		}
+		mbr = gpt_read(gpt, 0LL, 1);
+		if (mbr == NULL) {
+			gpt_warnx(gpt, "Error reading MBR");
+			return -1;
 		}
-		mbr = gpt_read(fd, 0LL, 1);
 		memset(mbr, 0, sizeof(*mbr));
 		mbr->mbr_sig = htole16(MBR_SIG);
-		mbr->mbr_part[0].part_shd = 0x00;
-		mbr->mbr_part[0].part_ssect = 0x02;
-		mbr->mbr_part[0].part_scyl = 0x00;
-		mbr->mbr_part[0].part_typ = MBR_PTYPE_PMBR;
-		mbr->mbr_part[0].part_ehd = 0xfe;
-		mbr->mbr_part[0].part_esect = 0xff;
-		mbr->mbr_part[0].part_ecyl = 0xff;
-		mbr->mbr_part[0].part_start_lo = htole16(1);
-		if (last > 0xffffffff) {
-			mbr->mbr_part[0].part_size_lo = htole16(0xffff);
-			mbr->mbr_part[0].part_size_hi = htole16(0xffff);
-		} else {
-			mbr->mbr_part[0].part_size_lo = htole16(last);
-			mbr->mbr_part[0].part_size_hi = htole16(last >> 16);
-		}
-		map = map_add(0LL, 1LL, MAP_TYPE_PMBR, mbr);
-		gpt_write(fd, map);
+		gpt_create_pmbr_part(mbr->mbr_part, last);
+
+		map = map_add(gpt, 0LL, 1LL, MAP_TYPE_PMBR, mbr);
+		gpt_write(gpt, map);
 	}
 
 	/* Get the amount of free space after the MBR */
-	blocks = map_free(1LL, 0LL);
+	blocks = map_free(gpt, 1LL, 0LL);
 	if (blocks == 0LL) {
-		warnx("%s: error: no room for the GPT header", device_name);
-		return;
+		gpt_warnx(gpt, "No room for the GPT header");
+		return -1;
 	}
 
 	/* Don't create more than parts entries. */
-	if ((uint64_t)(blocks - 1) * secsz > parts * sizeof(struct gpt_ent)) {
-		blocks = (parts * sizeof(struct gpt_ent)) / secsz;
-		if ((parts * sizeof(struct gpt_ent)) % secsz)
+	if ((uint64_t)(blocks - 1) * gpt->secsz >
+	    parts * sizeof(struct gpt_ent)) {
+		blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz;
+		if ((parts * sizeof(struct gpt_ent)) % gpt->secsz)
 			blocks++;
 		blocks++;		/* Don't forget the header itself */
 	}
@@ -146,103 +140,111 @@ create(int fd)
 	 * Get the amount of free space at the end of the device and
 	 * calculate the size for the GPT structures.
 	 */
-	map = map_last();
+	map = map_last(gpt);
 	if (map->map_type != MAP_TYPE_UNUSED) {
-		warnx("%s: error: no room for the backup header", device_name);
-		return;
+		gpt_warnx(gpt, "No room for the backup header");
+		return -1;
 	}
 
 	if (map->map_size < blocks)
 		blocks = map->map_size;
 	if (blocks == 1LL) {
-		warnx("%s: error: no room for the GPT table", device_name);
-		return;
+		gpt_warnx(gpt, "No room for the GPT table");
+		return -1;
+	}
+
+	if ((p = calloc(1, gpt->secsz)) == NULL) {
+		gpt_warnx(gpt, "Can't allocate the GPT");
+		return -1;
+	}
+	if ((gpt->gpt = map_add(gpt, 1LL, 1LL,
+	    MAP_TYPE_PRI_GPT_HDR, p)) == NULL) {
+		free(p);
+		gpt_warnx(gpt, "Can't add the GPT");
+		return -1;
 	}
 
 	blocks--;		/* Number of blocks in the GPT table. */
-	gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR, calloc(1, secsz));
-	tbl = map_add(2LL, blocks, MAP_TYPE_PRI_GPT_TBL,
-	    calloc(blocks, secsz));
-	if (gpt == NULL || tbl == NULL)
-		return;
+	if ((p = calloc(blocks, gpt->secsz)) == NULL) {
+		gpt_warnx(gpt, "Can't allocate the GPT table");
+		return -1;
+	}
+	if ((gpt->tbl = map_add(gpt, 2LL, blocks,
+	    MAP_TYPE_PRI_GPT_TBL, p)) == NULL) {
+		free(p);
+		gpt_warnx(gpt, "Can't add the GPT table");
+		return -1;
+	}
 
-	hdr = gpt->map_data;
+	hdr = gpt->gpt->map_data;
 	memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
 	hdr->hdr_revision = htole32(GPT_HDR_REVISION);
 	hdr->hdr_size = htole32(GPT_HDR_SIZE);
-	hdr->hdr_lba_self = htole64(gpt->map_start);
+	hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
 	hdr->hdr_lba_alt = htole64(last);
-	hdr->hdr_lba_start = htole64(tbl->map_start + blocks);
+	hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks);
 	hdr->hdr_lba_end = htole64(last - blocks - 1LL);
 	gpt_uuid_generate(hdr->hdr_guid);
-	hdr->hdr_lba_table = htole64(tbl->map_start);
-	hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent));
+	hdr->hdr_lba_table = htole64(gpt->tbl->map_start);
+	hdr->hdr_entries = htole32((blocks * gpt->secsz) /
+	    sizeof(struct gpt_ent));
 	if (le32toh(hdr->hdr_entries) > parts)
 		hdr->hdr_entries = htole32(parts);
 	hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));
 
-	ent = tbl->map_data;
+	ent = gpt->tbl->map_data;
 	for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
 		gpt_uuid_generate(ent[i].ent_guid);
 	}
 
-	hdr->hdr_crc_table = htole32(crc32(ent, le32toh(hdr->hdr_entries) *
-	    le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, gpt);
-	gpt_write(fd, tbl);
+	if (gpt_write_primary(gpt) == -1)
+		return -1;
 
 	/*
 	 * Create backup GPT if the user didn't suppress it.
 	 */
 	if (!primary_only) {
-		tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR,
-		    calloc(1, secsz));
-		lbt = map_add(last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,
-		    tbl->map_data);
-		memcpy(tpg->map_data, gpt->map_data, secsz);
-		hdr = tpg->map_data;
-		hdr->hdr_lba_self = htole64(tpg->map_start);
-		hdr->hdr_lba_alt = htole64(gpt->map_start);
-		hdr->hdr_lba_table = htole64(lbt->map_start);
-		hdr->hdr_crc_self = 0;		/* Don't ever forget this! */
-		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-		gpt_write(fd, lbt);
-		gpt_write(fd, tpg);
+		// XXX: error checks 
+		gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR,
+		    calloc(1, gpt->secsz));
+		gpt->lbt = map_add(gpt, last - blocks, blocks,
+		    MAP_TYPE_SEC_GPT_TBL, gpt->tbl->map_data);
+		memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
+		hdr = gpt->tpg->map_data;
+		hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+		hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+		hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
+		if (gpt_write_backup(gpt) == -1)
+			return -1;
 	}
+	return 0;
 }
 
 int
-cmd_create(int argc, char *argv[])
+cmd_create(gpt_t gpt, int argc, char *argv[])
 {
-	int ch, fd;
+	int ch;
 
-	while ((ch = getopt(argc, argv, "fp")) != -1) {
+	parts = 128;
+
+	while ((ch = getopt(argc, argv, "fPp:")) != -1) {
 		switch(ch) {
 		case 'f':
 			force = 1;
 			break;
-		case 'p':
+		case 'P':
 			primary_only = 1;
 			break;
+		case 'p':
+			parts = atoi(optarg);
+			break;
 		default:
-			usage_create();
+			return usage_create();
 		}
 	}
 
-	if (argc == optind)
-		usage_create();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], force);
-		if (fd == -1)
-			continue;
-
-		create(fd);
-
-		gpt_close(fd);
-	}
+	if (argc != optind)
+		return usage_create();
 
-	return (0);
+	return create(gpt);
 }

Index: src/sbin/gpt/destroy.c
diff -u src/sbin/gpt/destroy.c:1.7 src/sbin/gpt/destroy.c:1.8
--- src/sbin/gpt/destroy.c:1.7	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/destroy.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/destroy.c,v 1.6 2005/08/31 01:47:19 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: destroy.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: destroy.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,54 +47,63 @@ __RCSID("$NetBSD: destroy.c,v 1.7 2015/1
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static int recoverable;
 static int force;
 
-const char destroymsg[] = "destroy [-rf] device ...";
+const char destroymsg[] = "destroy [-rf]";
 
-__dead static void
+static int
 usage_destroy(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), destroymsg);
-	exit(1);
+	return -1;
 }
 
-static void
-destroy(int fd)
+static int
+destroy(gpt_t gpt)
 {
-	map_t *pri_hdr, *sec_hdr;
+	map_t pri_hdr, sec_hdr;
 
-	pri_hdr = map_find(MAP_TYPE_PRI_GPT_HDR);
-	sec_hdr = map_find(MAP_TYPE_SEC_GPT_HDR);
+	pri_hdr = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+	sec_hdr = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
 
 	if (pri_hdr == NULL && sec_hdr == NULL) {
-		warnx("%s: error: device doesn't contain a GPT", device_name);
-		return;
+		gpt_warnx(gpt, "Device doesn't contain a GPT");
+		return -1;
 	}
 
 	if (recoverable && sec_hdr == NULL) {
-		warnx("%s: error: recoverability not possible", device_name);
-		return;
+		gpt_warnx(gpt, "Recoverability not possible");
+		return -1;
 	}
 
 	if (pri_hdr != NULL) {
-		memset(pri_hdr->map_data, 0, secsz);
-		gpt_write(fd, pri_hdr);
+		memset(pri_hdr->map_data, 0, gpt->secsz);
+		if (gpt_write(gpt, pri_hdr) == -1) {
+			gpt_warnx(gpt, "Error writing primary header");
+			return -1;
+		}
 	}
 
 	if (!recoverable && sec_hdr != NULL) {
-		memset(sec_hdr->map_data, 0, secsz);
-		gpt_write(fd, sec_hdr);
+		memset(sec_hdr->map_data, 0, gpt->secsz);
+		if (gpt_write(gpt, sec_hdr) == -1) {
+			gpt_warnx(gpt, "Error writing backup header");
+			return -1;
+		}
 	}
+
+	return 0;
 }
 
 int
-cmd_destroy(int argc, char *argv[])
+cmd_destroy(gpt_t gpt, int argc, char *argv[])
 {
-	int ch, fd;
+	int ch;
 
 	while ((ch = getopt(argc, argv, "fr")) != -1) {
 		switch(ch) {
@@ -105,22 +114,12 @@ cmd_destroy(int argc, char *argv[])
 			recoverable = 1;
 			break;
 		default:
-			usage_destroy();
+			return usage_destroy();
 		}
 	}
 
-	if (argc == optind)
-		usage_destroy();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], force);
-		if (fd == -1)
-			continue;
-
-		destroy(fd);
-
-		gpt_close(fd);
-	}
+	if (argc != optind)
+		return usage_destroy();
 
-	return (0);
+	return destroy(gpt);
 }
Index: src/sbin/gpt/recover.c
diff -u src/sbin/gpt/recover.c:1.7 src/sbin/gpt/recover.c:1.8
--- src/sbin/gpt/recover.c:1.7	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/recover.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/recover.c,v 1.8 2005/08/31 01:47:19 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: recover.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: recover.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,125 +47,130 @@ __RCSID("$NetBSD: recover.c,v 1.7 2015/1
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static int recoverable;
 
-const char recovermsg[] = "recover device ...";
+const char recovermsg[] = "recover";
 
-__dead static void
+static int
 usage_recover(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), recovermsg);
-	exit(1);
+	return -1;
 }
 
-static void
-recover(int fd)
+static int
+recover(gpt_t gpt)
 {
 	uint64_t last;
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
 	struct gpt_hdr *hdr;
 
-	if (map_find(MAP_TYPE_MBR) != NULL) {
-		warnx("%s: error: device contains a MBR", device_name);
-		return;
-	}
-
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-
-	if (gpt == NULL && tpg == NULL) {
-		warnx("%s: no primary or secondary GPT headers, can't recover",
-		    device_name);
-		return;
-	}
-	if (tbl == NULL && lbt == NULL) {
-		warnx("%s: no primary or secondary GPT tables, can't recover",
-		    device_name);
-		return;
-	}
-
-	last = mediasz / secsz - 1LL;
-
-	if (gpt != NULL &&
-	    ((struct gpt_hdr *)(gpt->map_data))->hdr_lba_alt != last) {
-		warnx("%s: media size has changed, please use 'gpt resizedisk'",
-		   device_name);
-		return;
-	}
-
-	if (tbl != NULL && lbt == NULL) {
-		lbt = map_add(last - tbl->map_size, tbl->map_size,
-		    MAP_TYPE_SEC_GPT_TBL, tbl->map_data);
-		if (lbt == NULL) {
-			warnx("%s: adding secondary GPT table failed",
-			    device_name);
-			return;
-		}
-		gpt_write(fd, lbt);
-		warnx("%s: recovered secondary GPT table from primary",
-		    device_name);
-	} else if (tbl == NULL && lbt != NULL) {
-		tbl = map_add(2LL, lbt->map_size, MAP_TYPE_PRI_GPT_TBL,
-		    lbt->map_data);
-		if (tbl == NULL) {
-			warnx("%s: adding primary GPT table failed",
-			    device_name);
-			return;
-		}
-		gpt_write(fd, tbl);
-		warnx("%s: recovered primary GPT table from secondary",
-		    device_name);
-	}
-
-	if (gpt != NULL && tpg == NULL) {
-		tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR,
-		    calloc(1, secsz));
-		if (tpg == NULL) {
-			warnx("%s: adding secondary GPT header failed",
-			    device_name);
-			return;
-		}
-		memcpy(tpg->map_data, gpt->map_data, secsz);
-		hdr = tpg->map_data;
-		hdr->hdr_lba_self = htole64(tpg->map_start);
-		hdr->hdr_lba_alt = htole64(gpt->map_start);
-		hdr->hdr_lba_table = htole64(lbt->map_start);
+	if (map_find(gpt, MAP_TYPE_MBR) != NULL) {
+		gpt_warnx(gpt, "Device contains an MBR");
+		return -1;
+	}
+
+	gpt->gpt = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+	gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+	gpt->tbl = map_find(gpt, MAP_TYPE_PRI_GPT_TBL);
+	gpt->lbt = map_find(gpt, MAP_TYPE_SEC_GPT_TBL);
+
+	if (gpt->gpt == NULL && gpt->tpg == NULL) {
+		gpt_warnx(gpt, "No primary or secondary GPT headers, "
+		    "can't recover");
+		return -1;
+	}
+	if (gpt->tbl == NULL && gpt->lbt == NULL) {
+		gpt_warnx(gpt, "No primary or secondary GPT tables, "
+		    "can't recover");
+		return -1;
+	}
+
+	last = gpt->mediasz / gpt->secsz - 1LL;
+
+	if (gpt->gpt != NULL &&
+	    ((struct gpt_hdr *)(gpt->gpt->map_data))->hdr_lba_alt != last) {
+		gpt_warnx(gpt, "Media size has changed, please use "
+		   "'gpt resizedisk'");
+		return -1;
+	}
+
+	if (gpt->tbl != NULL && gpt->lbt == NULL) {
+		gpt->lbt = map_add(gpt, last - gpt->tbl->map_size,
+		    gpt->tbl->map_size, MAP_TYPE_SEC_GPT_TBL,
+		    gpt->tbl->map_data);
+		if (gpt->lbt == NULL) {
+			gpt_warnx(gpt, "Adding secondary GPT table failed");
+			return -1;
+		}
+		if (gpt_write(gpt, gpt->lbt) == -1) {
+			gpt_warnx(gpt, "Writing secondary GPT table failed");
+			return -1;
+		}
+		gpt_msg(gpt, "Recovered secondary GPT table from primary");
+	} else if (gpt->tbl == NULL && gpt->lbt != NULL) {
+		gpt->tbl = map_add(gpt, 2LL, gpt->lbt->map_size,
+		    MAP_TYPE_PRI_GPT_TBL, gpt->lbt->map_data);
+		if (gpt->tbl == NULL) {
+			gpt_warnx(gpt, "Adding primary GPT table failed");
+			return -1;
+		}
+		if (gpt_write(gpt, gpt->tbl) == -1) {
+			gpt_warnx(gpt, "Writing primary GPT table failed");
+			return -1;
+		}
+		gpt_msg(gpt, "Recovered primary GPT table from secondary");
+	}
+
+	if (gpt->gpt != NULL && gpt->tpg == NULL) {
+		gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR,
+		    calloc(1, gpt->secsz));
+		if (gpt->tpg == NULL) {
+			gpt_warnx(gpt, "Adding secondary GPT header failed");
+			return -1;
+		}
+		memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
+		hdr = gpt->tpg->map_data;
+		hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+		hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+		hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
 		hdr->hdr_crc_self = 0;
 		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-		gpt_write(fd, tpg);
-		warnx("%s: recovered secondary GPT header from primary",
-		    device_name);
-	} else if (gpt == NULL && tpg != NULL) {
-		gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
-		    calloc(1, secsz));
-		if (gpt == NULL) {
-			warnx("%s: adding primary GPT header failed",
-			    device_name);
-			return;
-		}
-		memcpy(gpt->map_data, tpg->map_data, secsz);
-		hdr = gpt->map_data;
-		hdr->hdr_lba_self = htole64(gpt->map_start);
-		hdr->hdr_lba_alt = htole64(tpg->map_start);
-		hdr->hdr_lba_table = htole64(tbl->map_start);
+		if (gpt_write(gpt, gpt->tpg) == -1) {
+			gpt_warnx(gpt, "Writing secondary GPT header failed");
+			return -1;
+		}
+		gpt_msg(gpt, "Recovered secondary GPT header from primary");
+	} else if (gpt->gpt == NULL && gpt->tpg != NULL) {
+		gpt->gpt = map_add(gpt, 1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
+		    calloc(1, gpt->secsz));
+		if (gpt->gpt == NULL) {
+			gpt_warnx(gpt, "Adding primary GPT header failed");
+			return -1;
+		}
+		memcpy(gpt->gpt->map_data, gpt->tpg->map_data, gpt->secsz);
+		hdr = gpt->gpt->map_data;
+		hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
+		hdr->hdr_lba_alt = htole64(gpt->tpg->map_start);
+		hdr->hdr_lba_table = htole64(gpt->tbl->map_start);
 		hdr->hdr_crc_self = 0;
 		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-		gpt_write(fd, gpt);
-		warnx("%s: recovered primary GPT header from secondary",
-		    device_name);
+		if (gpt_write(gpt, gpt->gpt) == -1) {
+			gpt_warnx(gpt, "Writing primary GPT header failed");
+			return -1;
+		}
+		gpt_msg(gpt, "Recovered primary GPT header from secondary");
 	}
+	return 0;
 }
 
 int
-cmd_recover(int argc, char *argv[])
+cmd_recover(gpt_t gpt, int argc, char *argv[])
 {
-	int ch, fd;
+	int ch;
 
 	while ((ch = getopt(argc, argv, "r")) != -1) {
 		switch(ch) {
@@ -173,22 +178,12 @@ cmd_recover(int argc, char *argv[])
 			recoverable = 1;
 			break;
 		default:
-			usage_recover();
+			return usage_recover();
 		}
 	}
 
-	if (argc == optind)
+	if (argc != optind)
 		usage_recover();
 
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		recover(fd);
-
-		gpt_close(fd);
-	}
-
-	return (0);
+	return recover(gpt);
 }
Index: src/sbin/gpt/resizedisk.c
diff -u src/sbin/gpt/resizedisk.c:1.7 src/sbin/gpt/resizedisk.c:1.8
--- src/sbin/gpt/resizedisk.c:1.7	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/resizedisk.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: resizedisk.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: resizedisk.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/bootblock.h>
@@ -48,18 +48,19 @@ __RCSID("$NetBSD: resizedisk.c,v 1.7 201
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
-static uint64_t sector, size;
+static off_t sector, size;
 
-const char resizediskmsg[] = "resizedisk [-s size] device ...";
+const char resizediskmsg[] = "resizedisk [-s size]";
 
-__dead static void
+static int
 usage_resizedisk(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), resizediskmsg);
-	exit(1);
+	return -1;
 }
 
 /*
@@ -73,84 +74,78 @@ usage_resizedisk(void)
  *   - relocate or create new secondary
  * - when shrinking, verify that table fits
  */
-static void
-resizedisk(int fd)
+static int 
+resizedisk(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *mbrmap;
+	map_t mbrmap;
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	struct mbr *mbr;
-	uint64_t last, oldloc, newloc, lastdata, gpt_size;
+	off_t last, oldloc, newloc, lastdata, gpt_size;
 	int i;
 	
-	last = mediasz / secsz - 1;
+	last = gpt->mediasz / gpt->secsz - 1;
 	lastdata = 0;
 	newloc = 0;
 
 	if (sector > last) {
-		warnx("%s: specified size is larger then the disk",
-		    device_name);
-		return;
+		gpt_warnx(gpt, "specified size is larger then the disk");
+		return -1;
 	}
 
-        mbrmap = map_find(MAP_TYPE_PMBR);
+        mbrmap = map_find(gpt, MAP_TYPE_PMBR);
         if (mbrmap == NULL || mbrmap->map_start != 0) {
-                warnx("%s: error: no valid Protective MBR found", device_name);
-                return;
+                gpt_warnx(gpt, "No valid PMBR found");
+                return -1;
         }
         mbr = mbrmap->map_data;
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
+	gpt->gpt = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
 	ent = NULL;
 	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
+		gpt_warnx(gpt, "No primary GPT header; run create or recover");
+		return -1;
 	}
-	hdr = gpt->map_data;
+	hdr = gpt->gpt->map_data;
 	oldloc = le64toh(hdr->hdr_lba_alt);
 
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL)
-		if (gpt_gpt(fd, oldloc, 1))
-			tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
+	gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+	if (gpt->tpg == NULL)
+		if (gpt_gpt(gpt, oldloc, 1))
+			gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+
+	gpt->tbl = map_find(gpt, MAP_TYPE_PRI_GPT_TBL);
+	if (gpt->tbl == NULL) {
+		gpt_warnx(gpt, "Run recover");
+		return -1;
 	}
 
-	gpt_size = tbl->map_size;
+	gpt_size = gpt->tbl->map_size;
 	if (sector == oldloc) {
-		warnx("%s: device is already the specified size", device_name);
-		return;
+		gpt_warnx(gpt, "Device is already the specified size");
+		return 0;
 	}
 	if (sector == 0 && last == oldloc) {
-		warnx("%s: device hasn't changed size", device_name);
-		return;
+		gpt_warnx(gpt, "Device hasn't changed size");
+		return 0;
 	}
 
-	for (ent = tbl->map_data; ent <
-	    (struct gpt_ent *)((char *)tbl->map_data +
+	for (ent = gpt->tbl->map_data; ent <
+	    (struct gpt_ent *)((char *)gpt->tbl->map_data +
 	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)); ent++) {
 		if (!gpt_uuid_is_nil(ent->ent_type) &&
-		    (le64toh(ent->ent_lba_end) > lastdata)) {
+		    ((off_t)le64toh(ent->ent_lba_end) > lastdata)) {
 			lastdata = le64toh(ent->ent_lba_end);
 		}
 	}
 	if (sector - gpt_size <= lastdata) {
-		warnx("%s: not enough space at %" PRIu64
-		    " for secondary GPT table", device_name, sector);
-		return;
+		gpt_warnx(gpt, "Not enough space at %" PRIu64
+		    " for secondary GPT table", sector);
+		return -1;
 	}
 	if (last - gpt_size <= lastdata) {
-		warnx("%s: not enough space for new secondary GPT table",
-		    device_name);
-		return;
+		gpt_warnx(gpt, "Not enough space for new secondary GPT table");
+		return -1;
 	}
 
 	if (sector > oldloc)
@@ -160,55 +155,51 @@ resizedisk(int fd)
 	if (sector == 0 && last > oldloc)
 		newloc = last;
 	if (newloc > 0) {
-		if (tpg == NULL) {
-			warnx("%s: error: no secondary GPT header; run recover",
-			    device_name);
-			return;
+		if (gpt->tpg == NULL) {
+			gpt_warnx(gpt, "No secondary GPT header; run recover");
+			return -1;
 		}
-		if (lbt == NULL) {
-			warnx("%s: error: run recover -- trust me",
-			    device_name);
-			return;
+		if (gpt->lbt == NULL) {
+			gpt_warnx(gpt, "Run recover");
+			return -1;
 		}
-		tpg->map_start = newloc;
-		lbt->map_start = newloc - gpt_size;
+		gpt->tpg->map_start = newloc;
+		gpt->lbt->map_start = newloc - gpt_size;
 	} else {
 		if (sector > 0)
 			newloc = sector;
 		else
 			newloc = last;
-		tpg = map_add(newloc, 1LL, MAP_TYPE_SEC_GPT_HDR,
-		    calloc(1, secsz));
-		lbt = map_add(newloc - gpt_size, gpt_size, MAP_TYPE_SEC_GPT_TBL,
-		    tbl->map_data);
-		memcpy(tpg->map_data, gpt->map_data, secsz);
+		gpt->tpg = map_add(gpt, newloc, 1LL, MAP_TYPE_SEC_GPT_HDR,
+		    calloc(1, gpt->secsz));
+		gpt->lbt = map_add(gpt, newloc - gpt_size, gpt_size,
+		    MAP_TYPE_SEC_GPT_TBL, gpt->tbl->map_data);
+		memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
 	}
 
-	hdr = gpt->map_data;
-	hdr->hdr_lba_alt = tpg->map_start;
+	hdr = gpt->gpt->map_data;
+	hdr->hdr_lba_alt = gpt->tpg->map_start;
 	hdr->hdr_crc_self = 0;
-	hdr->hdr_lba_end = htole64(lbt->map_start - 1);
+	hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1);
 	hdr->hdr_crc_self =
-	    htole32(crc32(gpt->map_data, GPT_HDR_SIZE));
-	gpt_write(fd, gpt);
+	    htole32(crc32(gpt->gpt->map_data, GPT_HDR_SIZE));
+	gpt_write(gpt, gpt->gpt);
 
-	hdr = tpg->map_data;
-	hdr->hdr_lba_self = htole64(tpg->map_start);
-	hdr->hdr_lba_alt = htole64(gpt->map_start);
-	hdr->hdr_lba_end = htole64(lbt->map_start - 1);
-	hdr->hdr_lba_table = htole64(lbt->map_start);
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self =
-	    htole32(crc32(tpg->map_data, GPT_HDR_SIZE));
-	gpt_write(fd, lbt);
-	gpt_write(fd, tpg);
+	hdr = gpt->tpg->map_data;
+	hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+	hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+	hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1);
+	hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
+
+	if (gpt_write_backup(gpt) == -1)
+		return -1;
 
 	for (i = 0; i < 4; i++)
 		if (mbr->mbr_part[0].part_typ == MBR_PTYPE_PMBR)
 			break;
 	if (i == 4) {
-		warnx("%s: no valid PMBR partition found", device_name);
-		return;
+		gpt_warnx(gpt, "No valid PMBR partition found");
+		return -1;
 	}
 	if (last > 0xffffffff) {
 		mbr->mbr_part[0].part_size_lo = htole16(0xffff);
@@ -217,33 +208,36 @@ resizedisk(int fd)
 		mbr->mbr_part[0].part_size_lo = htole16(last);
 		mbr->mbr_part[0].part_size_hi = htole16(last >> 16);
 	}
-	gpt_write(fd, mbrmap);
+	if (gpt_write(gpt, mbrmap) == -1) {
+		gpt_warnx(gpt, "Error writing PMBR");
+		return -1;
+	}
 
-	return;
+	return 0;
 }
 
 int
-cmd_resizedisk(int argc, char *argv[])
+cmd_resizedisk(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 	int64_t human_num;
 
 	while ((ch = getopt(argc, argv, "s:")) != -1) {
 		switch(ch) {
 		case 's':
 			if (sector > 0 || size > 0)
-				usage_resizedisk();
+				return usage_resizedisk();
 			sector = strtoll(optarg, &p, 10);
 			if (sector < 1)
-				usage_resizedisk();
+				return usage_resizedisk();
 			if (*p == '\0')
 				break;
 			if (*p == 's' || *p == 'S') {
 				if (*(p + 1) == '\0')
 					break;
 				else
-					usage_resizedisk();
+					return usage_resizedisk();
 			}
 			if (*p == 'b' || *p == 'B') {
 				if (*(p + 1) == '\0') {
@@ -251,40 +245,23 @@ cmd_resizedisk(int argc, char *argv[])
 					sector = 0;
 					break;
 				} else
-					usage_resizedisk();
+					return usage_resizedisk();
 			}
 			if (dehumanize_number(optarg, &human_num) < 0)
-				usage_resizedisk();
+				return usage_resizedisk();
 			size = human_num;
 			sector = 0;
 			break;
 		default:
-			usage_resizedisk();
+			return usage_resizedisk();
 		}
 	}
 
-	if (argc == optind)
-		usage_resizedisk();
+	if (argc != optind)
+		return usage_resizedisk();
 
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		if (size % secsz != 0) {
-			warnx("Size in bytes must be a multiple of sector "
-			      "size;");
-			warnx("the sector size for %s is %d bytes.",
-			    device_name, secsz);
-			continue;
-		}
-		if (size > 0)
-			sector = size / secsz - 1;
-
-		resizedisk(fd);
+	if ((sector = gpt_check(gpt, 0, size)) == -1)
+		return -1;
 
-		gpt_close(fd);
-	}
-
-	return 0;
+	return resizedisk(gpt);
 }
Index: src/sbin/gpt/type.c
diff -u src/sbin/gpt/type.c:1.7 src/sbin/gpt/type.c:1.8
--- src/sbin/gpt/type.c:1.7	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/type.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: type.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: type.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,6 +47,7 @@ __RCSID("$NetBSD: type.c,v 1.7 2015/11/2
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static int all;
 static gpt_uuid_t type, newtype;
@@ -54,12 +55,12 @@ static off_t block, size;
 static unsigned int entry;
 static uint8_t *label;
 
-const char typemsg1[] = "type -a -T newtype device ...";
+const char typemsg1[] = "type -a -T newtype";
 const char typemsg2[] = "type [-b blocknr] [-i index] [-L label] "
 	"[-s sectors] [-t type]";
-const char typemsg3[] = "     -T newtype device ...";
+const char typemsg3[] = "     -T newtype";
 
-__dead static void
+static int
 usage_type(void)
 {
 
@@ -68,42 +69,21 @@ usage_type(void)
             "       %s %s\n"
             "       %*s %s\n", getprogname(), typemsg1,
             getprogname(), typemsg2, (int)strlen(getprogname()), "", typemsg3);
-	exit(1);
+	return -1;
 }
 
-static void
-chtype(int fd)
+static int
+chtype(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *m;
-	struct gpt_hdr *hdr;
+	map_t m;
 	struct gpt_ent *ent;
 	unsigned int i;
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
-
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
-
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
+	if (gpt_hdr(gpt) == NULL)
+		return -1;
 
 	/* Change type of all matching entries in the map. */
-	for (m = map_first(); m != NULL; m = m->map_next) {
+	for (m = map_first(gpt); m != NULL; m = m->map_next) {
 		if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
 			continue;
 		if (entry > 0 && entry != m->map_index)
@@ -115,9 +95,7 @@ chtype(int fd)
 
 		i = m->map_index - 1;
 
-		hdr = gpt->map_data;
-		ent = (void*)((char*)tbl->map_data + i *
-		    le32toh(hdr->hdr_entsz));
+		ent = gpt_ent_primary(gpt, i);
 
 		if (label != NULL)
 			if (strcmp((char *)label,
@@ -131,37 +109,27 @@ chtype(int fd)
 		/* Change the primary entry. */
 		gpt_uuid_copy(ent->ent_type, newtype);
 
-		hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-		hdr->hdr_crc_self = 0;
-		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-		gpt_write(fd, gpt);
-		gpt_write(fd, tbl);
-
-		hdr = tpg->map_data;
-		ent = (void*)((char*)lbt->map_data + i *
-		    le32toh(hdr->hdr_entsz));
+		if (gpt_write_primary(gpt) == -1)
+			return -1;
+
+		ent = gpt_ent_backup(gpt, i);
 
 		/* Change the secondary entry. */
 		gpt_uuid_copy(ent->ent_type, newtype);
 
-		hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-		hdr->hdr_crc_self = 0;
-		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-		gpt_write(fd, lbt);
-		gpt_write(fd, tpg);
-		printf("partition %d type changed\n", m->map_index);
+		if (gpt_write_backup(gpt) == -1)
+			return -1;
+
+		gpt_msg(gpt, "Partition %d type changed", m->map_index);
 	}
+	return 0;
 }
 
 int
-cmd_type(int argc, char *argv[])
+cmd_type(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 	int64_t human_num;
 
 	/* Get the type options */
@@ -169,73 +137,63 @@ cmd_type(int argc, char *argv[])
 		switch(ch) {
 		case 'a':
 			if (all > 0)
-				usage_type();
+				return usage_type();
 			all = 1;
 			break;
 		case 'b':
 			if (block > 0)
-				usage_type();
+				return usage_type();
 			if (dehumanize_number(optarg, &human_num) < 0)
-				usage_type();
+				return usage_type();
 			block = human_num;
 			if (block < 1)
-				usage_type();
+				return usage_type();
 			break;
 		case 'i':
 			if (entry > 0)
-				usage_type();
+				return usage_type();
 			entry = strtoul(optarg, &p, 10);
 			if (*p != 0 || entry < 1)
-				usage_type();
+				return usage_type();
 			break;
                 case 'L':
                         if (label != NULL)
-                                usage_type();
+                                return usage_type();
                         label = (uint8_t *)strdup(optarg);
                         break;
 		case 's':
 			if (size > 0)
-				usage_type();
+				return usage_type();
 			size = strtoll(optarg, &p, 10);
 			if (*p != 0 || size < 1)
-				usage_type();
+				return usage_type();
 			break;
 		case 't':
 			if (!gpt_uuid_is_nil(type))
-				usage_type();
+				return usage_type();
 			if (gpt_uuid_parse(optarg, type) != 0)
-				usage_type();
+				return usage_type();
 			break;
 		case 'T':
 			if (!gpt_uuid_is_nil(newtype))
-				usage_type();
+				return usage_type();
 			if (gpt_uuid_parse(optarg, newtype) != 0)
-				usage_type();
+				return usage_type();
 			break;
 		default:
-			usage_type();
+			return usage_type();
 		}
 	}
 
 	if (!all ^
 	    (block > 0 || entry > 0 || label != NULL || size > 0 ||
 	    !gpt_uuid_is_nil(type)))
-		usage_type();
+		return usage_type();
 	if (gpt_uuid_is_nil(newtype))
-		usage_type();
-
-	if (argc == optind)
-		usage_type();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		chtype(fd);
+		return usage_type();
 
-		gpt_close(fd);
-	}
+	if (argc != optind)
+		return usage_type();
 
-	return (0);
+	return chtype(gpt);
 }

Index: src/sbin/gpt/gpt.8
diff -u src/sbin/gpt/gpt.8:1.38 src/sbin/gpt/gpt.8:1.39
--- src/sbin/gpt/gpt.8:1.38	Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/gpt.8	Tue Dec  1 04:05:33 2015
@@ -1,4 +1,4 @@
-.\" $NetBSD: gpt.8,v 1.38 2015/11/30 19:59:34 christos Exp $
+.\" $NetBSD: gpt.8,v 1.39 2015/12/01 09:05:33 christos Exp $
 .\"
 .\" Copyright (c) 2002 Marcel Moolenaar
 .\" All rights reserved.
@@ -34,9 +34,8 @@
 .Nd GUID partition table maintenance utility
 .Sh SYNOPSIS
 .Nm
-.Op Fl mnprqv
+.Op Fl nrqv
 .Op Fl m Ar mediasize
-.Op Fl p Ar partitions
 .Op Fl s Ar sectorsize
 .Ar command
 .Op Ar command_options
@@ -81,13 +80,6 @@ changed.
 You need to use the
 .Xr dkctl 8
 command manually update the device's wedge configuration if you do that.
-.It Fl p Ar partitions
-Change the default number of partitions the GPT can
-accommodate.
-This is used whenever a new GPT is created.
-By default, the
-.Nm
-utility will create space for 128 partitions (or 32 sectors of 512 bytes).
 .It Fl r
 Open the device for reading only.
 .Nm
@@ -244,7 +236,7 @@ option selects the partition by label.
 If there are multiple partitions with the same label, it will use the
 first one found.
 .\" ==== create ====
-.It Nm Ic create Oo Fl fp Oc Ar device ...
+.It Nm Ic create Oo Fl fP Oc Oo Fl p Ar partitions Oc Ar device ...
 The
 .Ic create
 command allows the user to create a new (empty) GPT.
@@ -258,11 +250,20 @@ option is specified, an existing MBR is 
 described by the MBR are lost.
 .Pp
 The
-.Fl p
+.Fl P
 option tells
 .Nm
 to create only the primary table and not the backup table.
 This option is only useful for debugging and should not be used otherwise.
+.Pp
+The
+.Fl p
+option changes the default number of partitions the GPT can
+accommodate.
+This is used whenever a new GPT is created.
+By default, the
+.Nm
+utility will create space for 128 partitions (or 32 sectors of 512 bytes).
 .\" ==== destroy ====
 .It Nm Ic destroy Oo Fl r Oc Ar device ...
 The
@@ -340,7 +341,7 @@ The
 option is used to specify the label in the command line.
 The label is assumed to be encoded in UTF-8.
 .\" ==== migrate ====
-.It Nm Ic migrate Oo Fl fs Oc Ar device ...
+.It Nm Ic migrate Oo Fl fs Oc Oo Fl p Ar partitions Oc Ar device ...
 The
 .Ic migrate
 command allows the user to migrate an MBR-based disk partitioning into a
@@ -368,6 +369,15 @@ option isn't applicable to
 partitions.
 .Pp
 The
+.Fl p
+option changes the default number of partitions the GPT can
+accommodate.
+This is used whenever a new GPT is created.
+By default, the
+.Nm
+utility will create space for 128 partitions (or 32 sectors of 512 bytes).
+.Pp
+The
 .Ic migrate
 command requires space at the beginning and the end of the device outside
 any partitions to store the GPTs.

Index: src/sbin/gpt/gpt.c
diff -u src/sbin/gpt/gpt.c:1.48 src/sbin/gpt/gpt.c:1.49
--- src/sbin/gpt/gpt.c:1.48	Mon Nov 30 21:03:55 2015
+++ src/sbin/gpt/gpt.c	Tue Dec  1 04:05:33 2015
@@ -35,7 +35,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: gpt.c,v 1.48 2015/12/01 02:03:55 christos Exp $");
+__RCSID("$NetBSD: gpt.c,v 1.49 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/param.h>
@@ -58,19 +58,7 @@ __RCSID("$NetBSD: gpt.c,v 1.48 2015/12/0
 
 #include "map.h"
 #include "gpt.h"
-
-char	device_path[MAXPATHLEN];
-const char *device_arg;
-const char *device_name;
-
-off_t	mediasz;
-
-u_int	parts;
-u_int	secsz;
-
-int	readonly, verbose, quiet, nosync;
-
-static int modified;
+#include "gpt_private.h"
 
 static uint32_t crc32_tab[] = {
 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
@@ -243,61 +231,61 @@ utf8_to_utf16(const uint8_t *s8, uint16_
 	} while (c != 0);
 }
 
-void*
-gpt_read(int fd, off_t lba, size_t count)
+void *
+gpt_read(gpt_t gpt, off_t lba, size_t count)
 {
 	off_t ofs;
 	void *buf;
 
-	count *= secsz;
+	count *= gpt->secsz;
 	buf = malloc(count);
 	if (buf == NULL)
-		return (NULL);
+		return NULL;
 
-	ofs = lba * secsz;
-	if (lseek(fd, ofs, SEEK_SET) == ofs &&
-	    read(fd, buf, count) == (ssize_t)count)
-		return (buf);
+	ofs = lba * gpt->secsz;
+	if (lseek(gpt->fd, ofs, SEEK_SET) == ofs &&
+	    read(gpt->fd, buf, count) == (ssize_t)count)
+		return buf;
 
 	free(buf);
-	return (NULL);
+	return NULL;
 }
 
 int
-gpt_write(int fd, map_t *map)
+gpt_write(gpt_t gpt, map_t map)
 {
 	off_t ofs;
 	size_t count;
 
-	count = map->map_size * secsz;
-	ofs = map->map_start * secsz;
-	if (lseek(fd, ofs, SEEK_SET) != ofs ||
-	    write(fd, map->map_data, count) != (ssize_t)count)
+	count = map->map_size * gpt->secsz;
+	ofs = map->map_start * gpt->secsz;
+	if (lseek(gpt->fd, ofs, SEEK_SET) != ofs ||
+	    write(gpt->fd, map->map_data, count) != (ssize_t)count)
 		return -1;
-	modified = 1;
+	gpt->flags |= GPT_MODIFIED;
 	return 0;
 }
 
 static int
-gpt_mbr(int fd, off_t lba)
+gpt_mbr(gpt_t gpt, off_t lba)
 {
 	struct mbr *mbr;
-	map_t *m, *p;
+	map_t m, p;
 	off_t size, start;
 	unsigned int i, pmbr;
 
-	mbr = gpt_read(fd, lba, 1);
+	mbr = gpt_read(gpt, lba, 1);
 	if (mbr == NULL) {
-		if (!quiet)
-			warn("%s: read failed", device_name);
-		return (-1);
+		gpt_warn(gpt, "Read failed");
+		return -1;
 	}
 
 	if (mbr->mbr_sig != htole16(MBR_SIG)) {
-		if (verbose)
-			gpt_msg("MBR not found at sector %ju", (uintmax_t)lba);
+		if (gpt->verbose)
+			gpt_msg(gpt,
+			    "MBR not found at sector %ju", (uintmax_t)lba);
 		free(mbr);
-		return (0);
+		return 0;
 	}
 
 	/*
@@ -315,23 +303,23 @@ gpt_mbr(int fd, off_t lba)
 			break;
 	}
 	if (pmbr && i == 4 && lba == 0) {
-		if (pmbr != 1 && !quiet)
-			warnx("%s: Suspicious PMBR at sector %ju",
-			    device_name, (uintmax_t)lba);
-		else if (verbose > 1)
-			gpt_msg("PMBR at sector %ju", (uintmax_t)lba);
-		p = map_add(lba, 1LL, MAP_TYPE_PMBR, mbr);
-		return ((p == NULL) ? -1 : 0);
-	}
-	if (pmbr && !quiet)
-		warnx("%s: Suspicious MBR at sector %ju", device_name,
-		    (uintmax_t)lba);
-	else if (verbose > 1)
-		gpt_msg("MBR at sector %ju", (uintmax_t)lba);
+		if (pmbr != 1)
+			gpt_warnx(gpt, "Suspicious PMBR at sector %ju",
+			    (uintmax_t)lba);
+		else if (gpt->verbose > 1)
+			gpt_msg(gpt, "PMBR at sector %ju", (uintmax_t)lba);
+		p = map_add(gpt, lba, 1LL, MAP_TYPE_PMBR, mbr);
+		goto out;
+	}
+	if (pmbr)
+		gpt_warnx(gpt, "Suspicious MBR at sector %ju", (uintmax_t)lba);
+	else if (gpt->verbose > 1)
+		gpt_msg(gpt, "MBR at sector %ju", (uintmax_t)lba);
 
-	p = map_add(lba, 1LL, MAP_TYPE_MBR, mbr);
+	p = map_add(gpt, lba, 1LL, MAP_TYPE_MBR, mbr);
 	if (p == NULL)
-		return (-1);
+		goto out;
+
 	for (i = 0; i < 4; i++) {
 		if (mbr->mbr_part[i].part_typ == MBR_PTYPE_UNUSED ||
 		    mbr->mbr_part[i].part_typ == MBR_PTYPE_PMBR)
@@ -341,44 +329,50 @@ gpt_mbr(int fd, off_t lba)
 		size = le16toh(mbr->mbr_part[i].part_size_hi);
 		size = (size << 16) + le16toh(mbr->mbr_part[i].part_size_lo);
 		if (start == 0 && size == 0) {
-			warnx("%s: Malformed MBR at sector %llu", device_name,
-			    (long long)lba);
+			gpt_warnx(gpt, "Malformed MBR at sector %ju",
+			    (uintmax_t)lba);
 			continue;
 		}
 		/* start is relative to the offset of the MBR itself. */
 		start += lba;
-		if (verbose > 2)
-			gpt_msg("MBR part: type=%d, start=%ju, size=%ju",
+		if (gpt->verbose > 2)
+			gpt_msg(gpt, "MBR part: type=%d, start=%ju, size=%ju",
 			    mbr->mbr_part[i].part_typ,
 			    (uintmax_t)start, (uintmax_t)size);
 		if (mbr->mbr_part[i].part_typ != MBR_PTYPE_EXT_LBA) {
-			m = map_add(start, size, MAP_TYPE_MBR_PART, p);
+			m = map_add(gpt, start, size, MAP_TYPE_MBR_PART, p);
 			if (m == NULL)
-				return (-1);
+				return -1;
 			m->map_index = i + 1;
 		} else {
-			if (gpt_mbr(fd, start) == -1)
-				return (-1);
+			if (gpt_mbr(gpt, start) == -1)
+				return -1;
 		}
 	}
-	return (0);
+	return 0;
+out:
+	if (p == NULL) {
+		free(mbr);
+		return -1;
+	}
+	return 0;
 }
 
 int
-gpt_gpt(int fd, off_t lba, int found)
+gpt_gpt(gpt_t gpt, off_t lba, int found)
 {
 	off_t size;
 	struct gpt_ent *ent;
 	struct gpt_hdr *hdr;
 	char *p;
-	map_t *m;
+	map_t m;
 	size_t blocks, tblsz;
 	unsigned int i;
 	uint32_t crc;
 
-	hdr = gpt_read(fd, lba, 1);
+	hdr = gpt_read(gpt, lba, 1);
 	if (hdr == NULL)
-		return (-1);
+		return -1;
 
 	if (memcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)))
 		goto fail_hdr;
@@ -386,46 +380,45 @@ gpt_gpt(int fd, off_t lba, int found)
 	crc = le32toh(hdr->hdr_crc_self);
 	hdr->hdr_crc_self = 0;
 	if (crc32(hdr, le32toh(hdr->hdr_size)) != crc) {
-		if (verbose)
-			warnx("%s: Bad CRC in GPT header at sector %llu",
-			    device_name, (long long)lba);
+		if (gpt->verbose)
+			gpt_msg(gpt, "Bad CRC in GPT header at sector %ju",
+			    (uintmax_t)lba);
 		goto fail_hdr;
 	}
 
 	tblsz = le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz);
-	blocks = tblsz / secsz + ((tblsz % secsz) ? 1 : 0);
+	blocks = tblsz / gpt->secsz + ((tblsz % gpt->secsz) ? 1 : 0);
 
 	/* Use generic pointer to deal with hdr->hdr_entsz != sizeof(*ent). */
-	p = gpt_read(fd, le64toh(hdr->hdr_lba_table), blocks);
+	p = gpt_read(gpt, le64toh(hdr->hdr_lba_table), blocks);
 	if (p == NULL) {
 		if (found) {
-			if (verbose)
-				warn("%s: Cannot read LBA table at sector %llu",
-				    device_name, (unsigned long long)
-				    le64toh(hdr->hdr_lba_table));
-			return (-1);
+			if (gpt->verbose)
+				gpt_msg(gpt,
+				    "Cannot read LBA table at sector %ju",
+				    (uintmax_t)le64toh(hdr->hdr_lba_table));
+			return -1;
 		}
 		goto fail_hdr;
 	}
 
 	if (crc32(p, tblsz) != le32toh(hdr->hdr_crc_table)) {
-		if (verbose)
-			warnx("%s: Bad CRC in GPT table at sector %llu",
-			    device_name,
-			    (long long)le64toh(hdr->hdr_lba_table));
+		if (gpt->verbose)
+			gpt_msg(gpt, "Bad CRC in GPT table at sector %ju",
+			    (uintmax_t)le64toh(hdr->hdr_lba_table));
 		goto fail_ent;
 	}
 
-	if (verbose > 1)
-		warnx("%s: %s GPT at sector %llu", device_name,
-		    (lba == 1) ? "Pri" : "Sec", (long long)lba);
+	if (gpt->verbose > 1)
+		gpt_msg(gpt, "%s GPT at sector %ju",
+		    (lba == 1) ? "Pri" : "Sec", (uintmax_t)lba);
 
-	m = map_add(lba, 1, (lba == 1)
+	m = map_add(gpt, lba, 1, (lba == 1)
 	    ? MAP_TYPE_PRI_GPT_HDR : MAP_TYPE_SEC_GPT_HDR, hdr);
 	if (m == NULL)
 		return (-1);
 
-	m = map_add(le64toh(hdr->hdr_lba_table), blocks, (lba == 1)
+	m = map_add(gpt, le64toh(hdr->hdr_lba_table), blocks, (lba == 1)
 	    ? MAP_TYPE_PRI_GPT_TBL : MAP_TYPE_SEC_GPT_TBL, p);
 	if (m == NULL)
 		return (-1);
@@ -440,16 +433,16 @@ gpt_gpt(int fd, off_t lba, int found)
 
 		size = le64toh(ent->ent_lba_end) - le64toh(ent->ent_lba_start) +
 		    1LL;
-		if (verbose > 2) {
+		if (gpt->verbose > 2) {
 			char buf[128];
 			gpt_uuid_snprintf(buf, sizeof(buf), "%s", 
 			    ent->ent_type);
-			warnx("%s: GPT partition: type=%s, start=%llu, "
-			    "size=%llu", device_name, buf,
-			    (long long)le64toh(ent->ent_lba_start),
-			    (long long)size);
+			gpt_msg(gpt, "GPT partition: type=%s, start=%ju, "
+			    "size=%ju", buf,
+			    (uintmax_t)le64toh(ent->ent_lba_start),
+			    (uintmax_t)size);
 		}
-		m = map_add(le64toh(ent->ent_lba_start), size,
+		m = map_add(gpt, le64toh(ent->ent_lba_start), size,
 		    MAP_TYPE_GPT_PART, ent);
 		if (m == NULL)
 			return (-1);
@@ -465,72 +458,73 @@ gpt_gpt(int fd, off_t lba, int found)
 	return (0);
 }
 
-int
-gpt_open(const char *dev, int flags)
+gpt_t
+gpt_open(const char *dev, int flags, int verbose, off_t mediasz, u_int secsz)
 {
-	struct stat sb;
-	int fd, mode, found;
+	int mode, found;
 	off_t devsz;
+	gpt_t gpt;
 
-	mode = readonly ? O_RDONLY : O_RDWR|O_EXCL;
 
-	device_arg = device_name = dev;
-	fd = opendisk(dev, mode, device_path, sizeof(device_path), 0);
-	if (fd == -1) {
-		if (!quiet)
-			warn("Cannot open `%s'", device_name);
-		return -1;
+	if ((gpt = calloc(1, sizeof(*gpt))) == NULL) {
+		if (!(gpt->flags & GPT_QUIET))
+			warn("Cannot allocate `%s'", dev);
+		return NULL;
+	}
+	gpt->flags = flags;
+	gpt->verbose = verbose;
+	gpt->mediasz = mediasz;
+	gpt->secsz = secsz;
+
+	mode = (gpt->flags & GPT_READONLY) ? O_RDONLY : O_RDWR|O_EXCL;
+		
+	gpt->fd = opendisk(dev, mode, gpt->device_name,
+	    sizeof(gpt->device_name), 0);
+	if (gpt->fd == -1) {
+		strlcpy(gpt->device_name, dev, sizeof(gpt->device_name));
+		gpt_warn(gpt, "Cannot open");
+		goto close;
 	}
-	device_name = device_path;
 
-	if (fstat(fd, &sb) == -1) {
-		if (!quiet)
-			warn("Cannot stat `%s'", device_name);
+	if (fstat(gpt->fd, &gpt->sb) == -1) {
+		gpt_warn(gpt, "Cannot stat");
 		goto close;
 	}
 
-	if ((sb.st_mode & S_IFMT) != S_IFREG) {
-		if (secsz == 0) {
+	if ((gpt->sb.st_mode & S_IFMT) != S_IFREG) {
+		if (gpt->secsz == 0) {
 #ifdef DIOCGSECTORSIZE
-			if (ioctl(fd, DIOCGSECTORSIZE, &secsz) == -1) {
-				if (!quiet)
-					warn("Cannot get sector size for `%s'",
-					    device_name);
+			if (ioctl(gpt->fd, DIOCGSECTORSIZE, &gpt->secsz) == -1) {
+				gpt_warn(gpt, "Cannot get sector size");
 				goto close;
 			}
 #endif
-			if (secsz == 0) {
-				if (!quiet)
-					warnx("Sector size for `%s' can't be 0",
-					    device_name);
+			if (gpt->secsz == 0) {
+				gpt_warnx(gpt, "Sector size can't be 0");
 				goto close;
 			}
 		}
-		if (mediasz == 0) {
+		if (gpt->mediasz == 0) {
 #ifdef DIOCGMEDIASIZE
-			if (ioctl(fd, DIOCGMEDIASIZE, &mediasz) == -1) {
-				if (!quiet)
-					warn("Cannot get media size for `%s'",
-					device_name);
+			if (ioctl(gpt->fd, DIOCGMEDIASIZE, &gpt->mediasz) == -1) {
+				gpt_warn(gpt, "Cannot get media size");
 				goto close;
 			}
 #endif
-			if (mediasz == 0) {
-				if (!quiet)
-					warnx("Media size for `%s' can't be 0",
-					    device_name);
+			if (gpt->mediasz == 0) {
+				gpt_warnx(gpt, "Media size can't be 0");
 				goto close;
 			}
 		}
 	} else {
-		if (secsz == 0)
-			secsz = 512;	/* Fixed size for files. */
-		if (mediasz == 0) {
-			if (sb.st_size % secsz) {
+		if (gpt->secsz == 0)
+			gpt->secsz = 512;	/* Fixed size for files. */
+		if (gpt->mediasz == 0) {
+			if (gpt->sb.st_size % gpt->secsz) {
 				errno = EINVAL;
 				goto close;
 			}
-			mediasz = sb.st_size;
+			gpt->mediasz = gpt->sb.st_size;
 		}
 	}
 
@@ -540,68 +534,217 @@ gpt_open(const char *dev, int flags)
 	 * user data. Let's catch this extreme border case here so that
 	 * we don't have to worry about it later.
 	 */
-	devsz = mediasz / secsz;
+	devsz = gpt->mediasz / gpt->secsz;
 	if (devsz < 6) {
-		if (!quiet)
-			warnx("Need 6 sectors on '%s' we have %ju",
-			    device_name, (uintmax_t)devsz);
+		gpt_warnx(gpt, "Need 6 sectorso, we have %ju",
+		    (uintmax_t)devsz);
 		goto close;
 	}
 
-	if (verbose) {
-		gpt_msg("mediasize=%ju; sectorsize=%u; blocks=%ju",
-		    (uintmax_t)mediasz, secsz, (uintmax_t)devsz);
+	if (gpt->verbose) {
+		gpt_msg(gpt, "mediasize=%ju; sectorsize=%u; blocks=%ju",
+		    (uintmax_t)gpt->mediasz, gpt->secsz, (uintmax_t)devsz);
 	}
 
-	map_init(devsz);
+	map_init(gpt, devsz);
 
-	if (gpt_mbr(fd, 0LL) == -1)
+	if (gpt_mbr(gpt, 0LL) == -1)
 		goto close;
-	if ((found = gpt_gpt(fd, 1LL, 1)) == -1)
+	if ((found = gpt_gpt(gpt, 1LL, 1)) == -1)
 		goto close;
-	if (gpt_gpt(fd, devsz - 1LL, found) == -1)
+	if (gpt_gpt(gpt, devsz - 1LL, found) == -1)
 		goto close;
 
-	return (fd);
+	return gpt;
 
  close:
-	close(fd);
-	return (-1);
+	if (gpt->fd != -1)
+		close(gpt->fd);
+	free(gpt);
+	return NULL;
 }
 
 void
-gpt_close(int fd)
+gpt_close(gpt_t gpt)
 {
 
-	if (!modified)
+	if (!(gpt->flags & GPT_MODIFIED))
 		goto out;
 
-	if (!nosync) {
+	if (!(gpt->flags & GPT_NOSYNC)) {
 #ifdef DIOCMWEDGES
 		int bits;
-		if (ioctl(fd, DIOCMWEDGES, &bits) == -1)
-			warn("Can't update wedge information");
+		if (ioctl(gpt->fd, DIOCMWEDGES, &bits) == -1)
+			gpt_warn(gpt, "Can't update wedge information");
 		else
 			goto out;
 #endif
 	}
-	gpt_msg("You need to run \"dkctl %s makewedges\""
-	    " for the changes to take effect\n", device_name);
+	gpt_msg(gpt, "You need to run \"dkctl %s makewedges\""
+	    " for the changes to take effect\n", gpt->device_name);
 
 out:
-	close(fd);
+	close(gpt->fd);
 }
 
 void
-gpt_msg(const char *fmt, ...)
+gpt_warnx(gpt_t gpt, const char *fmt, ...)
 {
 	va_list ap;
 
-	if (quiet)
+	if (gpt->flags & GPT_QUIET)
 		return;
-	printf("%s: ", device_name);
+	fprintf(stderr, "%s: %s: ", getprogname(), gpt->device_name);
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
+
+void
+gpt_warn(gpt_t gpt, const char *fmt, ...)
+{
+	va_list ap;
+	int e = errno;
+
+	if (gpt->flags & GPT_QUIET)
+		return;
+	fprintf(stderr, "%s: %s: ", getprogname(), gpt->device_name);
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, " (%s)\n", strerror(e));
+	errno = e;
+}
+
+void
+gpt_msg(gpt_t gpt, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (gpt->flags & GPT_QUIET)
+		return;
+	printf("%s: ", gpt->device_name);
 	va_start(ap, fmt);
 	vprintf(fmt, ap);
 	va_end(ap);
 	printf("\n");
 }
+
+struct gpt_hdr *
+gpt_hdr(gpt_t gpt)
+{
+	gpt->gpt = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+	if (gpt->gpt == NULL) {
+		gpt_warnx(gpt, "No primary GPT header; run create or recover");
+		return NULL;
+	}
+
+	gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+	if (gpt->tpg == NULL) {
+		gpt_warnx(gpt, "No secondary GPT header; run recover");
+		return NULL;
+	}
+
+	gpt->tbl = map_find(gpt, MAP_TYPE_PRI_GPT_TBL);
+	gpt->lbt = map_find(gpt, MAP_TYPE_SEC_GPT_TBL);
+	if (gpt->tbl == NULL || gpt->lbt == NULL) {
+		gpt_warnx(gpt, "Corrupt maps, run recover");
+		return NULL;
+	}
+
+	return gpt->gpt->map_data;
+}
+
+int
+gpt_write_crc(gpt_t gpt, map_t map, map_t tbl)
+{
+	struct gpt_hdr *hdr = map->map_data;
+
+	hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
+	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
+	hdr->hdr_crc_self = 0;
+	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+
+	if (gpt_write(gpt, map) == -1) {
+		gpt_warn(gpt, "Error writing crc map");
+		return -1;
+	}
+
+	if (gpt_write(gpt, tbl) == -1) {
+		gpt_warn(gpt, "Error writing crc table");
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+gpt_write_primary(gpt_t gpt)
+{
+	return gpt_write_crc(gpt, gpt->gpt, gpt->tbl);
+}
+
+
+int
+gpt_write_backup(gpt_t gpt)
+{
+	return gpt_write_crc(gpt, gpt->tpg, gpt->lbt);
+}
+
+void
+gpt_create_pmbr_part(struct mbr_part *part, off_t last)
+{
+	part->part_shd = 0x00;
+	part->part_ssect = 0x02;
+	part->part_scyl = 0x00;
+	part->part_typ = MBR_PTYPE_PMBR;
+	part->part_ehd = 0xfe;
+	part->part_esect = 0xff;
+	part->part_ecyl = 0xff;
+	part->part_start_lo = htole16(1);
+	if (last > 0xffffffff) {
+		part->part_size_lo = htole16(0xffff);
+		part->part_size_hi = htole16(0xffff);
+	} else {
+		part->part_size_lo = htole16(last);
+		part->part_size_hi = htole16(last >> 16);
+	}
+}
+
+off_t
+gpt_check(gpt_t gpt, off_t alignment, off_t size)
+{
+	if (alignment % gpt->secsz != 0) {
+		gpt_warnx(gpt, "Alignment (%#jx) must be a multiple of "
+		    "sector size (%#x)", (uintmax_t)alignment, gpt->secsz);
+		return -1;
+	}
+
+	if (size % gpt->secsz != 0) {
+		gpt_warnx(gpt, "Size (%#jx) must be a multiple of "
+		    "sector size (%#x)", (uintmax_t)size, gpt->secsz);
+		return -1;
+	}
+	if (size > 0)
+		return size / gpt->secsz;
+	return 0;
+}
+struct gpt_ent *
+gpt_ent(map_t map, map_t tbl, unsigned int i)
+{
+	struct gpt_hdr *hdr = map->map_data;
+	return (void *)((char *)tbl->map_data + i * le32toh(hdr->hdr_entsz));
+}
+
+struct gpt_ent *
+gpt_ent_primary(gpt_t gpt, unsigned int i)
+{
+	return gpt_ent(gpt->gpt, gpt->tbl, i);
+}
+
+struct gpt_ent *
+gpt_ent_backup(gpt_t gpt, unsigned int i)
+{
+	return gpt_ent(gpt->tpg, gpt->lbt, i);
+}

Index: src/sbin/gpt/gpt.h
diff -u src/sbin/gpt/gpt.h:1.22 src/sbin/gpt/gpt.h:1.23
--- src/sbin/gpt/gpt.h:1.22	Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/gpt.h	Tue Dec  1 04:05:33 2015
@@ -60,40 +60,52 @@ struct mbr {
 #define	MBR_SIG		0xAA55
 };
 
-extern const char *device_arg;
-extern const char *device_name;
-extern off_t mediasz;
-extern u_int parts;
-extern u_int secsz;
-extern int readonly, verbose, quiet, nosync;
+typedef struct gpt *gpt_t;
+typedef struct map *map_t;
 
 uint32_t crc32(const void *, size_t);
-void	gpt_close(int);
-int	gpt_gpt(int, off_t, int);
-int	gpt_open(const char *, int);
-void*	gpt_read(int, off_t, size_t);
-int	gpt_write(int, map_t *);
-void	gpt_msg(const char *, ...) __printflike(1, 2);
+void	gpt_close(gpt_t);
+int	gpt_gpt(gpt_t, off_t, int);
+gpt_t	gpt_open(const char *, int, int, off_t, u_int);
+void*	gpt_read(gpt_t, off_t, size_t);
+int	gpt_write(gpt_t, map_t);
+int	gpt_write_crc(gpt_t, map_t, map_t);
+int	gpt_write_primary(gpt_t);
+int	gpt_write_backup(gpt_t);
+struct gpt_hdr *gpt_hdr(gpt_t);
+void	gpt_msg(gpt_t, const char *, ...) __printflike(2, 3);
+void	gpt_warn(gpt_t, const char *, ...) __printflike(2, 3);
+void	gpt_warnx(gpt_t, const char *, ...) __printflike(2, 3);
+void	gpt_create_pmbr_part(struct mbr_part *, off_t);
+off_t	gpt_check(gpt_t, off_t, off_t);
+struct gpt_ent *gpt_ent(map_t, map_t, unsigned int);
+struct gpt_ent *gpt_ent_primary(gpt_t, unsigned int);
+struct gpt_ent *gpt_ent_backup(gpt_t, unsigned int);
 
 uint8_t *utf16_to_utf8(uint16_t *);
 void	utf8_to_utf16(const uint8_t *, uint16_t *, size_t);
 
-int	cmd_add(int, char *[]);
-int	cmd_backup(int, char *[]);
-int	cmd_biosboot(int, char *[]);
-int	cmd_create(int, char *[]);
-int	cmd_destroy(int, char *[]);
-int	cmd_header(int, char *[]);
-int	cmd_label(int, char *[]);
-int	cmd_migrate(int, char *[]);
-int	cmd_recover(int, char *[]);
-int	cmd_remove(int, char *[]);
-int	cmd_resize(int, char *[]);
-int	cmd_resizedisk(int, char *[]);
-int	cmd_restore(int, char *[]);
-int	cmd_set(int, char *[]);
-int	cmd_show(int, char *[]);
-int	cmd_type(int, char *[]);
-int	cmd_unset(int, char *[]);
+int	cmd_add(gpt_t, int, char *[]);
+int	cmd_backup(gpt_t, int, char *[]);
+int	cmd_biosboot(gpt_t, int, char *[]);
+int	cmd_create(gpt_t, int, char *[]);
+int	cmd_destroy(gpt_t, int, char *[]);
+int	cmd_header(gpt_t, int, char *[]);
+int	cmd_label(gpt_t, int, char *[]);
+int	cmd_migrate(gpt_t, int, char *[]);
+int	cmd_recover(gpt_t, int, char *[]);
+int	cmd_remove(gpt_t, int, char *[]);
+int	cmd_resize(gpt_t, int, char *[]);
+int	cmd_resizedisk(gpt_t, int, char *[]);
+int	cmd_restore(gpt_t, int, char *[]);
+int	cmd_set(gpt_t, int, char *[]);
+int	cmd_show(gpt_t, int, char *[]);
+int	cmd_type(gpt_t, int, char *[]);
+int	cmd_unset(gpt_t, int, char *[]);
+
+#define GPT_READONLY	1
+#define GPT_MODIFIED	2
+#define GPT_QUIET	4
+#define GPT_NOSYNC	8
 
 #endif /* _GPT_H_ */
Index: src/sbin/gpt/migrate.c
diff -u src/sbin/gpt/migrate.c:1.22 src/sbin/gpt/migrate.c:1.23
--- src/sbin/gpt/migrate.c:1.22	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/migrate.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/migrate.c,v 1.16 2005/09/01 02:42:52 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: migrate.c,v 1.22 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: migrate.c,v 1.23 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -55,6 +55,7 @@ __RCSID("$NetBSD: migrate.c,v 1.22 2015/
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 /*
  * Allow compilation on platforms that do not have a BSD label.
@@ -77,33 +78,37 @@ __RCSID("$NetBSD: migrate.c,v 1.22 2015/
 
 static int force;
 static int slice;
+static u_int parts;
 
-const char migratemsg[] = "migrate [-fs] device ...";
+const char migratemsg[] = "migrate [-fs] [-p <partitions>]";
 
-__dead static void
+static int
 usage_migrate(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), migratemsg);
-	exit(1);
+	return -1;
 }
 
-static struct gpt_ent*
-migrate_disklabel(int fd, off_t start, struct gpt_ent *ent)
+static struct gpt_ent *
+migrate_disklabel(gpt_t gpt, off_t start, struct gpt_ent *ent)
 {
 	char *buf;
 	struct disklabel *dl;
 	off_t ofs, rawofs;
 	int i;
 
-	buf = gpt_read(fd, start + LABELSECTOR, 1);
+	buf = gpt_read(gpt, start + LABELSECTOR, 1);
+	if (buf == NULL) {
+		gpt_warn(gpt, "Error reading label");
+		return NULL;
+	}
 	dl = (void*)(buf + LABELOFFSET);
 
 	if (le32toh(dl->d_magic) != DISKMAGIC ||
 	    le32toh(dl->d_magic2) != DISKMAGIC) {
-		warnx("%s: warning: FreeBSD slice without disklabel",
-		    device_name);
+		gpt_warnx(gpt, "FreeBSD slice without disklabel");
 		free(buf);
 		return (ent);
 	}
@@ -118,7 +123,7 @@ migrate_disklabel(int fd, off_t start, s
 		if (ofs < rawofs)
 			rawofs = 0;
 	}
-	rawofs /= secsz;
+	rawofs /= gpt->secsz;
 
 	for (i = 0; i < le16toh(dl->d_npartitions); i++) {
 		switch (dl->d_partitions[i].p_fstype) {
@@ -145,13 +150,13 @@ migrate_disklabel(int fd, off_t start, s
 			break;
 		}
 		default:
-			warnx("%s: warning: unknown FreeBSD partition (%d)",
-			    device_name, dl->d_partitions[i].p_fstype);
+			gpt_warnx(gpt, "Unknown FreeBSD partition (%d)",
+			    dl->d_partitions[i].p_fstype);
 			continue;
 		}
 
 		ofs = (le32toh(dl->d_partitions[i].p_offset) *
-		    le32toh(dl->d_secsize)) / secsz;
+		    le32toh(dl->d_secsize)) / gpt->secsz;
 		ofs = (ofs > 0) ? ofs - rawofs : 0;
 		ent->ent_lba_start = htole64(start + ofs);
 		ent->ent_lba_end = htole64(start + ofs +
@@ -160,26 +165,29 @@ migrate_disklabel(int fd, off_t start, s
 	}
 
 	free(buf);
-	return (ent);
+	return ent;
 }
 
 static struct gpt_ent*
-migrate_netbsd_disklabel(int fd, off_t start, struct gpt_ent *ent)
+migrate_netbsd_disklabel(gpt_t gpt, off_t start, struct gpt_ent *ent)
 {
 	char *buf;
 	struct disklabel *dl;
 	off_t ofs, rawofs;
 	int i;
 
-	buf = gpt_read(fd, start + LABELSECTOR, 1);
+	buf = gpt_read(gpt, start + LABELSECTOR, 1);
+	if (buf == NULL) {
+		gpt_warn(gpt, "Error reading label");
+		return NULL;
+	}
 	dl = (void*)(buf + LABELOFFSET);
 
 	if (le32toh(dl->d_magic) != DISKMAGIC ||
 	    le32toh(dl->d_magic2) != DISKMAGIC) {
-		warnx("%s: warning: NetBSD slice without disklabel",
-		    device_name);
+		gpt_warnx(gpt, "NetBSD slice without disklabel");
 		free(buf);
-		return (ent);
+		return ent;
 	}
 
 	rawofs = le32toh(dl->d_partitions[RAW_PART].p_offset) *
@@ -192,7 +200,7 @@ migrate_netbsd_disklabel(int fd, off_t s
 		if (ofs < rawofs)
 			rawofs = 0;
 	}
-	rawofs /= secsz;
+	rawofs /= gpt->secsz;
 
 	for (i = 0; i < le16toh(dl->d_npartitions); i++) {
 		switch (dl->d_partitions[i].p_fstype) {
@@ -229,13 +237,13 @@ migrate_netbsd_disklabel(int fd, off_t s
 			break;
 		}
 		default:
-			warnx("%s: warning: unknown NetBSD partition (%d)",
-			    device_name, dl->d_partitions[i].p_fstype);
+			gpt_warnx(gpt, "Unknown NetBSD partition (%d)",
+			    dl->d_partitions[i].p_fstype);
 			continue;
 		}
 
 		ofs = (le32toh(dl->d_partitions[i].p_offset) *
-		    le32toh(dl->d_secsize)) / secsz;
+		    le32toh(dl->d_secsize)) / gpt->secsz;
 		ofs = (ofs > 0) ? ofs - rawofs : 0;
 		ent->ent_lba_start = htole64(ofs);
 		ent->ent_lba_end = htole64(ofs +
@@ -244,49 +252,48 @@ migrate_netbsd_disklabel(int fd, off_t s
 	}
 
 	free(buf);
-	return (ent);
+	return ent;
 }
 
-static void
-migrate(int fd)
+static int
+migrate(gpt_t gpt)
 {
 	off_t blocks, last;
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *map;
+	map_t map;
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	struct mbr *mbr;
 	uint32_t start, size;
 	unsigned int i;
 
-	last = mediasz / secsz - 1LL;
+	last = gpt->mediasz / gpt->secsz - 1LL;
 
-	map = map_find(MAP_TYPE_MBR);
+	map = map_find(gpt, MAP_TYPE_MBR);
 	if (map == NULL || map->map_start != 0) {
-		warnx("%s: error: no partitions to convert", device_name);
-		return;
+		gpt_warnx(gpt, "No partitions to convert");
+		return -1;
 	}
 
 	mbr = map->map_data;
 
-	if (map_find(MAP_TYPE_PRI_GPT_HDR) != NULL ||
-	    map_find(MAP_TYPE_SEC_GPT_HDR) != NULL) {
-		warnx("%s: error: device already contains a GPT", device_name);
-		return;
+	if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL ||
+	    map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) {
+		gpt_warnx(gpt, "Device already contains a GPT");
+		return -1;
 	}
 
 	/* Get the amount of free space after the MBR */
-	blocks = map_free(1LL, 0LL);
+	blocks = map_free(gpt, 1LL, 0LL);
 	if (blocks == 0LL) {
-		warnx("%s: error: no room for the GPT header", device_name);
-		return;
+		gpt_warnx(gpt, "No room for the GPT header");
+		return -1;
 	}
 
 	/* Don't create more than parts entries. */
-	if ((uint64_t)(blocks - 1) * secsz > parts * sizeof(struct gpt_ent)) {
-		blocks = (parts * sizeof(struct gpt_ent)) / secsz;
-		if ((parts * sizeof(struct gpt_ent)) % secsz)
+	if ((uint64_t)(blocks - 1) * gpt->secsz >
+	    parts * sizeof(struct gpt_ent)) {
+		blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz;
+		if ((parts * sizeof(struct gpt_ent)) % gpt->secsz)
 			blocks++;
 		blocks++;		/* Don't forget the header itself */
 	}
@@ -299,50 +306,53 @@ migrate(int fd)
 	 * Get the amount of free space at the end of the device and
 	 * calculate the size for the GPT structures.
 	 */
-	map = map_last();
+	map = map_last(gpt);
 	if (map->map_type != MAP_TYPE_UNUSED) {
-		warnx("%s: error: no room for the backup header", device_name);
-		return;
+		gpt_warnx(gpt, "No room for the backup header");
+		return -1;
 	}
 
 	if (map->map_size < blocks)
 		blocks = map->map_size;
 	if (blocks == 1LL) {
-		warnx("%s: error: no room for the GPT table", device_name);
-		return;
+		gpt_warnx(gpt, "No room for the GPT table");
+		return -1;
 	}
 
 	blocks--;		/* Number of blocks in the GPT table. */
-	gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR, calloc(1, secsz));
-	tbl = map_add(2LL, blocks, MAP_TYPE_PRI_GPT_TBL,
-	    calloc(blocks, secsz));
-	if (gpt == NULL || tbl == NULL)
-		return;
-
-	lbt = map_add(last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,
-	    tbl->map_data);
-	tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR, calloc(1, secsz));
+	gpt->gpt = map_add(gpt, 1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
+	    calloc(1, gpt->secsz));
+	gpt->tbl = map_add(gpt, 2LL, blocks, MAP_TYPE_PRI_GPT_TBL,
+	    calloc(blocks, gpt->secsz));
+	if (gpt->gpt == NULL || gpt->tbl == NULL)
+		return -1;
+
+	gpt->lbt = map_add(gpt, last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,
+	    gpt->tbl->map_data);
+	gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR,
+	    calloc(1, gpt->secsz));
 
-	hdr = gpt->map_data;
+	hdr = gpt->gpt->map_data;
 	memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
 	hdr->hdr_revision = htole32(GPT_HDR_REVISION);
+
 	/*
 	 * XXX struct gpt_hdr is not a multiple of 8 bytes in size and thus
 	 * contains padding we must not include in the size.
 	 */
 	hdr->hdr_size = htole32(GPT_HDR_SIZE);
-	hdr->hdr_lba_self = htole64(gpt->map_start);
-	hdr->hdr_lba_alt = htole64(tpg->map_start);
-	hdr->hdr_lba_start = htole64(tbl->map_start + blocks);
-	hdr->hdr_lba_end = htole64(lbt->map_start - 1LL);
+	hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
+	hdr->hdr_lba_alt = htole64(gpt->tpg->map_start);
+	hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks);
+	hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1LL);
 	gpt_uuid_generate(hdr->hdr_guid);
-	hdr->hdr_lba_table = htole64(tbl->map_start);
-	hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent));
+	hdr->hdr_lba_table = htole64(gpt->tbl->map_start);
+	hdr->hdr_entries = htole32((blocks * gpt->secsz) / sizeof(struct gpt_ent));
 	if (le32toh(hdr->hdr_entries) > parts)
 		hdr->hdr_entries = htole32(parts);
 	hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));
 
-	ent = tbl->map_data;
+	ent = gpt->tbl->map_data;
 	for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
 		gpt_uuid_generate(ent[i].ent_guid);
 	}
@@ -366,11 +376,11 @@ migrate(int fd)
 				ent->ent_lba_end = htole64(start + size - 1LL);
 				ent++;
 			} else
-				ent = migrate_disklabel(fd, start, ent);
+				ent = migrate_disklabel(gpt, start, ent);
 			break;
 		}
 		case MBR_PTYPE_NETBSD:
-			ent = migrate_netbsd_disklabel(fd, start, ent);
+			ent = migrate_netbsd_disklabel(gpt, start, ent);
 			break;
 		case MBR_PTYPE_EFI: {
 			gpt_uuid_create(GPT_TYPE_EFI,
@@ -383,90 +393,66 @@ migrate(int fd)
 		}
 		default:
 			if (!force) {
-				warnx("%s: error: unknown partition type (%d)",
-				    device_name, mbr->mbr_part[i].part_typ);
-				return;
+				gpt_warnx(gpt, "unknown partition type (%d)",
+				    mbr->mbr_part[i].part_typ);
+				return -1;
 			}
+			break;
 		}
 	}
-	ent = tbl->map_data;
 
-	hdr->hdr_crc_table = htole32(crc32(ent, le32toh(hdr->hdr_entries) *
-	    le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, gpt);
-	gpt_write(fd, tbl);
+	if (gpt_write_primary(gpt) == -1)
+		return -1;
 
 	/*
 	 * Create backup GPT.
 	 */
-	memcpy(tpg->map_data, gpt->map_data, secsz);
-	hdr = tpg->map_data;
-	hdr->hdr_lba_self = htole64(tpg->map_start);
-	hdr->hdr_lba_alt = htole64(gpt->map_start);
-	hdr->hdr_lba_table = htole64(lbt->map_start);
-	hdr->hdr_crc_self = 0;			/* Don't ever forget this! */
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+	memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
+	hdr = gpt->tpg->map_data;
+	hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+	hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+	hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
 
-	gpt_write(fd, lbt);
-	gpt_write(fd, tpg);
+	if (gpt_write_backup(gpt) == -1)
+		return -1;
 
-	map = map_find(MAP_TYPE_MBR);
+	map = map_find(gpt, MAP_TYPE_MBR);
 	mbr = map->map_data;
 	/*
 	 * Turn the MBR into a Protective MBR.
 	 */
 	memset(mbr->mbr_part, 0, sizeof(mbr->mbr_part));
-	mbr->mbr_part[0].part_shd = 0x00;
-	mbr->mbr_part[0].part_ssect = 0x02;
-	mbr->mbr_part[0].part_scyl = 0x00;
-	mbr->mbr_part[0].part_typ = MBR_PTYPE_PMBR;
-	mbr->mbr_part[0].part_ehd = 0xfe;
-	mbr->mbr_part[0].part_esect = 0xff;
-	mbr->mbr_part[0].part_ecyl = 0xff;
-	mbr->mbr_part[0].part_start_lo = htole16(1);
-	if (last > 0xffffffff) {
-		mbr->mbr_part[0].part_size_lo = htole16(0xffff);
-		mbr->mbr_part[0].part_size_hi = htole16(0xffff);
-	} else {
-		mbr->mbr_part[0].part_size_lo = htole16(last);
-		mbr->mbr_part[0].part_size_hi = htole16(last >> 16);
-	}
-	gpt_write(fd, map);
+	gpt_create_pmbr_part(mbr->mbr_part, last);
+	gpt_write(gpt, map);
+	return 0;
 }
 
 int
-cmd_migrate(int argc, char *argv[])
+cmd_migrate(gpt_t gpt, int argc, char *argv[])
 {
-	int ch, fd;
+	int ch;
+
+	parts = 128;
 
 	/* Get the migrate options */
-	while ((ch = getopt(argc, argv, "fs")) != -1) {
+	while ((ch = getopt(argc, argv, "fp:s")) != -1) {
 		switch(ch) {
 		case 'f':
 			force = 1;
 			break;
+		case 'p':
+			parts = atoi(optarg);
+			break;
 		case 's':
 			slice = 1;
 			break;
 		default:
-			usage_migrate();
+			return usage_migrate();
 		}
 	}
 
-	if (argc == optind)
-		usage_migrate();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		migrate(fd);
-
-		gpt_close(fd);
-	}
+	if (argc != optind)
+		return usage_migrate();
 
-	return (0);
+	return migrate(gpt);
 }

Index: src/sbin/gpt/header.c
diff -u src/sbin/gpt/header.c:1.3 src/sbin/gpt/header.c:1.4
--- src/sbin/gpt/header.c:1.3	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/header.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 
 #include <sys/cdefs.h>
 #ifdef __RCSID
-__RCSID("$NetBSD: header.c,v 1.3 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: header.c,v 1.4 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,23 +47,24 @@ __RCSID("$NetBSD: header.c,v 1.3 2015/11
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
-const char headermsg[] = "header device ...";
+const char headermsg[] = "header";
 
-__dead static void
+static int
 usage_header(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), headermsg);
-	exit(1);
+	return -1;
 }
 
-static void
-header(void)
+static int
+header(gpt_t gpt)
 {
 	unsigned int revision;
-	map_t *gpt;
+	map_t map;
 	struct gpt_hdr *hdr;
 	char buf[128];
 #ifdef HN_AUTOSCALE
@@ -71,76 +72,66 @@ header(void)
 #endif
 
 #ifdef HN_AUTOSCALE
-	if (humanize_number(human_num, 5, mediasz,
+	if (humanize_number(human_num, 5, gpt->mediasz,
 	    "", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
 		human_num[0] = '\0';
 	if (human_num[0] != '\0')
-		printf("Media Size: %llu (%s)\n", (long long unsigned)mediasz,
+		printf("Media Size: %ju (%s)\n", (uintmax_t)gpt->mediasz,
 		    human_num);
 	else
 #endif
-		printf("Media Size: %llu\n", (long long unsigned)mediasz);
+		printf("Media Size: %ju\n", (uintmax_t)gpt->mediasz);
 
-	printf("Sector Size: %u\n", secsz);
+	printf("Sector Size: %u\n", gpt->secsz);
 
 #ifdef HN_AUTOSCALE
-	if (humanize_number(human_num, 5, mediasz / secsz,
+	if (humanize_number(human_num, 5, gpt->mediasz / gpt->secsz,
 	    "", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
 		human_num[0] = '\0';
 	if (human_num[0] != '\0')
-		printf("Number of Sectors: %llu (%s)\n",
-		    (long long unsigned)(mediasz / secsz), human_num);
+		printf("Number of Sectors: %ju (%s)\n",
+		    (uintmax_t)(gpt->mediasz / gpt->secsz), human_num);
 	else
 #endif
-		printf("Number of Sectors: %llu\n",
-		    (long long unsigned)(mediasz / secsz));
+		printf("Number of Sectors: %ju\n",
+		    (uintmax_t)(gpt->mediasz / gpt->secsz));
 
 	printf("\nHeader Information:\n");
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	if (gpt == NULL) {
-		printf("- GPT Header not found\n");
-		return;
+	map = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+	if (map == NULL) {
+		printf("- GPT Header not found");
+		return 0;
 	}
 
-	hdr = gpt->map_data;
+	hdr = map->map_data;
 	revision = le32toh(hdr->hdr_revision);
 	printf("- GPT Header Revision: %u.%u\n", revision >> 16,
 	     revision & 0xffff);
-	printf("- First Data Sector: %llu\n",
-	    (long long unsigned)hdr->hdr_lba_start);
+	printf("- First Data Sector: %ju\n",
+	    (uintmax_t)hdr->hdr_lba_start);
 #ifdef HN_AUTOSCALE
 	if (humanize_number(human_num, 5, hdr->hdr_lba_end,
 	    "", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
 		human_num[0] = '\0';
 	if (human_num[0] != '\0')
-		printf("- Last Data Sector: %llu (%s)\n",
-		    (long long unsigned)hdr->hdr_lba_end, human_num);
+		printf("- Last Data Sector: %ju (%s)\n",
+		    (uintmax_t)hdr->hdr_lba_end, human_num);
 	else
 #endif
-	printf("- Last Data Sector: %llu\n",
-	    (long long unsigned)hdr->hdr_lba_end);
+	printf("- Last Data Sector: %ju\n",
+	    (uintmax_t)hdr->hdr_lba_end);
 	gpt_uuid_snprintf(buf, sizeof(buf), "%d", hdr->hdr_guid);
 	printf("- Media GUID: %s\n", buf);
 	printf("- Number of GPT Entries: %u\n", hdr->hdr_entries);
+	return 0;
 }
 
 int
-cmd_header(int argc, char *argv[])
+cmd_header(gpt_t gpt, int argc, char *argv[])
 {
-	int fd;
+	if (argc != optind)
+		return usage_header();
 
-	if (argc == optind)
-		usage_header();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-		header();
-
-		gpt_close(fd);
-	}
-
-	return (0);
+	return header(gpt);
 }
Index: src/sbin/gpt/map.h
diff -u src/sbin/gpt/map.h:1.3 src/sbin/gpt/map.h:1.4
--- src/sbin/gpt/map.h:1.3	Wed Nov 20 03:08:47 2013
+++ src/sbin/gpt/map.h	Tue Dec  1 04:05:33 2015
@@ -29,7 +29,7 @@
 #ifndef _MAP_H_
 #define	_MAP_H_
 
-typedef struct map {
+struct map {
 	off_t	map_start;
 	off_t	map_size;
 	struct map *map_next;
@@ -46,19 +46,17 @@ typedef struct map {
 #define	MAP_TYPE_PMBR		8
 	unsigned int map_index;
 	void 	*map_data;
-} map_t;
+};
 
-extern int lbawidth;
+struct gpt;
 
-map_t *map_add(off_t, off_t, int, void*);
-map_t *map_alloc(off_t, off_t, off_t);
-map_t *map_find(int);
-map_t *map_first(void);
-map_t *map_last(void);
-off_t map_resize(map_t *, off_t, off_t);
-
-off_t map_free(off_t, off_t);
-
-void map_init(off_t);
+struct map *map_add(struct gpt *, off_t, off_t, int, void *);
+struct map *map_alloc(struct gpt *, off_t, off_t, off_t);
+struct map *map_find(struct gpt *, int);
+struct map *map_first(struct gpt *);
+struct map *map_last(struct gpt *);
+off_t map_resize(struct gpt *, struct map *, off_t, off_t);
+off_t map_free(struct gpt *, off_t, off_t);
+void map_init(struct gpt *, off_t);
 
 #endif /* _MAP_H_ */

Index: src/sbin/gpt/label.c
diff -u src/sbin/gpt/label.c:1.19 src/sbin/gpt/label.c:1.20
--- src/sbin/gpt/label.c:1.19	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/label.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/label.c,v 1.3 2006/10/04 18:20:25 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: label.c,v 1.19 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: label.c,v 1.20 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,6 +47,7 @@ __RCSID("$NetBSD: label.c,v 1.19 2015/11
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 #include "gpt_uuid.h"
 
 static int all;
@@ -55,12 +56,12 @@ static off_t block, size;
 static unsigned int entry;
 static uint8_t *name, *xlabel;
 
-const char labelmsg1[] = "label -a <-l label | -f file> device ...";
+const char labelmsg1[] = "label -a <-l label | -f file>";
 const char labelmsg2[] = "label [-b blocknr] [-i index] [-L label] "
 	"[-s sectors]";
-const char labelmsg3[] = "      [-t uuid] <-l label | -f file> device ...";
+const char labelmsg3[] = "      [-t uuid] <-l label | -f file>";
 
-__dead static void
+static int
 usage_label(void)
 {
 	fprintf(stderr,
@@ -68,42 +69,22 @@ usage_label(void)
 	    "       %s %s\n"
 	    "       %*s %s\n", getprogname(), labelmsg1,
 	    getprogname(), labelmsg2, (int)strlen(getprogname()), "", labelmsg3);
-	exit(1);
+	return -1;
 }
 
-static void
-label(int fd)
+static int
+label(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *m;
+	map_t m;
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	unsigned int i;
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
-
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
-
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
+	if ((hdr = gpt_hdr(gpt)) == NULL)
+		return -1;
 
 	/* Relabel all matching entries in the map. */
-	for (m = map_first(); m != NULL; m = m->map_next) {
+	for (m = map_first(gpt); m != NULL; m = m->map_next) {
 		if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
 			continue;
 		if (entry > 0 && entry != m->map_index)
@@ -115,10 +96,7 @@ label(int fd)
 
 		i = m->map_index - 1;
 
-		hdr = gpt->map_data;
-		ent = (void*)((char*)tbl->map_data + i *
-		    le32toh(hdr->hdr_entsz));
-
+		ent = gpt_ent_primary(gpt, i);
 		if (xlabel != NULL)
 			if (strcmp((char *)xlabel,
 			    (char *)utf16_to_utf8(ent->ent_name)) != 0)
@@ -131,32 +109,19 @@ label(int fd)
 		/* Label the primary entry. */
 		utf8_to_utf16(name, ent->ent_name, 36);
 
-		hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-		hdr->hdr_crc_self = 0;
-		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-		gpt_write(fd, gpt);
-		gpt_write(fd, tbl);
-
-		hdr = tpg->map_data;
-		ent = (void*)((char*)lbt->map_data + i *
-		    le32toh(hdr->hdr_entsz));
+		if (gpt_write_primary(gpt) == -1)
+			return -1;
 
+		ent = gpt_ent_backup(gpt, i);
 		/* Label the secondary entry. */
 		utf8_to_utf16(name, ent->ent_name, 36);
 
-		hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-		hdr->hdr_crc_self = 0;
-		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+		if (gpt_write_backup(gpt) == -1)
+			return -1;
 
-		gpt_write(fd, lbt);
-		gpt_write(fd, tpg);
-
-		printf("partition %d on %s labeled %s\n", m->map_index,
-		    device_name, name);
+		gpt_msg(gpt, "Partition %d labeled %s", m->map_index, name);
 	}
+	return 0;
 }
 
 static void
@@ -187,10 +152,10 @@ name_from_file(const char *fn)
 }
 
 int
-cmd_label(int argc, char *argv[])
+cmd_label(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 	int64_t human_num;
 
 	/* Get the label options */
@@ -246,27 +211,17 @@ cmd_label(int argc, char *argv[])
 				usage_label();
 			break;
 		default:
-			usage_label();
+			return usage_label();
 		}
 	}
 
 	if (!all ^
 	    (block > 0 || entry > 0 || xlabel != NULL || size > 0 ||
 	    !gpt_uuid_is_nil(type)))
-		usage_label();
-
-	if (name == NULL || argc == optind)
-		usage_label();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		label(fd);
+		return usage_label();
 
-		gpt_close(fd);
-	}
+	if (name == NULL || argc != optind)
+		return usage_label();
 
-	return (0);
+	return label(gpt);
 }

Index: src/sbin/gpt/main.c
diff -u src/sbin/gpt/main.c:1.1 src/sbin/gpt/main.c:1.2
--- src/sbin/gpt/main.c:1.1	Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/main.c	Tue Dec  1 04:05:33 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.1 2015/11/30 19:59:34 christos Exp $	*/
+/*	$NetBSD: main.c,v 1.2 2015/12/01 09:05:33 christos Exp $	*/
 
 /*-
  * Copyright (c) 2002 Marcel Moolenaar
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 #ifdef __RCSID
-__RCSID("$NetBSD: main.c,v 1.1 2015/11/30 19:59:34 christos Exp $");
+__RCSID("$NetBSD: main.c,v 1.2 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <stdio.h>
@@ -46,7 +46,7 @@ __RCSID("$NetBSD: main.c,v 1.1 2015/11/3
 #include "gpt.h"
 
 static struct {
-	int (*fptr)(int, char *[]);
+	int (*fptr)(gpt_t, int, char *[]);
 	const char *name;
 } cmdsw[] = {
 	{ cmd_add, "add" },
@@ -90,10 +90,14 @@ usage(void)
 #endif
 	const char *p = getprogname();
 	const char *f =
-	    "[-nrqv] [-m <mediasize>] [-p <partitionnum>] [-s <sectorsize>]";
+	    "[-nrqv] [-m <mediasize>] [-s <sectorsize>]";
 
-	fprintf(stderr,
-	    "Usage: %s %s <command> [<args>]\n", p, f);
+	if (strcmp(p, "gpt") == 0)
+		fprintf(stderr,
+		    "Usage: %s %s <command> [<args>] <device>\n", p, f);
+	else
+		fprintf(stderr,
+		    "Usage: %s %s <device> <command> [<args>]\n", p, f);
 	fprintf(stderr, 
 	    "Commands:\n"
 #ifndef HAVE_NBTOOL_CONFIG_H
@@ -153,11 +157,24 @@ prefix(const char *cmd)
 int
 main(int argc, char *argv[])
 {
-	char *cmd, *p;
+	char *cmd, *p, *dev = NULL;
 	int ch, i;
+	u_int secsz = 0;
+	off_t mediasz = 0;
+	int flags = 0;
+	int verbose = 0;
+	gpt_t gpt;
+
+	setprogname(argv[0]);
+
+	if (strcmp(getprogname(), "gpt") == 0) {
+		if (argc < 3)
+			usage();
+		dev = argv[--argc];
+	}
 
 	/* Get the generic options */
-	while ((ch = getopt(argc, argv, "m:np:qrs:v")) != -1) {
+	while ((ch = getopt(argc, argv, "m:nqrs:v")) != -1) {
 		switch(ch) {
 		case 'm':
 			if (mediasz > 0)
@@ -167,20 +184,13 @@ main(int argc, char *argv[])
 				usage();
 			break;
 		case 'n':
-			nosync = 1;
-			break;
-		case 'p':
-			if (parts > 0)
-				usage();
-			parts = strtoul(optarg, &p, 10);
-			if (*p != 0 || parts < 1)
-				usage();
+			flags |= GPT_NOSYNC;
 			break;
 		case 'r':
-			readonly = 1;
+			flags |= GPT_READONLY;
 			break;
 		case 'q':
-			quiet = 1;
+			flags |= GPT_QUIET;
 			break;
 		case 's':
 			if (secsz > 0)
@@ -196,18 +206,32 @@ main(int argc, char *argv[])
 			usage();
 		}
 	}
-	if (!parts)
-		parts = 128;
+
+	if (argc == optind)
+		usage();
+
+	if (dev == NULL)
+		dev = argv[optind++];
 
 	if (argc == optind)
 		usage();
 
 	cmd = argv[optind++];
-	for (i = 0; cmdsw[i].name != NULL && strcmp(cmd, cmdsw[i].name); i++);
+	for (i = 0; cmdsw[i].name != NULL && strcmp(cmd, cmdsw[i].name); i++)
+		continue;
 
 	if (cmdsw[i].fptr == NULL)
-		errx(1, "unknown command: %s", cmd);
+		errx(EXIT_FAILURE, "Unknown command: %s", cmd);
 
 	prefix(cmd);
-	return ((*cmdsw[i].fptr)(argc, argv));
+
+	gpt = gpt_open(dev, flags, verbose, mediasz, secsz);
+	if (gpt == NULL)
+		return EXIT_FAILURE;
+
+	if ((*cmdsw[i].fptr)(gpt, argc, argv) == -1)
+		return EXIT_FAILURE;
+
+	gpt_close(gpt);
+	return EXIT_SUCCESS;
 }

Index: src/sbin/gpt/map.c
diff -u src/sbin/gpt/map.c:1.10 src/sbin/gpt/map.c:1.11
--- src/sbin/gpt/map.c:1.10	Sun Nov 29 09:12:35 2015
+++ src/sbin/gpt/map.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/map.c,v 1.6 2005/08/31 01:47:19 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: map.c,v 1.10 2015/11/29 14:12:35 christos Exp $");
+__RCSID("$NetBSD: map.c,v 1.11 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -43,15 +43,12 @@ __RCSID("$NetBSD: map.c,v 1.10 2015/11/2
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
-int lbawidth;
-
-static map_t *mediamap;
-
-static map_t *
+static map_t
 mkmap(off_t start, off_t size, int type)
 {
-	map_t *m;
+	map_t m;
 
 	m = calloc(1, sizeof(*m));
 	if (m == NULL)
@@ -85,31 +82,31 @@ map_type(int t)
 	return maptypes[t];
 }
 
-map_t *
-map_add(off_t start, off_t size, int type, void *data)
+map_t
+map_add(gpt_t gpt, off_t start, off_t size, int type, void *data)
 {
-	map_t *m, *n, *p;
+	map_t m, n, p;
 
 #ifdef DEBUG
 	printf("add: %s %#jx %#jx\n", map_type(type), (uintmax_t)start,
 	    (uintmax_t)size);
-	for (n = mediamap; n; n = n->map_next)
+	for (n = gpt->mediamap; n; n = n->map_next)
 		printf("have: %s %#jx %#jx\n", map_type(n->map_type),
 		    (uintmax_t)n->map_start, (uintmax_t)n->map_size);
 #endif
 
-	n = mediamap;
+	n = gpt->mediamap;
 	while (n != NULL && n->map_start + n->map_size <= start)
 		n = n->map_next;
 	if (n == NULL) {
-		if (!quiet)
-			warnx("Can't find map");
+		if (!(gpt->flags & GPT_QUIET))
+			gpt_warnx(gpt, "Can't find map");
 		return (NULL);
 	}
 
 	if (n->map_start + n->map_size < start + size) {
-		if (!quiet)
-			warnx("map entry doesn't fit media");
+		if (!(gpt->flags & GPT_QUIET))
+			gpt_warnx(gpt, "map entry doesn't fit media");
 		return (NULL);
 	}
 
@@ -117,8 +114,8 @@ map_add(off_t start, off_t size, int typ
 		if (n->map_type != MAP_TYPE_UNUSED) {
 			if (n->map_type != MAP_TYPE_MBR_PART ||
 			    type != MAP_TYPE_GPT_PART) {
-				if (!quiet)
-					warnx("partition(%ju,%ju) mirrored",
+				if (!(gpt->flags & GPT_QUIET))
+					gpt_warnx(gpt, "partition(%ju,%ju) mirrored",
 					    (uintmax_t)start, (uintmax_t)size);
 			}
 		}
@@ -130,7 +127,7 @@ map_add(off_t start, off_t size, int typ
 	if (n->map_type != MAP_TYPE_UNUSED) {
 		if (n->map_type != MAP_TYPE_MBR_PART ||
 		    type != MAP_TYPE_GPT_PART) {
-			warnx("bogus map current=%s new=%s",
+			gpt_warnx(gpt, "bogus map current=%s new=%s",
 			    map_type(n->map_type), map_type(type));
 			return (NULL);
 		}
@@ -149,7 +146,7 @@ map_add(off_t start, off_t size, int typ
 		if (m->map_prev != NULL)
 			m->map_prev->map_next = m;
 		else
-			mediamap = m;
+			gpt->mediamap = m;
 		n->map_prev = m;
 		n->map_start += size;
 		n->map_size -= size;
@@ -173,17 +170,17 @@ map_add(off_t start, off_t size, int typ
 		if (p->map_prev != NULL)
 			p->map_prev->map_next = p;
 		else
-			mediamap = p;
+			gpt->mediamap = p;
 	}
 
 	return (m);
 }
 
-map_t *
-map_alloc(off_t start, off_t size, off_t alignment)
+map_t
+map_alloc(gpt_t gpt, off_t start, off_t size, off_t alignment)
 {
 	off_t delta;
-	map_t *m;
+	map_t m;
 
 	if (alignment > 0) {
 		if ((start % alignment) != 0)
@@ -192,7 +189,7 @@ map_alloc(off_t start, off_t size, off_t
 			size = (size + alignment) / alignment * alignment;
 	}
 
-	for (m = mediamap; m != NULL; m = m->map_next) {
+	for (m = gpt->mediamap; m != NULL; m = m->map_next) {
 		if (m->map_type != MAP_TYPE_UNUSED || m->map_start < 2)
 			continue;
 		if (start != 0 && m->map_start > start)
@@ -217,7 +214,7 @@ map_alloc(off_t start, off_t size, off_t
 				else
 					size = m->map_size - delta;
 			}
-			return map_add(m->map_start + delta, size,
+			return map_add(gpt, m->map_start + delta, size,
 				    MAP_TYPE_GPT_PART, NULL);
 		}
 	}
@@ -226,15 +223,15 @@ map_alloc(off_t start, off_t size, off_t
 }
 
 off_t
-map_resize(map_t *m, off_t size, off_t alignment)
+map_resize(gpt_t gpt, map_t m, off_t size, off_t alignment)
 {
-	map_t *n, *o;
+	map_t n, o;
 	off_t alignsize, prevsize;
 
 	n = m->map_next;
 
 	if (size < 0 || alignment < 0) {
-		warnx("negative size or alignment");
+		gpt_warnx(gpt, "negative size or alignment");
 		return 0;
 	}
 	if (size == 0 && alignment == 0) {
@@ -319,40 +316,40 @@ map_resize(map_t *m, off_t size, off_t a
 		return alignsize;
 }
 
-map_t *
-map_find(int type)
+map_t
+map_find(gpt_t gpt, int type)
 {
-	map_t *m;
+	map_t m;
 
-	m = mediamap;
+	m = gpt->mediamap;
 	while (m != NULL && m->map_type != type)
 		m = m->map_next;
 	return (m);
 }
 
-map_t *
-map_first(void)
+map_t
+map_first(gpt_t gpt)
 {
-	return mediamap;
+	return gpt->mediamap;
 }
 
-map_t *
-map_last(void)
+map_t
+map_last(gpt_t gpt)
 {
-	map_t *m;
+	map_t m;
 
-	m = mediamap;
+	m = gpt->mediamap;
 	while (m != NULL && m->map_next != NULL)
 		m = m->map_next;
 	return (m);
 }
 
 off_t
-map_free(off_t start, off_t size)
+map_free(gpt_t gpt, off_t start, off_t size)
 {
-	map_t *m;
+	map_t m;
 
-	m = mediamap;
+	m = gpt->mediamap;
 
 	while (m != NULL && m->map_start + m->map_size <= start)
 		m = m->map_next;
@@ -364,12 +361,12 @@ map_free(off_t start, off_t size)
 }
 
 void
-map_init(off_t size)
+map_init(gpt_t gpt, off_t size)
 {
 	char buf[32];
 
-	mediamap = mkmap(0LL, size, MAP_TYPE_UNUSED);
-	lbawidth = snprintf(buf, sizeof(buf), "%ju", (uintmax_t)size);
-	if (lbawidth < 5)
-		lbawidth = 5;
+	gpt->mediamap = mkmap(0LL, size, MAP_TYPE_UNUSED);
+	gpt->lbawidth = snprintf(buf, sizeof(buf), "%ju", (uintmax_t)size);
+	if (gpt->lbawidth < 5)
+		gpt->lbawidth = 5;
 }

Index: src/sbin/gpt/remove.c
diff -u src/sbin/gpt/remove.c:1.17 src/sbin/gpt/remove.c:1.18
--- src/sbin/gpt/remove.c:1.17	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/remove.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: remove.c,v 1.17 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: remove.c,v 1.18 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,6 +47,7 @@ __RCSID("$NetBSD: remove.c,v 1.17 2015/1
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static int all;
 static gpt_uuid_t type;
@@ -54,11 +55,11 @@ static off_t block, size;
 static unsigned int entry;
 static uint8_t *label;
 
-const char removemsg1[] = "remove -a device ...";
+const char removemsg1[] = "remove -a";
 const char removemsg2[] = "remove [-b blocknr] [-i index] [-L label] "
-	"[-s sectors] [-t type] device ...";
+	"[-s sectors] [-t type]";
 
-__dead static void
+static int
 usage_remove(void)
 {
 
@@ -66,42 +67,21 @@ usage_remove(void)
 	    "usage: %s %s\n"
 	    "       %s %s\n",
 	    getprogname(), removemsg1, getprogname(), removemsg2);
-	exit(1);
+	return -1;
 }
 
-static void
-rem(int fd)
+static int
+rem(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *m;
-	struct gpt_hdr *hdr;
+	map_t m;
 	struct gpt_ent *ent;
 	unsigned int i;
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
-
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
-
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
+	if (gpt_hdr(gpt) == NULL)
+		return -1;
 
 	/* Remove all matching entries in the map. */
-	for (m = map_first(); m != NULL; m = m->map_next) {
+	for (m = map_first(gpt); m != NULL; m = m->map_next) {
 		if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
 			continue;
 		if (entry > 0 && entry != m->map_index)
@@ -113,9 +93,7 @@ rem(int fd)
 
 		i = m->map_index - 1;
 
-		hdr = gpt->map_data;
-		ent = (void*)((char*)tbl->map_data + i *
-		    le32toh(hdr->hdr_entsz));
+		ent = gpt_ent_primary(gpt, i);
 
 		if (label != NULL)
 			if (strcmp((char *)label,
@@ -129,38 +107,26 @@ rem(int fd)
 		/* Remove the primary entry by clearing the partition type. */
 		gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
 
-		hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-		hdr->hdr_crc_self = 0;
-		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-		gpt_write(fd, gpt);
-		gpt_write(fd, tbl);
-
-		hdr = tpg->map_data;
-		ent = (void*)((char*)lbt->map_data + i *
-		    le32toh(hdr->hdr_entsz));
+		if (gpt_write_primary(gpt) == -1)
+			return -1;
+
+		ent = gpt_ent_backup(gpt, i);
 
 		/* Remove the secondary entry. */
 		gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
 
-		hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-		    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-		hdr->hdr_crc_self = 0;
-		hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-		gpt_write(fd, lbt);
-		gpt_write(fd, tpg);
-		printf("partition %d removed from %s\n", m->map_index,
-		    device_name);
+		if (gpt_write_backup(gpt) == -1)
+			return -1;
+		gpt_msg(gpt, "partition %d removed", m->map_index);
 	}
+	return 0;
 }
 
 int
-cmd_remove(int argc, char *argv[])
+cmd_remove(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 	int64_t human_num;
 
 	/* Get the remove options */
@@ -168,28 +134,28 @@ cmd_remove(int argc, char *argv[])
 		switch(ch) {
 		case 'a':
 			if (all > 0)
-				usage_remove();
+				return usage_remove();
 			all = 1;
 			break;
 		case 'b':
 			if (block > 0)
-				usage_remove();
+				return usage_remove();
 			if (dehumanize_number(optarg, &human_num) < 0)
-				usage_remove();
+				return usage_remove();
 			block = human_num;
 			if (block < 1)
-				usage_remove();
+				return usage_remove();
 			break;
 		case 'i':
 			if (entry > 0)
-				usage_remove();
+				return usage_remove();
 			entry = strtoul(optarg, &p, 10);
 			if (*p != 0 || entry < 1)
-				usage_remove();
+				return usage_remove();
 			break;
 		case 'L':
 			if (label != NULL)
-				usage_remove();
+				return usage_remove();
 			label = (uint8_t *)strdup(optarg);
 			break;
 		case 's':
@@ -197,36 +163,26 @@ cmd_remove(int argc, char *argv[])
 				usage_remove();
 			size = strtoll(optarg, &p, 10);
 			if (*p != 0 || size < 1)
-				usage_remove();
+				return usage_remove();
 			break;
 		case 't':
 			if (!gpt_uuid_is_nil(type))
-				usage_remove();
+				return usage_remove();
 			if (gpt_uuid_parse(optarg, type) != 0)
-				usage_remove();
+				return usage_remove();
 			break;
 		default:
-			usage_remove();
+			return usage_remove();
 		}
 	}
 
 	if (!all ^
 	    (block > 0 || entry > 0 || label != NULL || size > 0 ||
 	    !gpt_uuid_is_nil(type)))
-		usage_remove();
+		return usage_remove();
 
-	if (argc == optind)
-		usage_remove();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		rem(fd);
-
-		gpt_close(fd);
-	}
+	if (argc != optind)
+		return usage_remove();
 
-	return (0);
+	return rem(gpt);
 }

Index: src/sbin/gpt/resize.c
diff -u src/sbin/gpt/resize.c:1.14 src/sbin/gpt/resize.c:1.15
--- src/sbin/gpt/resize.c:1.14	Mon Nov 30 21:03:55 2015
+++ src/sbin/gpt/resize.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: resize.c,v 1.14 2015/12/01 02:03:55 christos Exp $");
+__RCSID("$NetBSD: resize.c,v 1.15 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,167 +47,129 @@ __RCSID("$NetBSD: resize.c,v 1.14 2015/1
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static off_t alignment, sectors, size;
 static unsigned int entry;
 
-const char resizemsg[] = "resize -i index [-a alignment] [-s size] device ...";
+const char resizemsg[] = "resize -i index [-a alignment] [-s size]";
 
-__dead static void
+static int
 usage_resize(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), resizemsg);
-	exit(1);
+	return -1;
 }
 
-static void
-resize(int fd)
+static int
+resize(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
-	map_t *map;
+	map_t map;
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	unsigned int i;
 	off_t alignsecs, newsize;
 	
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	ent = NULL;
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
-
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
-
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
+	if ((hdr = gpt_hdr(gpt)) == NULL)
+		return -1;
 
-	hdr = gpt->map_data;
-	if (entry > le32toh(hdr->hdr_entries)) {
-		warnx("%s: error: index %u out of range (%u max)", device_name,
-		    entry, le32toh(hdr->hdr_entries));
-		return;
-	}
+	ent = NULL;
 
 	i = entry - 1;
-	ent = (void*)((char*)tbl->map_data + i *
-	    le32toh(hdr->hdr_entsz));
+	ent = gpt_ent_primary(gpt, i);
 	if (gpt_uuid_is_nil(ent->ent_type)) {
-		warnx("%s: error: entry at index %u is unused",
-		    device_name, entry);
-		return;
+		gpt_warnx(gpt, "Entry at index %u is unused", entry);
+		return -1;
 	}
 
-	alignsecs = alignment / secsz;
+	alignsecs = alignment / gpt->secsz;
 
-	for (map = map_first(); map != NULL; map = map->map_next) {
+	for (map = map_first(gpt); map != NULL; map = map->map_next) {
 		if (entry == map->map_index)
 			break;
 	}
 	if (map == NULL) {
-		warnx("%s: error: could not find map entry corresponding "
-		      "to index", device_name);
-		return;
+		gpt_warnx(gpt, "Could not find map entry corresponding "
+		    "to index");
+		return -1;
 	}
 
 	if (sectors > 0 && sectors == map->map_size)
 		if (alignment == 0 ||
 		    (alignment > 0 && sectors % alignsecs == 0)) {
 			/* nothing to do */
-			warnx("%s: partition does not need resizing",
-			    device_name);
-			return;
+			gpt_warnx(gpt, "partition does not need resizing");
+			return 0;
 		}
 
-	newsize = map_resize(map, sectors, alignsecs);
+	newsize = map_resize(gpt, map, sectors, alignsecs);
 	if (newsize == 0 && alignment > 0) {
-		warnx("%s: could not resize partition with alignment "
-		      "constraint", device_name);
-		return;
+		gpt_warnx(gpt, "Could not resize partition with alignment "
+		      "constraint");
+		return -1;
 	} else if (newsize == 0) {
-		warnx("%s: could not resize partition", device_name);
-		return;
+		gpt_warnx(gpt, "Could not resize partition");
+		return -1;
 	}
 
 	ent->ent_lba_end = htole64(map->map_start + newsize - 1LL);
 
-	hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, gpt);
-	gpt_write(fd, tbl);
-
-	hdr = tpg->map_data;
-	ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
+	if (gpt_write_primary(gpt) == -1)
+		return -1;
 
+	ent = gpt_ent(gpt->gpt, gpt->lbt, i);
 	ent->ent_lba_end = htole64(map->map_start + newsize - 1LL);
 
-	hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+	if (gpt_write_backup(gpt) == -1)
+		return -1;
 
-	gpt_write(fd, lbt);
-	gpt_write(fd, tpg);
-
-	gpt_msg("Partition %d resized: %" PRIu64 " %" PRIu64 "\n", entry,
+	gpt_msg(gpt, "Partition %d resized: %" PRIu64 " %" PRIu64 "\n", entry,
 	    map->map_start, newsize);
+
+	return 0;
 }
 
 int
-cmd_resize(int argc, char *argv[])
+cmd_resize(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 	int64_t human_num;
 
 	while ((ch = getopt(argc, argv, "a:i:s:")) != -1) {
 		switch(ch) {
 		case 'a':
 			if (alignment > 0)
-				usage_resize();
+				return usage_resize();
 			if (dehumanize_number(optarg, &human_num) < 0)
-				usage_resize();
+				return usage_resize();
 			alignment = human_num;
 			if (alignment < 1)
-				usage_resize();
+				return usage_resize();
 			break;
 		case 'i':
 			if (entry > 0)
-				usage_resize();
+				return usage_resize();
 			entry = strtoul(optarg, &p, 10);
 			if (*p != 0 || entry < 1)
-				usage_resize();
+				return usage_resize();
 			break;
 		case 's':
 			if (sectors > 0 || size > 0)
-				usage_resize();
+				return usage_resize();
 			sectors = strtoll(optarg, &p, 10);
 			if (sectors < 1)
-				usage_resize();
+				return usage_resize();
 			if (*p == '\0')
 				break;
 			if (*p == 's' || *p == 'S') {
 				if (*(p + 1) == '\0')
 					break;
 				else
-					usage_resize();
+					return usage_resize();
 			}
 			if (*p == 'b' || *p == 'B') {
 				if (*(p + 1) == '\0') {
@@ -215,50 +177,26 @@ cmd_resize(int argc, char *argv[])
 					sectors = 0;
 					break;
 				} else
-					usage_resize();
+					return usage_resize();
 			}
 			if (dehumanize_number(optarg, &human_num) < 0)
-				usage_resize();
+				return usage_resize();
 			size = human_num;
 			sectors = 0;
 			break;
 		default:
-			usage_resize();
+			return usage_resize();
 		}
 	}
 
-	if (argc == optind)
-		usage_resize();
+	if (argc != optind)
+		return usage_resize();
 
 	if (entry == 0)
-		usage_resize();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		if (alignment % secsz != 0) {
-			warnx("Alignment must be a multiple of sector size;");
-			warnx("the sector size for %s is %d bytes.",
-			    device_name, secsz);
-			continue;
-		}
+		return usage_resize();
 
-		if (size % secsz != 0) {
-			warnx("Size in bytes must be a multiple of sector "
-			      "size;");
-			warnx("the sector size for %s is %d bytes.",
-			    device_name, secsz);
-			continue;
-		}
-		if (size > 0)
-			sectors = size / secsz;
-
-		resize(fd);
+	if ((sectors = gpt_check(gpt, alignment, size)) == -1)
+		return -1;
 
-		gpt_close(fd);
-	}
-
-	return 0;
+	return resize(gpt);
 }

Index: src/sbin/gpt/set.c
diff -u src/sbin/gpt/set.c:1.6 src/sbin/gpt/set.c:1.7
--- src/sbin/gpt/set.c:1.6	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/set.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: set.c,v 1.6 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: set.c,v 1.7 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,99 +47,67 @@ __RCSID("$NetBSD: set.c,v 1.6 2015/11/29
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static unsigned int entry;
 static uint64_t attributes;
 
-const char setmsg[] = "set -a attribute -i index device ...";
+const char setmsg[] = "set -a attribute -i index";
 
-__dead static void
+static int
 usage_set(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), setmsg);
-	exit(1);
+	return -1;
 }
 
-static void
-set(int fd)
+static int
+set(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	unsigned int i;
 	
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	ent = NULL;
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
-
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
+	if ((hdr = gpt_hdr(gpt)) == NULL)
+		return -1;
 
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
 
-	hdr = gpt->map_data;
 	if (entry > le32toh(hdr->hdr_entries)) {
-		warnx("%s: error: index %u out of range (%u max)", device_name,
+		gpt_warnx(gpt, "Index %u out of range (%u max)",
 		    entry, le32toh(hdr->hdr_entries));
-		return;
+		return -1;
 	}
 
 	i = entry - 1;
-	ent = (void*)((char*)tbl->map_data + i *
-	    le32toh(hdr->hdr_entsz));
+	ent = gpt_ent_primary(gpt, i);
 	if (gpt_uuid_is_nil(ent->ent_type)) {
-		warnx("%s: error: entry at index %u is unused",
-		    device_name, entry);
-		return;
+		gpt_warnx(gpt, "Entry at index %u is unused", entry);
+		return -1;
 	}
 
 	ent->ent_attr |= attributes;
 
-	hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, gpt);
-	gpt_write(fd, tbl);
+	if (gpt_write_primary(gpt) == -1)
+		return -1;
 
-	hdr = tpg->map_data;
-	ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
+	ent = gpt_ent_backup(gpt, i);
 	ent->ent_attr |= attributes;
 
-	hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, lbt);
-	gpt_write(fd, tpg);
+	if (gpt_write_backup(gpt) == -1)
+		return -1;
 
-	printf("Partition %d attributes updated\n", entry);
+	gpt_msg(gpt, "Partition %d attributes updated", entry);
+	return 0;
 }
 
 int
-cmd_set(int argc, char *argv[])
+cmd_set(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 
 	while ((ch = getopt(argc, argv, "a:i:")) != -1) {
 		switch(ch) {
@@ -163,25 +131,15 @@ cmd_set(int argc, char *argv[])
 				usage_set();
 			break;
 		default:
-			usage_set();
+			return usage_set();
 		}
 	}
 
-	if (argc == optind)
-		usage_set();
+	if (argc != optind)
+		return usage_set();
 
 	if (entry == 0 || attributes == 0)
-		usage_set();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		set(fd);
+		return usage_set();
 
-		gpt_close(fd);
-	}
-
-	return 0;
+	return set(gpt);
 }
Index: src/sbin/gpt/unset.c
diff -u src/sbin/gpt/unset.c:1.6 src/sbin/gpt/unset.c:1.7
--- src/sbin/gpt/unset.c:1.6	Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/unset.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: unset.c,v 1.6 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: unset.c,v 1.7 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,99 +47,65 @@ __RCSID("$NetBSD: unset.c,v 1.6 2015/11/
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static unsigned int entry;
 static uint64_t attributes;
 
-const char unsetmsg[] = "unset -a attribute -i index device ...";
+const char unsetmsg[] = "unset -a attribute -i index";
 
-__dead static void
+static int
 usage_unset(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), unsetmsg);
-	exit(1);
+	return -1;
 }
 
-static void
-unset(int fd)
+static int
+unset(gpt_t gpt)
 {
-	map_t *gpt, *tpg;
-	map_t *tbl, *lbt;
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	unsigned int i;
 	
 
-	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
-	ent = NULL;
-	if (gpt == NULL) {
-		warnx("%s: error: no primary GPT header; run create or recover",
-		    device_name);
-		return;
-	}
-
-	tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-	if (tpg == NULL) {
-		warnx("%s: error: no secondary GPT header; run recover",
-		    device_name);
-		return;
-	}
+	if ((hdr = gpt_hdr(gpt)) == NULL)
+		return -1;
 
-	tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
-	lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-	if (tbl == NULL || lbt == NULL) {
-		warnx("%s: error: run recover -- trust me", device_name);
-		return;
-	}
-
-	hdr = gpt->map_data;
 	if (entry > le32toh(hdr->hdr_entries)) {
-		warnx("%s: error: index %u out of range (%u max)", device_name,
+		gpt_warnx(gpt, "Index %u out of range (%u max)",
 		    entry, le32toh(hdr->hdr_entries));
-		return;
+		return -1;
 	}
 
 	i = entry - 1;
-	ent = (void*)((char*)tbl->map_data + i *
-	    le32toh(hdr->hdr_entsz));
+	ent = gpt_ent_primary(gpt, i);
 	if (gpt_uuid_is_nil(ent->ent_type)) {
-		warnx("%s: error: entry at index %u is unused",
-		    device_name, entry);
-		return;
+		gpt_warnx(gpt, "Entry at index %u is unused", entry);
+		return -1;
 	}
 
 	ent->ent_attr &= ~attributes;
 
-	hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, gpt);
-	gpt_write(fd, tbl);
+	if (gpt_write_primary(gpt) == -1)
+		return -1;
 
-	hdr = tpg->map_data;
-	ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
+	ent = gpt_ent_backup(gpt, i);
 	ent->ent_attr &= ~attributes;
 
-	hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
-	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
-	hdr->hdr_crc_self = 0;
-	hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
-	gpt_write(fd, lbt);
-	gpt_write(fd, tpg);
-
-	printf("Partition %d attributes updated\n", entry);
+	if (gpt_write_backup(gpt) == -1)
+		return -1;
+	gpt_msg(gpt, "Partition %d attributes updated", entry);
+	return 0;
 }
 
 int
-cmd_unset(int argc, char *argv[])
+cmd_unset(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 
 	while ((ch = getopt(argc, argv, "a:i:")) != -1) {
 		switch(ch) {
@@ -153,35 +119,25 @@ cmd_unset(int argc, char *argv[])
 			else if (strcmp(optarg, "bootfailed") == 0)
 				attributes |= GPT_ENT_ATTR_BOOTFAILED;
 			else
-				usage_unset();
+				return usage_unset();
 			break;
 		case 'i':
 			if (entry > 0)
-				usage_unset();
+				return usage_unset();
 			entry = strtoul(optarg, &p, 10);
 			if (*p != 0 || entry < 1)
-				usage_unset();
+				return usage_unset();
 			break;
 		default:
-			usage_unset();
+			return usage_unset();
 		}
 	}
 
-	if (argc == optind)
-		usage_unset();
+	if (argc != optind)
+		return usage_unset();
 
 	if (entry == 0 || attributes == 0)
-		usage_unset();
-
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		unset(fd);
+		return usage_unset();
 
-		gpt_close(fd);
-	}
-
-	return 0;
+	return unset(gpt);
 }

Index: src/sbin/gpt/show.c
diff -u src/sbin/gpt/show.c:1.23 src/sbin/gpt/show.c:1.24
--- src/sbin/gpt/show.c:1.23	Sun Nov 29 09:12:56 2015
+++ src/sbin/gpt/show.c	Tue Dec  1 04:05:33 2015
@@ -33,7 +33,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: show.c,v 1.23 2015/11/29 14:12:56 christos Exp $");
+__RCSID("$NetBSD: show.c,v 1.24 2015/12/01 09:05:33 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -47,40 +47,41 @@ __RCSID("$NetBSD: show.c,v 1.23 2015/11/
 
 #include "map.h"
 #include "gpt.h"
+#include "gpt_private.h"
 
 static int show_label = 0;
 static int show_uuid = 0;
 static int show_guid = 0;
 static unsigned int entry = 0;
 
-const char showmsg[] = "show [-glu] [-i index] device ...";
+const char showmsg[] = "show [-glu] [-i index] device";
 
-__dead static void
+static int
 usage_show(void)
 {
 
 	fprintf(stderr,
 	    "usage: %s %s\n", getprogname(), showmsg);
-	exit(1);
+	return -1;
 }
 
-static void
-show(void)
+static int
+show(gpt_t gpt)
 {
 	off_t start;
-	map_t *m, *p;
+	map_t m, p;
 	struct mbr *mbr;
 	struct gpt_ent *ent;
 	unsigned int i;
 
-	printf("  %*s", lbawidth, "start");
-	printf("  %*s", lbawidth, "size");
+	printf("  %*s", gpt->lbawidth, "start");
+	printf("  %*s", gpt->lbawidth, "size");
 	printf("  index  contents\n");
 
-	m = map_first();
+	m = map_first(gpt);
 	while (m != NULL) {
-		printf("  %*llu", lbawidth, (long long)m->map_start);
-		printf("  %*llu", lbawidth, (long long)m->map_size);
+		printf("  %*llu", gpt->lbawidth, (long long)m->map_start);
+		printf("  %*llu", gpt->lbawidth, (long long)m->map_size);
 		putchar(' ');
 		putchar(' ');
 		if (m->map_index > 0)
@@ -155,31 +156,31 @@ show(void)
 		putchar('\n');
 		m = m->map_next;
 	}
+	return 0;
 }
 
-static void
-show_one(void)
+static int
+show_one(gpt_t gpt)
 {
-	map_t *m;
+	map_t m;
 	struct gpt_ent *ent;
 	char s1[128], s2[128];
 #ifdef HN_AUTOSCALE
 	char human_num[5];
 #endif
 
-	for (m = map_first(); m != NULL; m = m->map_next)
+	for (m = map_first(gpt); m != NULL; m = m->map_next)
 		if (entry == m->map_index)
 			break;
 	if (m == NULL) {
-		warnx("%s: error: could not find index %d",
-		    device_name, entry);
-		return;
+		gpt_warnx(gpt, "Could not find index %d", entry);
+		return -1;
 	}
 	ent = m->map_data;
 
 	printf("Details for index %d:\n", entry);
 #ifdef HN_AUTOSCALE
-	if (humanize_number(human_num, 5, (int64_t)(m->map_start * secsz),
+	if (humanize_number(human_num, 5, (int64_t)(m->map_start * gpt->secsz),
 	    "", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
 		human_num[0] = '\0';
 	if (human_num[0] != '\0')
@@ -189,7 +190,7 @@ show_one(void)
 #endif
 		printf("Start: %llu\n", (long long)m->map_start);
 #ifdef HN_AUTOSCALE
-	if (humanize_number(human_num, 5, (int64_t)(m->map_size * secsz),
+	if (humanize_number(human_num, 5, (int64_t)(m->map_size * gpt->secsz),
 	    "", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
 		human_num[0] = '\0';
 	if (human_num[0] != '\0')
@@ -226,13 +227,14 @@ show_one(void)
 		if (ent->ent_attr & GPT_ENT_ATTR_BOOTFAILED)
 			printf("  partition that was marked bootonce but failed to boot\n");
 	}
+	return 0;
 }
 
 int
-cmd_show(int argc, char *argv[])
+cmd_show(gpt_t gpt, int argc, char *argv[])
 {
 	char *p;
-	int ch, fd;
+	int ch;
 
 	while ((ch = getopt(argc, argv, "gi:lu")) != -1) {
 		switch(ch) {
@@ -241,10 +243,10 @@ cmd_show(int argc, char *argv[])
 			break;
 		case 'i':
 			if (entry > 0)
-				usage_show();
+				return usage_show();
 			entry = strtoul(optarg, &p, 10);
 			if (*p != 0 || entry < 1)
-				usage_show();
+				return usage_show();
 			break;
 		case 'l':
 			show_label = 1;
@@ -253,25 +255,12 @@ cmd_show(int argc, char *argv[])
 			show_uuid = 1;
 			break;
 		default:
-			usage_show();
+			return usage_show();
 		}
 	}
 
-	if (argc == optind)
-		usage_show();
+	if (argc != optind)
+		return usage_show();
 
-	while (optind < argc) {
-		fd = gpt_open(argv[optind++], 0);
-		if (fd == -1)
-			continue;
-
-		if (entry > 0)
-			show_one();
-		else
-			show();
-
-		gpt_close(fd);
-	}
-
-	return (0);
+	return entry > 0 ? show_one(gpt) : show(gpt);
 }

Added files:

Index: src/sbin/gpt/gpt_private.h
diff -u /dev/null src/sbin/gpt/gpt_private.h:1.1
--- /dev/null	Tue Dec  1 04:05:33 2015
+++ src/sbin/gpt/gpt_private.h	Tue Dec  1 04:05:33 2015
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+struct gpt {
+	char device_name[MAXPATHLEN];
+	int fd;
+	int flags;
+	int verbose;
+	int lbawidth;
+	struct map *mediamap;
+	struct map *tbl, *lbt, *gpt, *tpg;
+	u_int secsz;
+	off_t mediasz;
+	struct stat sb;
+};

Reply via email to