Module Name:    src
Committed By:   christos
Date:           Tue Dec  1 19:25:24 UTC 2015

Modified Files:
        src/sbin/gpt: add.c create.c gpt.c gpt.h label.c migrate.c remove.c
            resize.c resizedisk.c set.c type.c unset.c

Log Message:
refactor more duplicated code.


To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/sbin/gpt/add.c
cvs rdiff -u -r1.15 -r1.16 src/sbin/gpt/create.c
cvs rdiff -u -r1.50 -r1.51 src/sbin/gpt/gpt.c
cvs rdiff -u -r1.24 -r1.25 src/sbin/gpt/gpt.h src/sbin/gpt/migrate.c
cvs rdiff -u -r1.21 -r1.22 src/sbin/gpt/label.c
cvs rdiff -u -r1.19 -r1.20 src/sbin/gpt/remove.c
cvs rdiff -u -r1.16 -r1.17 src/sbin/gpt/resize.c
cvs rdiff -u -r1.9 -r1.10 src/sbin/gpt/resizedisk.c src/sbin/gpt/type.c
cvs rdiff -u -r1.8 -r1.9 src/sbin/gpt/set.c src/sbin/gpt/unset.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/add.c
diff -u src/sbin/gpt/add.c:1.32 src/sbin/gpt/add.c:1.33
--- src/sbin/gpt/add.c:1.32	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/add.c	Tue Dec  1 14:25:24 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: add.c,v 1.32 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: add.c,v 1.33 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -79,6 +79,7 @@ add(gpt_t gpt)
 	struct gpt_ent *ent, e;
 	unsigned int i;
 	off_t alignsecs;
+	char buf[128];
 	
 	if ((hdr = gpt_hdr(gpt)) == NULL)
 		return -1;
@@ -141,29 +142,20 @@ add(gpt_t gpt)
 	memcpy(ent, &e, sizeof(e));
 	gpt_write_backup(gpt);
 
-	gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64 "\n", i + 1,
-	    type, map->map_start, map->map_size);
+	gpt_uuid_snprintf(buf, sizeof(buf), "%d", type);
+	gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64, i + 1,
+	    buf, map->map_start, map->map_size);
 	return 0;
 }
 
 static int
 cmd_add(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
 	int64_t human_num;
 
-	while ((ch = getopt(argc, argv, "a:b:i:l:s:t:")) != -1) {
+	while ((ch = getopt(argc, argv, GPT_AIS "bl:t:")) != -1) {
 		switch(ch) {
-		case 'a':
-			if (alignment > 0)
-				return usage();
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			alignment = human_num;
-			if (alignment < 1)
-				return usage();
-			break;
 		case 'b':
 			if (block > 0)
 				return usage();
@@ -173,45 +165,11 @@ cmd_add(gpt_t gpt, int argc, char *argv[
 			if (block < 1)
 				return usage();
 			break;
-		case 'i':
-			if (entry > 0)
-				usage();
-			entry = strtoul(optarg, &p, 10);
-			if (*p != 0 || entry < 1)
-				return usage();
-			break;
 		case 'l':
 			if (name != NULL)
 				return usage();
 			name = (uint8_t *)strdup(optarg);
 			break;
-		case 's':
-			if (sectors > 0 || size > 0)
-				return usage();
-			sectors = strtoll(optarg, &p, 10);
-			if (sectors < 1)
-				return usage();
-			if (*p == '\0')
-				break;
-			if (*p == 's' || *p == 'S') {
-				if (*(p + 1) == '\0')
-					break;
-				else
-					return usage();
-			}
-			if (*p == 'b' || *p == 'B') {
-				if (*(p + 1) == '\0') {
-					size = sectors;
-					sectors = 0;
-					break;
-				} else
-					return usage();
-			}
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			size = human_num;
-			sectors = 0;
-			break;
 		case 't':
 			if (!gpt_uuid_is_nil(type))
 				return usage();
@@ -219,11 +177,14 @@ cmd_add(gpt_t gpt, int argc, char *argv[
 				return usage();
 			break;
 		default:
-			return usage();
+			if (gpt_add_ais(gpt, &alignment, &entry, &size, ch)
+			    == -1)
+				return usage();
+			break;
 		}
 	}
 
-	if (argc == optind)
+	if (argc != optind)
 		return usage();
 
 	/* Create NetBSD FFS partitions by default. */
@@ -234,7 +195,7 @@ cmd_add(gpt_t gpt, int argc, char *argv[
 	if (optind != argc)
 		return usage();
 
-	if ((sectors = gpt_check(gpt, alignment, size)) == -1)
+	if ((sectors = gpt_check_ais(gpt, alignment, entry, size)) == -1)
 		return -1;
 
 	return add(gpt);

Index: src/sbin/gpt/create.c
diff -u src/sbin/gpt/create.c:1.15 src/sbin/gpt/create.c:1.16
--- src/sbin/gpt/create.c:1.15	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/create.c	Tue Dec  1 14:25:24 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: create.c,v 1.15 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: create.c,v 1.16 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -74,21 +74,10 @@ struct gpt_cmd c_create = {
 static int
 create(gpt_t gpt)
 {
-	off_t blocks, last;
+	off_t last = gpt_last(gpt);
 	map_t map;
 	struct mbr *mbr;
-	struct gpt_hdr *hdr;
-	struct gpt_ent *ent;
-	unsigned int i;
-	void *p;
-
-	last = gpt->mediasz / gpt->secsz - 1LL;
-
-	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(gpt, MAP_TYPE_MBR);
 	if (map != NULL) {
 		if (!force) {
@@ -117,110 +106,21 @@ create(gpt_t gpt)
 		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(gpt, 1LL, 0LL);
-	if (blocks == 0LL) {
-		gpt_warnx(gpt, "No room for the GPT header");
-		return -1;
-	}
-
-	/* Don't create more than parts entries. */
-	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 */
-	}
-
-	/* Never cross the median of the device. */
-	if ((blocks + 1LL) > ((last + 1LL) >> 1))
-		blocks = ((last + 1LL) >> 1) - 1LL;
-
-	/*
-	 * Get the amount of free space at the end of the device and
-	 * calculate the size for the GPT structures.
-	 */
-	map = map_last(gpt);
-	if (map->map_type != MAP_TYPE_UNUSED) {
-		gpt_warnx(gpt, "No room for the backup header");
-		return -1;
-	}
-
-	if (map->map_size < blocks)
-		blocks = map->map_size;
-	if (blocks == 1LL) {
-		gpt_warnx(gpt, "No room for the GPT table");
-		return -1;
+		if (gpt_write(gpt, map) == -1) {
+			gpt_warn(gpt, "Can't write PMBR");
+			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");
+	if (gpt_create(gpt, last, parts, primary_only) == -1)
 		return -1;
-	}
 
-	blocks--;		/* Number of blocks in the GPT table. */
-	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");
+	if (gpt_write_primary(gpt) == -1)
 		return -1;
-	}
-
-	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->gpt->map_start);
-	hdr->hdr_lba_alt = htole64(last);
-	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(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 = gpt->tbl->map_data;
-	for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
-		gpt_uuid_generate(ent[i].ent_guid);
-	}
 
-	if (gpt_write_primary(gpt) == -1)
+	if (!primary_only && gpt_write_backup(gpt) == -1)
 		return -1;
 
-	/*
-	 * Create backup GPT if the user didn't suppress it.
-	 */
-	if (!primary_only) {
-		// 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;
 }
 

Index: src/sbin/gpt/gpt.c
diff -u src/sbin/gpt/gpt.c:1.50 src/sbin/gpt/gpt.c:1.51
--- src/sbin/gpt/gpt.c:1.50	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/gpt.c	Tue Dec  1 14:25:24 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.50 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: gpt.c,v 1.51 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/param.h>
@@ -712,24 +712,7 @@ gpt_create_pmbr_part(struct mbr_part *pa
 	}
 }
 
-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)
 {
@@ -770,3 +753,392 @@ gpt_usage(const char *prefix, const stru
 	}
 	return -1;
 }
+
+off_t
+gpt_last(gpt_t gpt)
+{
+	return gpt->mediasz / gpt->secsz - 1LL;
+}
+
+int
+gpt_create(gpt_t gpt, off_t last, u_int parts, int primary_only)
+{
+	off_t blocks;
+	map_t map;
+	struct gpt_hdr *hdr;
+	struct gpt_ent *ent;
+	unsigned int i;
+	void *p;
+
+	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(gpt, 1LL, 0LL);
+	if (blocks == 0LL) {
+		gpt_warnx(gpt, "No room for the GPT header");
+		return -1;
+	}
+
+	/* Don't create more than parts entries. */
+	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 */
+	}
+
+	/* Never cross the median of the device. */
+	if ((blocks + 1LL) > ((last + 1LL) >> 1))
+		blocks = ((last + 1LL) >> 1) - 1LL;
+
+	/*
+	 * Get the amount of free space at the end of the device and
+	 * calculate the size for the GPT structures.
+	 */
+	map = map_last(gpt);
+	if (map->map_type != MAP_TYPE_UNUSED) {
+		gpt_warnx(gpt, "No room for the backup header");
+		return -1;
+	}
+
+	if (map->map_size < blocks)
+		blocks = map->map_size;
+	if (blocks == 1LL) {
+		gpt_warnx(gpt, "No room for the GPT table");
+		return -1;
+	}
+
+	blocks--;		/* Number of blocks in the GPT table. */
+
+	if ((p = calloc(1, gpt->secsz)) == NULL) {
+		gpt_warnx(gpt, "Can't allocate the primary 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 primary GPT");
+		return -1;
+	}
+
+	if ((p = calloc(blocks, gpt->secsz)) == NULL) {
+		gpt_warnx(gpt, "Can't allocate the primary 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 primary GPT table");
+		return -1;
+	}
+
+	hdr = gpt->gpt->map_data;
+	memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
+
+	/*
+	 * 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_revision = htole32(GPT_HDR_REVISION);
+	hdr->hdr_size = htole32(GPT_HDR_SIZE);
+	hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
+	hdr->hdr_lba_alt = htole64(last);
+	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(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 = gpt->tbl->map_data;
+	for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
+		gpt_uuid_generate(ent[i].ent_guid);
+	}
+
+	/*
+	 * Create backup GPT if the user didn't suppress it.
+	 */
+	if (primary_only)
+		return last;
+
+	if ((p = calloc(1, gpt->secsz)) == NULL) {
+		gpt_warnx(gpt, "Can't allocate the secondary GPT");
+		return -1;
+	}
+
+	if ((gpt->tpg = map_add(gpt, last, 1LL,
+	    MAP_TYPE_SEC_GPT_HDR, p)) == NULL) {
+		gpt_warnx(gpt, "Can't add the secondary GPT");
+		return -1;
+	}
+
+	if ((gpt->lbt = map_add(gpt, last - blocks, blocks,
+	    MAP_TYPE_SEC_GPT_TBL, gpt->tbl->map_data)) == NULL) {
+		gpt_warnx(gpt, "Can't add the secondary GPT table");
+		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);
+	return last;
+}
+
+int
+gpt_add_find(gpt_t gpt, struct gpt_find *find, int ch) 
+{
+	int64_t human_num;
+	char *p;
+
+	switch (ch) {
+	case 'a':
+		if (find->all > 0)
+			return -1;
+		find->all = 1;
+		break;
+	case 'b':
+		if (find->block > 0)
+			return -1;
+		if (dehumanize_number(optarg, &human_num) < 0)
+			return -1;
+		find->block = human_num;
+		if (find->block < 1)
+			return -1;
+		break;
+	case 'i':
+		if (find->entry > 0)
+			return -1;
+		find->entry = strtoul(optarg, &p, 10);
+		if (*p != 0 || find->entry < 1)
+			return -1;
+		break;
+	case 'L':
+		if (find->label != NULL)
+			return -1;
+		find->label = (uint8_t *)strdup(optarg);
+		break;
+	case 's':
+		if (find->size > 0)
+			return -1;
+		find->size = strtoll(optarg, &p, 10);
+		if (*p != 0 || find->size < 1)
+			return -1;
+		break;
+	case 't':
+		if (!gpt_uuid_is_nil(find->type))
+			return -1;
+		if (gpt_uuid_parse(optarg, find->type) != 0)
+			return -1;
+		break;
+	default:
+		return -1;
+	}
+	return 0;
+}
+
+int
+gpt_change_ent(gpt_t gpt, const struct gpt_find *find,
+    void (*cfn)(struct gpt_ent *, void *), void *v)
+{
+	map_t m;
+	struct gpt_hdr *hdr;
+	struct gpt_ent *ent;
+	unsigned int i;
+
+	if (!find->all ^
+	    (find->block > 0 || find->entry > 0 || find->label != NULL
+	    || find->size > 0 || !gpt_uuid_is_nil(find->type)))
+		return -1;
+
+	if ((hdr = gpt_hdr(gpt)) == NULL)
+		return -1;
+
+	/* Relabel all matching entries in the map. */
+	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 (find->entry > 0 && find->entry != m->map_index)
+			continue;
+		if (find->block > 0 && find->block != m->map_start)
+			continue;
+		if (find->size > 0 && find->size != m->map_size)
+			continue;
+
+		i = m->map_index - 1;
+
+		ent = gpt_ent_primary(gpt, i);
+		if (find->label != NULL)
+			if (strcmp((char *)find->label,
+			    (char *)utf16_to_utf8(ent->ent_name)) != 0)
+				continue;
+
+		if (!gpt_uuid_is_nil(find->type) &&
+		    !gpt_uuid_equal(find->type, ent->ent_type))
+			continue;
+
+		/* Change the primary entry. */
+		(*cfn)(ent, v);
+
+		if (gpt_write_primary(gpt) == -1)
+			return -1;
+
+		ent = gpt_ent_backup(gpt, i);
+		/* Change the secondary entry. */
+		(*cfn)(ent, v);
+
+		if (gpt_write_backup(gpt) == -1)
+			return -1;
+
+		gpt_msg(gpt, "Partition %d %s", m->map_index, find->msg);
+	}
+	return 0;
+}
+
+int
+gpt_add_ais(gpt_t gpt, off_t *alignment, u_int *entry, off_t *size, int ch)
+{
+	int64_t human_num;
+	off_t sectors;
+	char *p;
+
+	switch (ch) {
+	case 'a':
+		if (*alignment > 0)
+			return -1;
+		if (dehumanize_number(optarg, &human_num) < 0)
+			return -1;
+		*alignment = human_num;
+		if (*alignment < 1)
+			return -1;
+		return 0;
+	case 'i':
+		if (*entry > 0)
+			return -1;
+		*entry = strtoul(optarg, &p, 10);
+		if (*p != 0 || *entry < 1)
+			return -1;
+		return 0;
+	case 's':
+		if (*size > 0)
+			return -1;
+		sectors = strtoll(optarg, &p, 10);
+		if (sectors < 1)
+			return -1;
+		if (*p == '\0' || ((*p == 's' || *p == 'S') && p[1] == '\0')) {
+			*size = sectors * gpt->secsz;
+			return 0;
+		}
+		if ((*p == 'b' || *p == 'B') && p[1] == '\0') {
+			*size = sectors;
+			return 0;
+		}
+		if (dehumanize_number(optarg, &human_num) < 0)
+			return -1;
+		*size = human_num;
+		return 0;
+	default:
+		return -1;
+	}
+}
+
+off_t
+gpt_check_ais(gpt_t gpt, off_t alignment, u_int entry, off_t size)
+{
+	if (entry == 0) {
+		gpt_warnx(gpt, "Entry not specified");
+		return -1;
+	}
+	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;
+}
+int
+gpt_attr_get(uint64_t *attributes)
+{
+	if (strcmp(optarg, "biosboot") == 0)
+		*attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
+	else if (strcmp(optarg, "bootme") == 0)
+		*attributes |= GPT_ENT_ATTR_BOOTME;
+	else if (strcmp(optarg, "bootonce") == 0)
+		*attributes |= GPT_ENT_ATTR_BOOTONCE;
+	else if (strcmp(optarg, "bootfailed") == 0)
+		*attributes |= GPT_ENT_ATTR_BOOTFAILED;
+	else
+		return -1;
+	return 0;
+}
+int
+gpt_attr_update(gpt_t gpt, u_int entry, uint64_t set, uint64_t clr)
+{
+	struct gpt_hdr *hdr;
+	struct gpt_ent *ent;
+	unsigned int i;
+	
+	if (entry == 0 || (set == 0 && clr == 0))
+		return -1;
+
+	if ((hdr = gpt_hdr(gpt)) == NULL)
+		return -1;
+
+	if (entry > le32toh(hdr->hdr_entries)) {
+		gpt_warnx(gpt, "Index %u out of range (%u max)",
+		    entry, le32toh(hdr->hdr_entries));
+		return -1;
+	}
+
+	i = entry - 1;
+	ent = gpt_ent_primary(gpt, i);
+	if (gpt_uuid_is_nil(ent->ent_type)) {
+		gpt_warnx(gpt, "Entry at index %u is unused", entry);
+		return -1;
+	}
+
+	ent->ent_attr &= ~clr;
+	ent->ent_attr |= set;
+
+	if (gpt_write_primary(gpt) == -1)
+		return -1;
+
+	ent = gpt_ent_backup(gpt, i);
+	ent->ent_attr &= ~clr;
+	ent->ent_attr |= set;
+
+	if (gpt_write_backup(gpt) == -1)
+		return -1;
+	gpt_msg(gpt, "Partition %d attributes updated", entry);
+	return 0;
+}
+
+int
+gpt_entry_get(u_int *entry)
+{
+	char *p;
+	if (*entry > 0)
+		return -1;
+	*entry = strtoul(optarg, &p, 10);
+	if (*p != 0 || *entry < 1)
+		return -1;
+	return 0;
+}

Index: src/sbin/gpt/gpt.h
diff -u src/sbin/gpt/gpt.h:1.24 src/sbin/gpt/gpt.h:1.25
--- src/sbin/gpt/gpt.h:1.24	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/gpt.h	Tue Dec  1 14:25:24 2015
@@ -75,7 +75,14 @@ uint32_t crc32(const void *, size_t);
 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);
+#define GPT_READONLY	1
+#define GPT_MODIFIED	2
+#define GPT_QUIET	4
+#define GPT_NOSYNC	8
+
 void*	gpt_read(gpt_t, off_t, size_t);
+off_t	gpt_last(gpt_t);
+int	gpt_create(gpt_t, off_t, u_int, int);
 int	gpt_write(gpt_t, map_t);
 int	gpt_write_crc(gpt_t, map_t, map_t);
 int	gpt_write_primary(gpt_t);
@@ -85,7 +92,6 @@ void	gpt_msg(gpt_t, const char *, ...) _
 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);
@@ -94,9 +100,26 @@ int	gpt_usage(const char *, const struct
 uint8_t *utf16_to_utf8(uint16_t *);
 void	utf8_to_utf16(const uint8_t *, uint16_t *, size_t);
 
-#define GPT_READONLY	1
-#define GPT_MODIFIED	2
-#define GPT_QUIET	4
-#define GPT_NOSYNC	8
+#define GPT_FIND "ab:i:L:s:t:"
+
+struct gpt_find {
+	int all;
+	gpt_uuid_t type;
+	off_t block, size;
+	unsigned int entry;
+	uint8_t *name, *label;
+	const char *msg;
+};
+int	gpt_change_ent(gpt_t, const struct gpt_find *,
+    void (*)(struct gpt_ent *, void *), void *);
+int	gpt_add_find(gpt_t, struct gpt_find *, int);
+
+#define GPT_AIS "a:i:s:"
+int	gpt_add_ais(gpt_t, off_t *, u_int *, off_t *, int);
+off_t	gpt_check_ais(gpt_t, off_t, u_int, off_t);
+
+int	gpt_attr_get(uint64_t *);
+int	gpt_attr_update(gpt_t, u_int, uint64_t, uint64_t);
+int	gpt_entry_get(u_int *);
 
 #endif /* _GPT_H_ */
Index: src/sbin/gpt/migrate.c
diff -u src/sbin/gpt/migrate.c:1.24 src/sbin/gpt/migrate.c:1.25
--- src/sbin/gpt/migrate.c:1.24	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/migrate.c	Tue Dec  1 14:25:24 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.24 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: migrate.c,v 1.25 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -262,16 +262,13 @@ migrate_netbsd_disklabel(gpt_t gpt, off_
 static int
 migrate(gpt_t gpt)
 {
-	off_t blocks, last;
+	off_t last = gpt_last(gpt);
 	map_t map;
-	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	struct mbr *mbr;
 	uint32_t start, size;
 	unsigned int i;
 
-	last = gpt->mediasz / gpt->secsz - 1LL;
-
 	map = map_find(gpt, MAP_TYPE_MBR);
 	if (map == NULL || map->map_start != 0) {
 		gpt_warnx(gpt, "No partitions to convert");
@@ -280,86 +277,10 @@ migrate(gpt_t gpt)
 
 	mbr = map->map_data;
 
-	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(gpt, 1LL, 0LL);
-	if (blocks == 0LL) {
-		gpt_warnx(gpt, "No room for the GPT header");
-		return -1;
-	}
-
-	/* Don't create more than parts entries. */
-	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 */
-	}
-
-	/* Never cross the median of the device. */
-	if ((blocks + 1LL) > ((last + 1LL) >> 1))
-		blocks = ((last + 1LL) >> 1) - 1LL;
-
-	/*
-	 * Get the amount of free space at the end of the device and
-	 * calculate the size for the GPT structures.
-	 */
-	map = map_last(gpt);
-	if (map->map_type != MAP_TYPE_UNUSED) {
-		gpt_warnx(gpt, "No room for the backup header");
-		return -1;
-	}
-
-	if (map->map_size < blocks)
-		blocks = map->map_size;
-	if (blocks == 1LL) {
-		gpt_warnx(gpt, "No room for the GPT table");
+	if (gpt_create(gpt, last, parts, 0) == -1)
 		return -1;
-	}
-
-	blocks--;		/* Number of blocks in the GPT table. */
-	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->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->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(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 = gpt->tbl->map_data;
-	for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
-		gpt_uuid_generate(ent[i].ent_guid);
-	}
 
 	/* Mirror partitions. */
 	for (i = 0; i < 4; i++) {
@@ -408,26 +329,18 @@ migrate(gpt_t gpt)
 	if (gpt_write_primary(gpt) == -1)
 		return -1;
 
-	/*
-	 * Create backup GPT.
-	 */
-	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;
 
-	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));
 	gpt_create_pmbr_part(mbr->mbr_part, last);
-	gpt_write(gpt, map);
+	if (gpt_write(gpt, map) == -1) {
+		gpt_warn(gpt, "Cant write PMBR");
+		return -1;
+	}
 	return 0;
 }
 

Index: src/sbin/gpt/label.c
diff -u src/sbin/gpt/label.c:1.21 src/sbin/gpt/label.c:1.22
--- src/sbin/gpt/label.c:1.21	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/label.c	Tue Dec  1 14:25:24 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.21 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: label.c,v 1.22 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -50,12 +50,6 @@ __RCSID("$NetBSD: label.c,v 1.21 2015/12
 #include "gpt_private.h"
 #include "gpt_uuid.h"
 
-static int all;
-static gpt_uuid_t type;
-static off_t block, size;
-static unsigned int entry;
-static uint8_t *name, *xlabel;
-
 static int cmd_label(gpt_t, int, char *[]);
 
 static const char *labelhelp[] = {
@@ -72,65 +66,21 @@ struct gpt_cmd c_label = {
 
 #define usage() gpt_usage(NULL, &c_label)
 
-static int
-label(gpt_t gpt)
+static void
+change(struct gpt_ent *ent, void *v)
 {
-	map_t m;
-	struct gpt_hdr *hdr;
-	struct gpt_ent *ent;
-	unsigned int i;
-
-	if ((hdr = gpt_hdr(gpt)) == NULL)
-		return -1;
-
-	/* Relabel all matching entries in the map. */
-	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)
-			continue;
-		if (block > 0 && block != m->map_start)
-			continue;
-		if (size > 0 && size != m->map_size)
-			continue;
-
-		i = m->map_index - 1;
-
-		ent = gpt_ent_primary(gpt, i);
-		if (xlabel != NULL)
-			if (strcmp((char *)xlabel,
-			    (char *)utf16_to_utf8(ent->ent_name)) != 0)
-				continue;
-
-		if (!gpt_uuid_is_nil(type) &&
-		    !gpt_uuid_equal(type, ent->ent_type))
-			continue;
-
-		/* Label the primary entry. */
-		utf8_to_utf16(name, ent->ent_name, 36);
-
-		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);
-
-		if (gpt_write_backup(gpt) == -1)
-			return -1;
-
-		gpt_msg(gpt, "Partition %d labeled %s", m->map_index, name);
-	}
-	return 0;
+	uint8_t *name = v;
+	utf8_to_utf16(name, ent->ent_name, 36);
 }
 
-static void
+static char *
 name_from_file(const char *fn)
 {
 	FILE *f;
 	char *p;
 	size_t maxlen = 1024;
 	size_t len;
+	char *name;
 
 	if (strcmp(fn, "-") != 0) {
 		f = fopen(fn, "r");
@@ -149,79 +99,41 @@ name_from_file(const char *fn)
 	p = strchr((const char *)name, '\n');
 	if (p != NULL)
 		*p = '\0';
+	return name;
 }
 
 static int
 cmd_label(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
-	int64_t human_num;
+	struct gpt_find find;
+	char *name = NULL;
+
+	memset(&find, 0, sizeof(find));
+	find.msg = "label changed";
 
 	/* Get the label options */
-	while ((ch = getopt(argc, argv, "ab:f:i:L:l:s:t:")) != -1) {
+	while ((ch = getopt(argc, argv, GPT_FIND "f:l:")) != -1) {
 		switch(ch) {
-		case 'a':
-			if (all > 0)
-				return usage();
-			all = 1;
-			break;
-		case 'b':
-			if (block > 0)
-				return usage();
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			block = human_num;
-			if (block < 1)
-				return usage();
-			break;
 		case 'f':
 			if (name != NULL)
 				return usage();
-			name_from_file(optarg);
-			break;
-		case 'i':
-			if (entry > 0)
-				return usage();
-			entry = strtoul(optarg, &p, 10);
-			if (*p != 0 || entry < 1)
-				return usage();
-			break;
-		case 'L':
-			if (xlabel != NULL)
-				return usage();
-			xlabel = (uint8_t *)strdup(optarg);
+			name = name_from_file(optarg);
 			break;
 		case 'l':
 			if (name != NULL)
 				return usage();
-			name = (uint8_t *)strdup(optarg);
-			break;
-		case 's':
-			if (size > 0)
-				return usage();
-			size = strtoll(optarg, &p, 10);
-			if (*p != 0 || size < 1)
-				return usage();
+			name = strdup(optarg);
 			break;
-		case 't':
-			if (!gpt_uuid_is_nil(type))
-				return usage();
-			if (gpt_uuid_parse(optarg, type) != 0)
+		default:
+			if (gpt_add_find(gpt, &find, ch) == -1)
 				return usage();
 			break;
-		default:
-			return usage();
 		}
 	}
 
-	if (!all ^
-	    (block > 0 || entry > 0 || xlabel != NULL || size > 0 ||
-	    !gpt_uuid_is_nil(type)))
-		return usage();
-
 	if (name == NULL || argc != optind)
 		return usage();
 
-	return label(gpt);
+	return gpt_change_ent(gpt, &find, change, name);
 }

Index: src/sbin/gpt/remove.c
diff -u src/sbin/gpt/remove.c:1.19 src/sbin/gpt/remove.c:1.20
--- src/sbin/gpt/remove.c:1.19	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/remove.c	Tue Dec  1 14:25:24 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.19 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: remove.c,v 1.20 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -49,12 +49,6 @@ __RCSID("$NetBSD: remove.c,v 1.19 2015/1
 #include "gpt.h"
 #include "gpt_private.h"
 
-static int all;
-static gpt_uuid_t type;
-static off_t block, size;
-static unsigned int entry;
-static uint8_t *label;
-
 static int cmd_remove(gpt_t, int, char *[]);
 
 static const char *removehelp[] = {
@@ -71,119 +65,29 @@ struct gpt_cmd c_remove = {
 
 #define usage() gpt_usage(NULL, &c_remove)
 
-static int
-rem(gpt_t gpt)
+static void
+change(struct gpt_ent *ent, void *v)
 {
-	map_t m;
-	struct gpt_ent *ent;
-	unsigned int i;
-
-	if (gpt_hdr(gpt) == NULL)
-		return -1;
-
-	/* Remove all matching entries in the map. */
-	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)
-			continue;
-		if (block > 0 && block != m->map_start)
-			continue;
-		if (size > 0 && size != m->map_size)
-			continue;
-
-		i = m->map_index - 1;
-
-		ent = gpt_ent_primary(gpt, i);
-
-		if (label != NULL)
-			if (strcmp((char *)label,
-			    (char *)utf16_to_utf8(ent->ent_name)) != 0)
-				continue;
-
-		if (!gpt_uuid_is_nil(type) &&
-		    !gpt_uuid_equal(type, ent->ent_type))
-			continue;
-
-		/* Remove the primary entry by clearing the partition type. */
-		gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
-
-		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);
-
-		if (gpt_write_backup(gpt) == -1)
-			return -1;
-		gpt_msg(gpt, "partition %d removed", m->map_index);
-	}
-	return 0;
+	/* Remove the primary entry by clearing the partition type. */
+	gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
 }
 
 static int
 cmd_remove(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
-	int64_t human_num;
+	struct gpt_find find;
+
+	memset(&find, 0, sizeof(find));
+	find.msg = "removed";
 
 	/* Get the remove options */
-	while ((ch = getopt(argc, argv, "ab:i:L:s:t:")) != -1) {
-		switch(ch) {
-		case 'a':
-			if (all > 0)
-				return usage();
-			all = 1;
-			break;
-		case 'b':
-			if (block > 0)
-				return usage();
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			block = human_num;
-			if (block < 1)
-				return usage();
-			break;
-		case 'i':
-			if (entry > 0)
-				return usage();
-			entry = strtoul(optarg, &p, 10);
-			if (*p != 0 || entry < 1)
-				return usage();
-			break;
-		case 'L':
-			if (label != NULL)
-				return usage();
-			label = (uint8_t *)strdup(optarg);
-			break;
-		case 's':
-			if (size > 0)
-				usage();
-			size = strtoll(optarg, &p, 10);
-			if (*p != 0 || size < 1)
-				return usage();
-			break;
-		case 't':
-			if (!gpt_uuid_is_nil(type))
-				return usage();
-			if (gpt_uuid_parse(optarg, type) != 0)
-				return usage();
-			break;
-		default:
+	while ((ch = getopt(argc, argv, GPT_FIND)) != -1)
+		if (gpt_add_find(gpt, &find, ch) == -1)
 			return usage();
-		}
-	}
-
-	if (!all ^
-	    (block > 0 || entry > 0 || label != NULL || size > 0 ||
-	    !gpt_uuid_is_nil(type)))
-		return usage();
 
 	if (argc != optind)
 		return usage();
 
-	return rem(gpt);
+	return gpt_change_ent(gpt, &find, change, NULL);
 }

Index: src/sbin/gpt/resize.c
diff -u src/sbin/gpt/resize.c:1.16 src/sbin/gpt/resize.c:1.17
--- src/sbin/gpt/resize.c:1.16	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/resize.c	Tue Dec  1 14:25:24 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.16 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: resize.c,v 1.17 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -139,67 +139,17 @@ resize(gpt_t gpt)
 static int
 cmd_resize(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
-	int64_t human_num;
 
-	while ((ch = getopt(argc, argv, "a:i:s:")) != -1) {
-		switch(ch) {
-		case 'a':
-			if (alignment > 0)
-				return usage();
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			alignment = human_num;
-			if (alignment < 1)
-				return usage();
-			break;
-		case 'i':
-			if (entry > 0)
-				return usage();
-			entry = strtoul(optarg, &p, 10);
-			if (*p != 0 || entry < 1)
-				return usage();
-			break;
-		case 's':
-			if (sectors > 0 || size > 0)
-				return usage();
-			sectors = strtoll(optarg, &p, 10);
-			if (sectors < 1)
-				return usage();
-			if (*p == '\0')
-				break;
-			if (*p == 's' || *p == 'S') {
-				if (*(p + 1) == '\0')
-					break;
-				else
-					return usage();
-			}
-			if (*p == 'b' || *p == 'B') {
-				if (*(p + 1) == '\0') {
-					size = sectors;
-					sectors = 0;
-					break;
-				} else
-					return usage();
-			}
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			size = human_num;
-			sectors = 0;
-			break;
-		default:
+	while ((ch = getopt(argc, argv, GPT_AIS)) != -1) {
+		if (gpt_add_ais(gpt, &alignment, &entry, &size, ch) == -1)
 			return usage();
-		}
 	}
 
 	if (argc != optind)
 		return usage();
 
-	if (entry == 0)
-		return usage();
-
-	if ((sectors = gpt_check(gpt, alignment, size)) == -1)
+	if ((sectors = gpt_check_ais(gpt, alignment, entry, size)) == -1)
 		return -1;
 
 	return resize(gpt);

Index: src/sbin/gpt/resizedisk.c
diff -u src/sbin/gpt/resizedisk.c:1.9 src/sbin/gpt/resizedisk.c:1.10
--- src/sbin/gpt/resizedisk.c:1.9	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/resizedisk.c	Tue Dec  1 14:25:24 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.9 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: resizedisk.c,v 1.10 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/bootblock.h>
@@ -223,38 +223,13 @@ resizedisk(gpt_t gpt)
 static int
 cmd_resizedisk(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
-	int64_t human_num;
 
 	while ((ch = getopt(argc, argv, "s:")) != -1) {
 		switch(ch) {
 		case 's':
-			if (sector > 0 || size > 0)
-				return usage();
-			sector = strtoll(optarg, &p, 10);
-			if (sector < 1)
-				return usage();
-			if (*p == '\0')
-				break;
-			if (*p == 's' || *p == 'S') {
-				if (*(p + 1) == '\0')
-					break;
-				else
-					return usage();
-			}
-			if (*p == 'b' || *p == 'B') {
-				if (*(p + 1) == '\0') {
-					size = sector;
-					sector = 0;
-					break;
-				} else
-					return usage();
-			}
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			size = human_num;
-			sector = 0;
+			if (gpt_add_ais(gpt, NULL, NULL, &size, ch) == -1)
+				return -1;
 			break;
 		default:
 			return usage();
@@ -264,7 +239,7 @@ cmd_resizedisk(gpt_t gpt, int argc, char
 	if (argc != optind)
 		return usage();
 
-	if ((sector = gpt_check(gpt, 0, size)) == -1)
+	if ((sector = gpt_check_ais(gpt, 0, ~0, size)) == -1)
 		return -1;
 
 	return resizedisk(gpt);
Index: src/sbin/gpt/type.c
diff -u src/sbin/gpt/type.c:1.9 src/sbin/gpt/type.c:1.10
--- src/sbin/gpt/type.c:1.9	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/type.c	Tue Dec  1 14:25:24 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.9 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: type.c,v 1.10 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -49,12 +49,6 @@ __RCSID("$NetBSD: type.c,v 1.9 2015/12/0
 #include "gpt.h"
 #include "gpt_private.h"
 
-static int all;
-static gpt_uuid_t type, newtype;
-static off_t block, size;
-static unsigned int entry;
-static uint8_t *label;
-
 static int cmd_type(gpt_t, int, char *[]);
 
 static const char *typehelp[] = {
@@ -71,108 +65,26 @@ struct gpt_cmd c_type = {
 
 #define usage() gpt_usage(NULL, &c_type)
 
-static int
-chtype(gpt_t gpt)
+static void
+change(struct gpt_ent *ent, void *v)
 {
-	map_t m;
-	struct gpt_ent *ent;
-	unsigned int i;
-
-	if (gpt_hdr(gpt) == NULL)
-		return -1;
-
-	/* Change type of all matching entries in the map. */
-	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)
-			continue;
-		if (block > 0 && block != m->map_start)
-			continue;
-		if (size > 0 && size != m->map_size)
-			continue;
-
-		i = m->map_index - 1;
-
-		ent = gpt_ent_primary(gpt, i);
-
-		if (label != NULL)
-			if (strcmp((char *)label,
-			    (char *)utf16_to_utf8(ent->ent_name)) != 0)
-				continue;
-
-		if (!gpt_uuid_is_nil(type) &&
-		    !gpt_uuid_equal(type, ent->ent_type))
-			continue;
-
-		/* Change the primary entry. */
-		gpt_uuid_copy(ent->ent_type, newtype);
-
-		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);
-
-		if (gpt_write_backup(gpt) == -1)
-			return -1;
-
-		gpt_msg(gpt, "Partition %d type changed", m->map_index);
-	}
-	return 0;
+	gpt_uuid_t *newtype = v;
+	gpt_uuid_copy(ent->ent_type, *newtype);
 }
 
 static int
 cmd_type(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
-	int64_t human_num;
+	gpt_uuid_t newtype;
+	struct gpt_find find;
+
+	memset(&find, 0, sizeof(find));
+	find.msg = "type changed";
 
 	/* Get the type options */
-	while ((ch = getopt(argc, argv, "ab:i:L:s:t:T:")) != -1) {
+	while ((ch = getopt(argc, argv, GPT_FIND "T:")) != -1) {
 		switch(ch) {
-		case 'a':
-			if (all > 0)
-				return usage();
-			all = 1;
-			break;
-		case 'b':
-			if (block > 0)
-				return usage();
-			if (dehumanize_number(optarg, &human_num) < 0)
-				return usage();
-			block = human_num;
-			if (block < 1)
-				return usage();
-			break;
-		case 'i':
-			if (entry > 0)
-				return usage();
-			entry = strtoul(optarg, &p, 10);
-			if (*p != 0 || entry < 1)
-				return usage();
-			break;
-                case 'L':
-                        if (label != NULL)
-                                return usage();
-                        label = (uint8_t *)strdup(optarg);
-                        break;
-		case 's':
-			if (size > 0)
-				return usage();
-			size = strtoll(optarg, &p, 10);
-			if (*p != 0 || size < 1)
-				return usage();
-			break;
-		case 't':
-			if (!gpt_uuid_is_nil(type))
-				return usage();
-			if (gpt_uuid_parse(optarg, type) != 0)
-				return usage();
-			break;
 		case 'T':
 			if (!gpt_uuid_is_nil(newtype))
 				return usage();
@@ -180,19 +92,14 @@ cmd_type(gpt_t gpt, int argc, char *argv
 				return usage();
 			break;
 		default:
-			return usage();
+			if (gpt_add_find(gpt, &find, ch) == -1)
+				return usage();
+			break;
 		}
 	}
 
-	if (!all ^
-	    (block > 0 || entry > 0 || label != NULL || size > 0 ||
-	    !gpt_uuid_is_nil(type)))
-		return usage();
-	if (gpt_uuid_is_nil(newtype))
-		return usage();
-
-	if (argc != optind)
+	if (gpt_uuid_is_nil(newtype) || argc != optind)
 		return usage();
 
-	return chtype(gpt);
+	return gpt_change_ent(gpt, &find, change, &newtype);
 }

Index: src/sbin/gpt/set.c
diff -u src/sbin/gpt/set.c:1.8 src/sbin/gpt/set.c:1.9
--- src/sbin/gpt/set.c:1.8	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/set.c	Tue Dec  1 14:25:24 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.8 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: set.c,v 1.9 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -49,9 +49,6 @@ __RCSID("$NetBSD: set.c,v 1.8 2015/12/01
 #include "gpt.h"
 #include "gpt_private.h"
 
-static unsigned int entry;
-static uint64_t attributes;
-
 static int cmd_set(gpt_t, int, char *[]);
 
 static const char *sethelp[] = {
@@ -68,70 +65,20 @@ struct gpt_cmd c_set = {
 #define usage() gpt_usage(NULL, &c_set)
 
 static int
-set(gpt_t gpt)
-{
-	struct gpt_hdr *hdr;
-	struct gpt_ent *ent;
-	unsigned int i;
-	
-
-	if ((hdr = gpt_hdr(gpt)) == NULL)
-		return -1;
-
-
-	if (entry > le32toh(hdr->hdr_entries)) {
-		gpt_warnx(gpt, "Index %u out of range (%u max)",
-		    entry, le32toh(hdr->hdr_entries));
-		return -1;
-	}
-
-	i = entry - 1;
-	ent = gpt_ent_primary(gpt, i);
-	if (gpt_uuid_is_nil(ent->ent_type)) {
-		gpt_warnx(gpt, "Entry at index %u is unused", entry);
-		return -1;
-	}
-
-	ent->ent_attr |= attributes;
-
-	if (gpt_write_primary(gpt) == -1)
-		return -1;
-
-	ent = gpt_ent_backup(gpt, i);
-	ent->ent_attr |= attributes;
-
-	if (gpt_write_backup(gpt) == -1)
-		return -1;
-
-	gpt_msg(gpt, "Partition %d attributes updated", entry);
-	return 0;
-}
-
-static int
 cmd_set(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
+	unsigned int entry = 0;
+	uint64_t attributes = 0;
 
 	while ((ch = getopt(argc, argv, "a:i:")) != -1) {
 		switch(ch) {
 		case 'a':
-			if (strcmp(optarg, "biosboot") == 0)
-				attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-			else if (strcmp(optarg, "bootme") == 0)
-				attributes |= GPT_ENT_ATTR_BOOTME;
-			else if (strcmp(optarg, "bootonce") == 0)
-				attributes |= GPT_ENT_ATTR_BOOTONCE;
-			else if (strcmp(optarg, "bootfailed") == 0)
-				attributes |= GPT_ENT_ATTR_BOOTFAILED;
-			else
+			if (gpt_attr_get(&attributes) == -1)
 				return usage();
 			break;
 		case 'i':
-			if (entry > 0)
-				usage();
-			entry = strtoul(optarg, &p, 10);
-			if (*p != 0 || entry < 1)
+			if (gpt_entry_get(&entry) == -1)
 				return usage();
 			break;
 		default:
@@ -142,8 +89,5 @@ cmd_set(gpt_t gpt, int argc, char *argv[
 	if (argc != optind)
 		return usage();
 
-	if (entry == 0 || attributes == 0)
-		return usage();
-
-	return set(gpt);
+	return gpt_attr_update(gpt, entry, attributes, 0);
 }
Index: src/sbin/gpt/unset.c
diff -u src/sbin/gpt/unset.c:1.8 src/sbin/gpt/unset.c:1.9
--- src/sbin/gpt/unset.c:1.8	Tue Dec  1 11:32:19 2015
+++ src/sbin/gpt/unset.c	Tue Dec  1 14:25:24 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.8 2015/12/01 16:32:19 christos Exp $");
+__RCSID("$NetBSD: unset.c,v 1.9 2015/12/01 19:25:24 christos Exp $");
 #endif
 
 #include <sys/types.h>
@@ -49,9 +49,6 @@ __RCSID("$NetBSD: unset.c,v 1.8 2015/12/
 #include "gpt.h"
 #include "gpt_private.h"
 
-static unsigned int entry;
-static uint64_t attributes;
-
 static int cmd_unset(gpt_t, int, char *[]);
 
 static const char *unsethelp[] = {
@@ -68,68 +65,20 @@ struct gpt_cmd c_unset = {
 #define usage() gpt_usage(NULL, &c_unset)
 
 static int
-unset(gpt_t gpt)
-{
-	struct gpt_hdr *hdr;
-	struct gpt_ent *ent;
-	unsigned int i;
-	
-
-	if ((hdr = gpt_hdr(gpt)) == NULL)
-		return -1;
-
-	if (entry > le32toh(hdr->hdr_entries)) {
-		gpt_warnx(gpt, "Index %u out of range (%u max)",
-		    entry, le32toh(hdr->hdr_entries));
-		return -1;
-	}
-
-	i = entry - 1;
-	ent = gpt_ent_primary(gpt, i);
-	if (gpt_uuid_is_nil(ent->ent_type)) {
-		gpt_warnx(gpt, "Entry at index %u is unused", entry);
-		return -1;
-	}
-
-	ent->ent_attr &= ~attributes;
-
-	if (gpt_write_primary(gpt) == -1)
-		return -1;
-
-	ent = gpt_ent_backup(gpt, i);
-	ent->ent_attr &= ~attributes;
-
-	if (gpt_write_backup(gpt) == -1)
-		return -1;
-	gpt_msg(gpt, "Partition %d attributes updated", entry);
-	return 0;
-}
-
-static int
 cmd_unset(gpt_t gpt, int argc, char *argv[])
 {
-	char *p;
 	int ch;
+	unsigned int entry = 0;
+	uint64_t attributes = 0;
 
 	while ((ch = getopt(argc, argv, "a:i:")) != -1) {
 		switch(ch) {
 		case 'a':
-			if (strcmp(optarg, "biosboot") == 0)
-				attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-			else if (strcmp(optarg, "bootme") == 0)
-				attributes |= GPT_ENT_ATTR_BOOTME;
-			else if (strcmp(optarg, "bootonce") == 0)
-				attributes |= GPT_ENT_ATTR_BOOTONCE;
-			else if (strcmp(optarg, "bootfailed") == 0)
-				attributes |= GPT_ENT_ATTR_BOOTFAILED;
-			else
+			if (gpt_attr_get(&attributes) == -1)
 				return usage();
 			break;
 		case 'i':
-			if (entry > 0)
-				return usage();
-			entry = strtoul(optarg, &p, 10);
-			if (*p != 0 || entry < 1)
+			if (gpt_entry_get(&entry) == -1)
 				return usage();
 			break;
 		default:
@@ -140,8 +89,5 @@ cmd_unset(gpt_t gpt, int argc, char *arg
 	if (argc != optind)
 		return usage();
 
-	if (entry == 0 || attributes == 0)
-		return usage();
-
-	return unset(gpt);
+	return gpt_attr_update(gpt, entry, 0, attributes);
 }

Reply via email to