Module Name: src Committed By: snj Date: Tue Jun 2 19:49:38 UTC 2015
Modified Files: src/sbin/gpt [netbsd-7]: Makefile add.c backup.c biosboot.c create.c destroy.c gpt.8 gpt.c gpt.h label.c map.c migrate.c recover.c remove.c resize.c restore.c set.c show.c unset.c Added Files: src/sbin/gpt [netbsd-7]: drvctl.c gpt_uuid.c gpt_uuid.h resizedisk.c type.c Log Message: Pull up following revision(s) (requested by jnemeth in ticket #774): sbin/gpt/Makefile: revisions 1.9-1.13 sbin/gpt/add.c: revisions 1.25-1.27 sbin/gpt/backup.c: revisions 1.2-1.8 sbin/gpt/biosboot.c: revisions 1.8-1.14 sbin/gpt/create.c: revisions 1.8-1.12 sbin/gpt/destroy.c: revisions 1.5-1.6 sbin/gpt/drvctl.c: revision 1.1 sbin/gpt/gpt.8: revisions 1.29-1.36 sbin/gpt/gpt.c: revisions 1.29-1.40 sbin/gpt/gpt.h: revisions 1.12-1.18 sbin/gpt/gpt_uuid.c: revisions 1.1-1.10 sbin/gpt/gpt_uuid.h: revisions 1.1-1.3 sbin/gpt/label.c: revisions 1.15-1.18 sbin/gpt/map.c: revision 1.7 sbin/gpt/migrate.c: revisions 1.15-1.21 sbin/gpt/recover.c: revision 1.5 sbin/gpt/remove.c: revisions 1.13-1.16 sbin/gpt/resize.c: revisions 1.9-1.11 sbin/gpt/resizedisk.c: revisions 1.1-1.6 sbin/gpt/restore.c: revisions 1.2-1.7 sbin/gpt/set.c: revisions 1.3-1.5 sbin/gpt/show.c: revision 1.16-1.21 sbin/gpt/type.c: revisions 1.1-1.6 sbin/gpt/unset.c: revisions 1.3-1.5 - record the sector size of the disk - correct confusion with end_cylinder and end_sector in MBRs -- - dump all partitions, not just ones that are in use - while here, squash a memory leak It shouldn't be necessary to backup unused partitions, however the partition GUID is created at the time the GPT is created and is never changed. It shouldn't matter if the GUID of an unused partition changes, but there may be some special case where it does. Since it isn't a big deal to record the unused partitions, might as well do it. -- Initial cut of gpt restore. This functions correctly in testing, but isn't all that pretty. It has minimal error testing and may leak memory. It also only works with empty disks. If passed "-F" flag, it will blank the disk for you. -- document the new restore subcommand -- - make gpt_gpt() available for use directly by subcommands - create new resizedisk disk subcommand for relocating backup GPT -- Fix compile error observed on i386. Use PRIu64. -- no C99isms in tool code -- - handle a GPT that isn't an exact multiple of a sector - adjust PMBR size, in case new disk is a different size - don't leak as much memory - clean up error handling somewhat -- PR/44218 - David Young -- add "type" subcommand to change a partition type -- PR/47990 - Dr. Wolfgang Stukenbrock -- add "-L <label>" as selector option -- minor toolification: need libprop... -- more toolification -- more toolification changes -- remove compat defines. -- Add internal uuid support, since the linux+macos versions of the library are different than than *bsd ones, and others might not have it at all. -- Check size of correct buffer. Note, just being pedantic as the buffer being checked is the same size as the one that should have been checked. -- correctly show partition type in the new world order -- actually return the uuid when parsing one that is in numeric format -- using random values for hdr->hdr_guid does not work very well -- oops, forgot to update end of data area -- It's HAVE_NBTOOL_CONFIG_H, not HAVE_NBTOOLS_CONFIG_H -- Fix tools build on !NetBSD. -- include <sys/endian.h> for both the non-tools build, and the tools build on a host where the file exists. Fixes a build problem on FreeBSD, reported by Herbert J. Skuhra, where tools/compat's configure detected that be32dec() and friends were available in the host's <sys/endian.h>, so tools/compat did not provide its own versions. -- "0" is not guaranteed to be unique -- provide a copy of the kernel uuid generator (with portable API calls) for tools. -- Allow specifying sector and media size on the command line. -- Remove trailing whitespace. -- Make gpt(8) generate v4 (random) uuids. Don't needlessly leak your date/time and MAC address when you edit the disk. Read from /dev/urandom rather than calling arc4random or anything, since this is a tool. (Cygwin seems to have /dev/urandom, but yell if this breaks the build on your exotic platform because it lacks /dev/urandom.) ok apb -- Paranoia: choke noisily on EOF from /dev/urandom. -- Report the argument instead of (null) when opendisk fails. -- handle constness -- handle constness better -- Add some more common partition types. -- Bump date for previous. -- Fix handling of -t option for the type command. Match any type, when no option is given, just like for the label command. -- Factor out the getdisksize() drvctl method, and provide an alternative that directly uses the disk ioctl's instead of relying on the drvctl device driver which is currently not mandatory. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.8.2.1 src/sbin/gpt/Makefile cvs rdiff -u -r1.24 -r1.24.4.1 src/sbin/gpt/add.c cvs rdiff -u -r1.1 -r1.1.6.1 src/sbin/gpt/backup.c cvs rdiff -u -r1.7 -r1.7.4.1 src/sbin/gpt/biosboot.c src/sbin/gpt/create.c cvs rdiff -u -r1.4 -r1.4.20.1 src/sbin/gpt/destroy.c src/sbin/gpt/recover.c cvs rdiff -u -r0 -r1.1.2.2 src/sbin/gpt/drvctl.c cvs rdiff -u -r1.28 -r1.28.4.1 src/sbin/gpt/gpt.8 cvs rdiff -u -r1.28 -r1.28.2.1 src/sbin/gpt/gpt.c cvs rdiff -u -r1.11 -r1.11.2.1 src/sbin/gpt/gpt.h cvs rdiff -u -r0 -r1.10.2.2 src/sbin/gpt/gpt_uuid.c cvs rdiff -u -r0 -r1.3.2.2 src/sbin/gpt/gpt_uuid.h cvs rdiff -u -r1.14 -r1.14.4.1 src/sbin/gpt/label.c src/sbin/gpt/migrate.c cvs rdiff -u -r1.6 -r1.6.4.1 src/sbin/gpt/map.c cvs rdiff -u -r1.12 -r1.12.4.1 src/sbin/gpt/remove.c cvs rdiff -u -r1.8 -r1.8.6.1 src/sbin/gpt/resize.c cvs rdiff -u -r0 -r1.6.2.2 src/sbin/gpt/resizedisk.c src/sbin/gpt/type.c cvs rdiff -u -r1.1 -r1.1.2.1 src/sbin/gpt/restore.c cvs rdiff -u -r1.2 -r1.2.6.1 src/sbin/gpt/set.c src/sbin/gpt/unset.c cvs rdiff -u -r1.15 -r1.15.4.1 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.8 src/sbin/gpt/Makefile:1.8.2.1 --- src/sbin/gpt/Makefile:1.8 Sun Aug 10 18:27:15 2014 +++ src/sbin/gpt/Makefile Tue Jun 2 19:49:38 2015 @@ -1,12 +1,26 @@ -# $NetBSD: Makefile,v 1.8 2014/08/10 18:27:15 jnemeth Exp $ +# $NetBSD: Makefile,v 1.8.2.1 2015/06/02 19:49:38 snj Exp $ # $FreeBSD: src/sbin/gpt/Makefile,v 1.7 2005/09/01 02:49:20 marcel Exp $ PROG= gpt -SRCS= add.c backup.c biosboot.c create.c destroy.c gpt.c label.c map.c \ - migrate.c recover.c remove.c resize.c restore.c set.c show.c unset.c +SRCS= add.c biosboot.c create.c destroy.c gpt.c label.c map.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 +.if (${HOSTPROG:U} == "") +SRCS+= backup.c restore.c LDADD+= -lprop -lutil DPADD+= ${LIBPROP} ${LIBUTIL} +.if ${USE_DRVCTL:Uno} == "yes" +CPPFLAGS+=-DUSE_DRVCTL +SRCS+=drvctl.c +.else +.PATH: ${.CURDIR}/../fsck +CPPFLAGS+=-I${.CURDIR}/../fsck +SRCS+=partutil.c +.endif +.endif + + .include <bsd.prog.mk> Index: src/sbin/gpt/add.c diff -u src/sbin/gpt/add.c:1.24 src/sbin/gpt/add.c:1.24.4.1 --- src/sbin/gpt/add.c:1.24 Tue Dec 10 01:05:00 2013 +++ src/sbin/gpt/add.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.24 2013/12/10 01:05:00 jnemeth Exp $"); +__RCSID("$NetBSD: add.c,v 1.24.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -40,12 +44,11 @@ __RCSID("$NetBSD: add.c,v 1.24 2013/12/1 #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <inttypes.h> #include "map.h" #include "gpt.h" -static uuid_t type; +static gpt_uuid_t type; static off_t alignment, block, sectors, size; static unsigned int entry; static uint8_t *name; @@ -67,7 +70,6 @@ usage_add(void) static void add(int fd) { - uuid_t uuid; map_t *gpt, *tpg; map_t *tbl, *lbt; map_t *map; @@ -110,8 +112,7 @@ add(int fd) i = entry - 1; ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_dec(ent->ent_type, &uuid); - if (!uuid_is_nil(&uuid, NULL)) { + if (!gpt_uuid_is_nil(ent->ent_type)) { warnx("%s: error: entry at index %u is not free", device_name, entry); return; @@ -121,8 +122,7 @@ add(int fd) for (i = 0; i < le32toh(hdr->hdr_entries); i++) { ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_dec(ent->ent_type, &uuid); - if (uuid_is_nil(&uuid, NULL)) + if (gpt_uuid_is_nil(ent->ent_type)) break; } if (i == le32toh(hdr->hdr_entries)) { @@ -149,7 +149,7 @@ add(int fd) } } - le_uuid_enc(ent->ent_type, &type); + 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) @@ -166,7 +166,7 @@ add(int fd) hdr = tpg->map_data; ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_enc(ent->ent_type, &type); + 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) @@ -253,9 +253,9 @@ cmd_add(int argc, char *argv[]) sectors = 0; break; case 't': - if (!uuid_is_nil(&type, NULL)) + if (!gpt_uuid_is_nil(type)) usage_add(); - if (parse_uuid(optarg, &type) != 0) + if (gpt_uuid_parse(optarg, type) != 0) usage_add(); break; default: @@ -267,9 +267,8 @@ cmd_add(int argc, char *argv[]) usage_add(); /* Create NetBSD FFS partitions by default. */ - if (uuid_is_nil(&type, NULL)) { - static const uuid_t nb_ffs = GPT_ENT_TYPE_NETBSD_FFS; - type = nb_ffs; + if (gpt_uuid_is_nil(type)) { + gpt_uuid_create(GPT_TYPE_NETBSD_FFS, type, NULL, 0); } while (optind < argc) { Index: src/sbin/gpt/backup.c diff -u src/sbin/gpt/backup.c:1.1 src/sbin/gpt/backup.c:1.1.6.1 --- src/sbin/gpt/backup.c:1.1 Thu Dec 19 06:46:51 2013 +++ src/sbin/gpt/backup.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.1 2013/12/19 06:46:51 jnemeth Exp $"); +__RCSID("$NetBSD: backup.c,v 1.1.6.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/bootblock.h> @@ -66,7 +70,6 @@ usage_backup(void) static void backup(void) { - uuid_t u; map_t *m; struct mbr *mbr; struct gpt_ent *ent; @@ -77,11 +80,15 @@ backup(void) prop_data_t propdata; prop_number_t propnum; prop_string_t propstr; - char *propext, *s; + char *propext, *s, buf[128]; bool rc; props = prop_dictionary_create(); PROP_ERR(props); + propnum = prop_number_create_integer(secsz); + PROP_ERR(propnum); + rc = prop_dictionary_set(props, "sector_size", propnum); + PROP_ERR(rc); m = map_first(); while (m != NULL) { switch (m->map_type) { @@ -139,6 +146,11 @@ backup(void) propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_esect); PROP_ERR(propnum); rc = prop_dictionary_set(mbr_dict, + "end_sector", propnum); + PROP_ERR(rc); + propnum = prop_number_create_unsigned_integer(mbr->mbr_part[i].part_ecyl); + PROP_ERR(propnum); + rc = prop_dictionary_set(mbr_dict, "end_cylinder", propnum); PROP_ERR(rc); propnum = prop_number_create_unsigned_integer(le16toh(mbr->mbr_part[i].part_start_lo)); @@ -188,10 +200,9 @@ backup(void) rc = prop_dictionary_set(type_dict, "revision", propnum); PROP_ERR(rc); - le_uuid_dec(hdr->hdr_guid, &u); - uuid_to_string(&u, &s, NULL); - propstr = prop_string_create_cstring(s); - free(s); + gpt_uuid_snprintf(buf, sizeof(buf), "%d", + hdr->hdr_guid); + propstr = prop_string_create_cstring(buf); PROP_ERR(propstr); rc = prop_dictionary_set(type_dict, "guid", propstr); PROP_ERR(rc); @@ -207,12 +218,11 @@ backup(void) type_dict = prop_dictionary_create(); PROP_ERR(type_dict); ent = m->map_data; - gpt_array = NULL; + gpt_array = prop_array_create(); + PROP_ERR(gpt_array); for (i = 1, ent = m->map_data; (char *)ent < (char *)(m->map_data) + m->map_size * secsz; i++, ent++) { - if (uuid_is_nil((uuid_t *)&ent->ent_type, NULL)) - continue; gpt_dict = prop_dictionary_create(); PROP_ERR(gpt_dict); propnum = prop_number_create_integer(i); @@ -220,17 +230,15 @@ backup(void) rc = prop_dictionary_set(gpt_dict, "index", propnum); PROP_ERR(propnum); - le_uuid_dec(ent->ent_type, &u); - uuid_to_string(&u, &s, NULL); - propstr = prop_string_create_cstring(s); - free(s); + gpt_uuid_snprintf(buf, sizeof(buf), "%d", + ent->ent_type); + propstr = prop_string_create_cstring(buf); PROP_ERR(propstr); rc = prop_dictionary_set(gpt_dict, "type", propstr); - le_uuid_dec(ent->ent_guid, &u); - uuid_to_string(&u, &s, NULL); - propstr = prop_string_create_cstring(s); - free(s); + gpt_uuid_snprintf(buf, sizeof(buf), "%d", + ent->ent_guid); + propstr = prop_string_create_cstring(buf); PROP_ERR(propstr); rc = prop_dictionary_set(gpt_dict, "guid", propstr); @@ -258,19 +266,13 @@ backup(void) "name", propstr); PROP_ERR(rc); } - if (gpt_array == NULL) { - gpt_array = prop_array_create(); - PROP_ERR(gpt_array); - } rc = prop_array_add(gpt_array, gpt_dict); PROP_ERR(rc); } - if (gpt_array != NULL) { - rc = prop_dictionary_set(type_dict, - "gpt_array", gpt_array); - PROP_ERR(rc); - prop_object_release(gpt_array); - } + rc = prop_dictionary_set(type_dict, + "gpt_array", gpt_array); + PROP_ERR(rc); + prop_object_release(gpt_array); rc = prop_dictionary_set(props, "GPT_TBL", type_dict); PROP_ERR(rc); prop_object_release(type_dict); @@ -282,6 +284,7 @@ backup(void) PROP_ERR(propext); prop_object_release(props); fputs(propext, stdout); + free(propext); } int @@ -298,7 +301,6 @@ cmd_backup(int argc, char *argv[]) warn("unable to open device '%s'", device_name); continue; } - backup(); gpt_close(fd); Index: src/sbin/gpt/biosboot.c diff -u src/sbin/gpt/biosboot.c:1.7 src/sbin/gpt/biosboot.c:1.7.4.1 --- src/sbin/gpt/biosboot.c:1.7 Wed Nov 27 01:47:53 2013 +++ src/sbin/gpt/biosboot.c Tue Jun 2 19:49:38 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: biosboot.c,v 1.7 2013/11/27 01:47:53 jnemeth Exp $ */ +/* $NetBSD: biosboot.c,v 1.7.4.1 2015/06/02 19:49:38 snj Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -31,28 +31,32 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __RCSID -__RCSID("$NetBSD: biosboot.c,v 1.7 2013/11/27 01:47:53 jnemeth Exp $"); +__RCSID("$NetBSD: biosboot.c,v 1.7.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> +#ifdef DIOCGWEDGEINFO #include <sys/disk.h> +#endif #include <sys/param.h> #include <sys/bootblock.h> #include <err.h> #include <fcntl.h> -#include <inttypes.h> #include <paths.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <util.h> #include "map.h" #include "gpt.h" @@ -65,8 +69,10 @@ static uint64_t size; static char *bootpath; static unsigned int entry; +static uint8_t *label; -const char biosbootmsg[] = "biosboot [-c bootcode] [-i index] device ..."; +const char biosbootmsg[] = "biosboot [-c bootcode] [-i index] " + "[-L label] device ..."; __dead static void usage_biosboot(void) @@ -138,7 +144,7 @@ biosboot(int fd) struct mbr *mbr, *bootcode; struct gpt_hdr *hdr; struct gpt_ent *ent; - int i; + unsigned int i, j; /* * Parse and validate partition maps @@ -196,8 +202,13 @@ biosboot(int fd) if (entry > 0 && m->map_index == entry) break; + if (label != NULL) + if (strcmp((char *)label, + (char *)utf16_to_utf8(ent->ent_name)) == 0) + break; + /* next, partition as could be specified by wedge */ - if (entry < 1 && size > 0 && + if (entry < 1 && label == NULL && size > 0 && m->map_start == start && m->map_size == (off_t)size) break; } @@ -212,7 +223,7 @@ biosboot(int fd) hdr = gpt->map_data; - for (uint32_t j = 0; j < le32toh(hdr->hdr_entries); j++) { + 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; } @@ -231,7 +242,7 @@ biosboot(int fd) hdr = tpg->map_data; - for (uint32_t j = 0; j < le32toh(hdr->hdr_entries); j++) { + 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; } @@ -252,18 +263,22 @@ biosboot(int fd) warnx("error: cannot update Protective MBR"); return; } + + printf("partition %d marked as bootable\n", i + 1); } int cmd_biosboot(int argc, char *argv[]) { +#ifdef DIOCGWEDGEINFO struct dkwedge_info dkw; +#endif struct stat sb; char devpath[MAXPATHLEN]; char *dev, *p; int ch, fd; - while ((ch = getopt(argc, argv, "c:i:")) != -1) { + while ((ch = getopt(argc, argv, "c:i:L:")) != -1) { switch(ch) { case 'c': if (bootpath != NULL) @@ -278,6 +293,11 @@ cmd_biosboot(int argc, char *argv[]) if (*p != 0 || entry < 1) usage_biosboot(); break; + case 'L': + if (label != NULL) + usage_biosboot(); + label = (uint8_t *)strdup(optarg); + break; default: usage_biosboot(); } Index: src/sbin/gpt/create.c diff -u src/sbin/gpt/create.c:1.7 src/sbin/gpt/create.c:1.7.4.1 --- src/sbin/gpt/create.c:1.7 Wed Dec 4 20:15:51 2013 +++ src/sbin/gpt/create.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.7 2013/12/04 20:15:51 jakllsch Exp $"); +__RCSID("$NetBSD: create.c,v 1.7.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -62,7 +66,6 @@ usage_create(void) static void create(int fd) { - uuid_t uuid; off_t blocks, last; map_t *gpt, *tpg; map_t *tbl, *lbt; @@ -99,7 +102,7 @@ create(int fd) return; } mbr = gpt_read(fd, 0LL, 1); - bzero(mbr, sizeof(*mbr)); + 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; @@ -166,13 +169,12 @@ create(int fd) hdr = 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_SIZE); + hdr->hdr_size = htole32(GPT_HDR_SIZE); hdr->hdr_lba_self = htole64(gpt->map_start); hdr->hdr_lba_alt = htole64(last); hdr->hdr_lba_start = htole64(tbl->map_start + blocks); hdr->hdr_lba_end = htole64(last - blocks - 1LL); - uuid_create(&uuid, NULL); - le_uuid_enc(hdr->hdr_uuid, &uuid); + gpt_uuid_generate(hdr->hdr_guid); hdr->hdr_lba_table = htole64(tbl->map_start); hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent)); if (le32toh(hdr->hdr_entries) > parts) @@ -181,8 +183,7 @@ create(int fd) ent = tbl->map_data; for (i = 0; i < le32toh(hdr->hdr_entries); i++) { - uuid_create(&uuid, NULL); - le_uuid_enc(ent[i].ent_uuid, &uuid); + gpt_uuid_generate(ent[i].ent_guid); } hdr->hdr_crc_table = htole32(crc32(ent, le32toh(hdr->hdr_entries) * Index: src/sbin/gpt/destroy.c diff -u src/sbin/gpt/destroy.c:1.4 src/sbin/gpt/destroy.c:1.4.20.1 --- src/sbin/gpt/destroy.c:1.4 Sat Aug 27 17:38:16 2011 +++ src/sbin/gpt/destroy.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.4 2011/08/27 17:38:16 joerg Exp $"); +__RCSID("$NetBSD: destroy.c,v 1.4.20.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -76,12 +80,12 @@ destroy(int fd) } if (pri_hdr != NULL) { - bzero(pri_hdr->map_data, secsz); + memset(pri_hdr->map_data, 0, secsz); gpt_write(fd, pri_hdr); } if (!recoverable && sec_hdr != NULL) { - bzero(sec_hdr->map_data, secsz); + memset(sec_hdr->map_data, 0, secsz); gpt_write(fd, sec_hdr); } } Index: src/sbin/gpt/recover.c diff -u src/sbin/gpt/recover.c:1.4 src/sbin/gpt/recover.c:1.4.20.1 --- src/sbin/gpt/recover.c:1.4 Sat Aug 27 17:38:16 2011 +++ src/sbin/gpt/recover.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.4 2011/08/27 17:38:16 joerg Exp $"); +__RCSID("$NetBSD: recover.c,v 1.4.20.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> Index: src/sbin/gpt/gpt.8 diff -u src/sbin/gpt/gpt.8:1.28 src/sbin/gpt/gpt.8:1.28.4.1 --- src/sbin/gpt/gpt.8:1.28 Thu Dec 19 07:49:50 2013 +++ src/sbin/gpt/gpt.8 Tue Jun 2 19:49:38 2015 @@ -1,4 +1,4 @@ -.\" $NetBSD: gpt.8,v 1.28 2013/12/19 07:49:50 wiz Exp $ +.\" $NetBSD: gpt.8,v 1.28.4.1 2015/06/02 19:49:38 snj Exp $ .\" .\" Copyright (c) 2002 Marcel Moolenaar .\" All rights reserved. @@ -26,7 +26,7 @@ .\" .\" $FreeBSD: src/sbin/gpt/gpt.8,v 1.17 2006/06/22 22:22:32 marcel Exp $ .\" -.Dd December 19, 2013 +.Dd December 6, 2014 .Dt GPT 8 .Os .Sh NAME @@ -68,6 +68,12 @@ Not all commands use all default setting have an effect on all commands. .Pp The +.Fl m Ar mediasize +option overrides the default media size for the device (obtained +from the kernel if possible) or defaulting to the file size for +plain files. +.Pp +The .Fl p Ar partitions option allows the user to change the number of partitions the GPT can accommodate. @@ -87,6 +93,13 @@ command, but the intent is to use it to implement dry-run behaviour. .Pp The +.Fl s Ar sectorsize +option overrides the default sector size for the device (obtained +from the kernel if possible) or +.Dv 512 +for plain files. +.Pp +The .Fl v option controls the verbosity level. The level increases with every occurrence of this option. @@ -145,11 +158,50 @@ option allows the user to specify the pa The type is given as an UUID, but .Nm accepts -.Cm efi , swap , ufs , hfs , linux , -.Cm raid , lfs , ccd , cgd , bios , -.Cm ffs , -and -.Cm windows +.Bl -tag -width "windows-reserved" -compact -offset indent +.It Cm apple +Apple HFS +.It Cm apple-ufs +Apple UFS +.It Cm bios +BIOS Boot +.It Cm efi +EFI System +.It Cm fbsd-legacy +FreeBSD legacy +.It Cm fbsd-swap +FreeBSD swap +.It Cm fbsd-ufs +FreeBSD UFS/UFS2 +.It Cm fbsd-vinum +FreeBSD vinum +.It Cm fbsd-zfs +FreeBSD ZFS +.It Cm linux-data +Linux data +.It Cm linux-raid +Linux RAID +.It Cm linux-swap +Linux swap +.It Cm linux-lvm +Linux LVM +.It Cm windows +Windows basic data +.It Cm windows-reserved +Windows reserved +.It Cm ccd +NetBSD ccd component +.It Cm cgd +NetBSD Cryptographic Disk +.It Cm ffs +NetBSD FFSv1/FFSv2 +.It Cm lfs +NetBSD LFS +.It Cm raid +NetBSD RAIDFrame component +.It Cm swap +NetBSD swap +.El as aliases for the most commonly used partition types. .\" ==== backup ==== .It Nm Ic backup Ar device ... @@ -162,7 +214,8 @@ command. The format is a plist. It should not be modified. .\" ==== biosboot ==== -.It Nm Ic biosboot Oo Fl c Ar bootcode Oc Oo Fl i Ar index Oc Ar device ... +.It Nm Ic biosboot Oo Fl c Ar bootcode Oc Oo Fl i Ar index Oc \ +Oo Fl L Ar label Oc Ar device ... The .Ic biosboot command allows the user to configure the partition that contains the @@ -182,6 +235,11 @@ The option selects the partition that should contain the primary bootstrap code, as installed via .Xr installboot 8 . +The +.Fl L +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 ... The @@ -216,7 +274,7 @@ to destroy the table in a way that it ca .\" ==== label ==== .It Nm Ic label Oo Fl a Oc Ao Fl f Ar file | Fl l Ar label Ac Ar device ... .It Nm Ic label Oo Fl b Ar blocknr Oc Oo Fl i Ar index Oc \ -Oo Fl s Ar sectors Oc Oo Fl t Ar type Oc \ +Oo Fl L Ar label Oc Oo Fl s Ar sectors Oc Oo Fl t Ar type Oc \ Ao Fl f Ar file | Fl l Ar label Ac Ar device ... The .Ic label @@ -237,6 +295,11 @@ The option selects the partition with the given partition number. .Pp The +.Fl L Ar label +option selects all partitions that have the given label. +This can cause multiple partitions to be relabeled. +.Pp +The .Fl s Ar sectors option selects all partitions that have the given size. This can cause multiple partitions to be labeled. @@ -320,7 +383,7 @@ It is very useful in case the primary la .\" ==== remove ==== .It Nm Ic remove Oo Fl a Oc Ar device ... .It Nm Ic remove Oo Fl b Ar blocknr Oc Oo Fl i Ar index Oc \ -Oo Fl s Ar sectors Oc Oo Fl t Ar type Oc Ar device ... +Oo Fl L Ar label Oc Oo Fl s Ar sectors Oc Oo Fl t Ar type Oc Ar device ... The .Ic remove command allows the user to remove any and all partitions that match the @@ -354,6 +417,52 @@ If the .Fl a option is specified then the size will be adjusted to be a multiple of alignment if possible. +.\" ==== resizedisk ==== +.It Nm Ic resizedisk Oo Fl s Ar size Oc Ar device ... +The +.Ic resizedisk +command allows the user to resize a disk. +With GPTs, a backup copy is stored at the end of the disk. +If the underlying medium changes size +.Pq or is going to change size , +then the backup copy needs to be moved to the new end of the disk, +and the last sector available for data storage needs to be adjusted. +This command does that. +If the backup copy no longer exists due to the medium shrinking, then +a new backup copy will be created using the primary copy. +.Pp +The +.Fl s +option allows the new size to be specified, otherwise the backup copy +will automatically be placed at the current end of the disk. +If there is no suffix, or the suffix is +.Sq s +or +.Sq S +then size is in sectors, otherwise size is in bytes which must be +a multiple of the device's sector size. +Using the +.Fl s +option allows you to move the backup copy prior to resizing the medium. +This is primarily useful when shrinking the medium. +.\" ==== restore ==== +.It Nm Ic restore Oo Fl F Oc Ar device ... +The +.Ic restore +command restores a partition table that was previously saved using the +.Ic backup +command. +The partition table is read from standard input and is expected to be in +the format of a plist. +It assumes an empty disk. +The +.Fl F +option can be used to blank the disk. +The new disk does not have to be the same size as the old disk as long as all +the partitions fit, as +.Ic restore +will automatically adjust. +However, the new disk must use the same sector size as the old disk. .\" ==== set ==== .It Nm Ic set Fl a Ar attribute Fl i Ar index Ar device ... The @@ -411,6 +520,19 @@ The order of precedence for the options .Fl l , .Fl g , .Fl u . +.\" ==== type ==== +.It Nm Ic type Oo Fl a Oc Fl T Ar newtype Ar device ... +.It Nm Ic type Oo Fl b Ar blocknr Oc Oo Fl i Ar index Oc \ +Oo Fl L Ar label Oc Oo Fl s Ar sectors Oc Oo Fl t Ar type Oc \ +Fl T Ar newtype Ar device ... +The +.Ic type +command allows the user to change the type of any and all partitions +that match the selection. +It uses the same selection options as the +.Ic label +command. +See above for a description of these options. .\" ==== unset ==== .It Nm Ic unset Fl a Ar attribute Fl i Ar index Ar device ... The Index: src/sbin/gpt/gpt.c diff -u src/sbin/gpt/gpt.c:1.28 src/sbin/gpt/gpt.c:1.28.2.1 --- src/sbin/gpt/gpt.c:1.28 Sun Aug 10 18:27:15 2014 +++ src/sbin/gpt/gpt.c Tue Jun 2 19:49:38 2015 @@ -26,17 +26,20 @@ * CRC32 code derived from work by Gary S. Brown. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.28 2014/08/10 18:27:15 jnemeth Exp $"); +__RCSID("$NetBSD: gpt.c,v 1.28.2.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/param.h> #include <sys/types.h> -#include <sys/disk.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/bootblock.h> @@ -50,17 +53,14 @@ __RCSID("$NetBSD: gpt.c,v 1.28 2014/08/1 #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <util.h> #include <ctype.h> -#include <prop/proplib.h> -#include <sys/drvctlio.h> #include "map.h" #include "gpt.h" char device_path[MAXPATHLEN]; const char *device_arg; -char *device_name; +const char *device_name; off_t mediasz; @@ -240,98 +240,6 @@ utf8_to_utf16(const uint8_t *s8, uint16_ } while (c != 0); } -int -parse_uuid(const char *s, uuid_t *uuid) -{ - uint32_t status; - - uuid_from_string(s, uuid, &status); - if (status == uuid_s_ok) - return (0); - - switch (*s) { - case 'b': - if (strcmp(s, "bios") == 0) { - static const uuid_t bios = GPT_ENT_TYPE_BIOS; - *uuid = bios; - return (0); - } - break; - case 'c': - if (strcmp(s, "ccd") == 0) { - static const uuid_t ccd = GPT_ENT_TYPE_NETBSD_CCD; - *uuid = ccd; - return (0); - } else if (strcmp(s, "cgd") == 0) { - static const uuid_t cgd = GPT_ENT_TYPE_NETBSD_CGD; - *uuid = cgd; - return (0); - } - break; - case 'e': - if (strcmp(s, "efi") == 0) { - static const uuid_t efi = GPT_ENT_TYPE_EFI; - *uuid = efi; - return (0); - } - break; - case 'f': - if (strcmp(s, "ffs") == 0) { - static const uuid_t nb_ffs = GPT_ENT_TYPE_NETBSD_FFS; - *uuid = nb_ffs; - return (0); - } - break; - case 'h': - if (strcmp(s, "hfs") == 0) { - static const uuid_t hfs = GPT_ENT_TYPE_APPLE_HFS; - *uuid = hfs; - return (0); - } - break; - case 'l': - if (strcmp(s, "lfs") == 0) { - static const uuid_t lfs = GPT_ENT_TYPE_NETBSD_LFS; - *uuid = lfs; - return (0); - } else if (strcmp(s, "linux") == 0) { - static const uuid_t lnx = GPT_ENT_TYPE_LINUX_DATA; - *uuid = lnx; - return (0); - } - break; - case 'r': - if (strcmp(s, "raid") == 0) { - static const uuid_t raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME; - *uuid = raid; - return (0); - } - break; - case 's': - if (strcmp(s, "swap") == 0) { - static const uuid_t sw = GPT_ENT_TYPE_NETBSD_SWAP; - *uuid = sw; - return (0); - } - break; - case 'u': - if (strcmp(s, "ufs") == 0) { - static const uuid_t ufs = GPT_ENT_TYPE_NETBSD_FFS; - *uuid = ufs; - return (0); - } - break; - case 'w': - if (strcmp(s, "windows") == 0) { - static const uuid_t win = GPT_ENT_TYPE_MS_BASIC_DATA; - *uuid = win; - return (0); - } - break; - } - return (EINVAL); -} - void* gpt_read(int fd, off_t lba, size_t count) { @@ -451,97 +359,13 @@ gpt_mbr(int fd, off_t lba) return (0); } -static int -drvctl(const char *name, u_int *sector_size, off_t *media_size) -{ - prop_dictionary_t command_dict, args_dict, results_dict, data_dict, - disk_info, geometry; - prop_string_t string; - prop_number_t number; - int dfd, res; - char *dname, *p; - - if ((dfd = open("/dev/drvctl", O_RDONLY)) == -1) { - warn("%s: /dev/drvctl", __func__); - return -1; - } - - command_dict = prop_dictionary_create(); - args_dict = prop_dictionary_create(); - - string = prop_string_create_cstring_nocopy("get-properties"); - prop_dictionary_set(command_dict, "drvctl-command", string); - prop_object_release(string); - - if ((dname = strdup(name[0] == 'r' ? name + 1 : name)) == NULL) { - (void)close(dfd); - return -1; - } - for (p = dname; *p; p++) - continue; - for (--p; p >= dname && !isdigit((unsigned char)*p); *p-- = '\0') - continue; - - string = prop_string_create_cstring(dname); - free(dname); - prop_dictionary_set(args_dict, "device-name", string); - prop_object_release(string); - - prop_dictionary_set(command_dict, "drvctl-arguments", args_dict); - prop_object_release(args_dict); - - res = prop_dictionary_sendrecv_ioctl(command_dict, dfd, DRVCTLCOMMAND, - &results_dict); - (void)close(dfd); - prop_object_release(command_dict); - if (res) { - warn("%s: prop_dictionary_sendrecv_ioctl", __func__); - errno = res; - return -1; - } - - number = prop_dictionary_get(results_dict, "drvctl-error"); - if ((errno = prop_number_integer_value(number)) != 0) - return -1; - - data_dict = prop_dictionary_get(results_dict, "drvctl-result-data"); - if (data_dict == NULL) - goto out; - - disk_info = prop_dictionary_get(data_dict, "disk-info"); - if (disk_info == NULL) - goto out; - - geometry = prop_dictionary_get(disk_info, "geometry"); - if (geometry == NULL) - goto out; - - number = prop_dictionary_get(geometry, "sector-size"); - if (number == NULL) - goto out; - - *sector_size = prop_number_integer_value(number); - - number = prop_dictionary_get(geometry, "sectors-per-unit"); - if (number == NULL) - goto out; - - *media_size = prop_number_integer_value(number) * *sector_size; - - return 0; -out: - errno = EINVAL; - return -1; -} - -static int +int gpt_gpt(int fd, off_t lba, int found) { - uuid_t type; off_t size; struct gpt_ent *ent; struct gpt_hdr *hdr; - char *p, *s; + char *p; map_t *m; size_t blocks, tblsz; unsigned int i; @@ -606,19 +430,19 @@ gpt_gpt(int fd, off_t lba, int found) for (i = 0; i < le32toh(hdr->hdr_entries); i++) { ent = (void*)(p + i * le32toh(hdr->hdr_entsz)); - if (uuid_is_nil((uuid_t *)&ent->ent_type, NULL)) + if (gpt_uuid_is_nil(ent->ent_type)) continue; size = le64toh(ent->ent_lba_end) - le64toh(ent->ent_lba_start) + 1LL; if (verbose > 2) { - le_uuid_dec(&ent->ent_type, &type); - uuid_to_string(&type, &s, NULL); - warnx( - "%s: GPT partition: type=%s, start=%llu, size=%llu", device_name, s, + 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); - free(s); } m = map_add(le64toh(ent->ent_lba_start), size, MAP_TYPE_GPT_PART, ent); @@ -644,7 +468,7 @@ gpt_open(const char *dev) mode = readonly ? O_RDONLY : O_RDWR|O_EXCL; - device_arg = dev; + device_arg = device_name = dev; fd = opendisk(dev, mode, device_path, sizeof(device_path), 0); if (fd == -1) return -1; @@ -658,19 +482,25 @@ gpt_open(const char *dev) if ((sb.st_mode & S_IFMT) != S_IFREG) { #ifdef DIOCGSECTORSIZE - if (ioctl(fd, DIOCGSECTORSIZE, &secsz) == -1 || - ioctl(fd, DIOCGMEDIASIZE, &mediasz) == -1) + if ((secsz == 0 && ioctl(fd, DIOCGSECTORSIZE, &secsz) == -1) || + (mediasz == 0 && ioctl(fd, DIOCGMEDIASIZE, &mediasz) == -1)) goto close; -#endif - if (drvctl(device_name, &secsz, &mediasz) == -1) +#else + if (getdisksize(device_name, &secsz, &mediasz) == -1) goto close; +#endif + if (secsz == 0 || mediasz == 0) + errx(1, "Please specify sector/media size"); } else { - secsz = 512; /* Fixed size for files. */ - if (sb.st_size % secsz) { - errno = EINVAL; - goto close; + if (secsz == 0) + secsz = 512; /* Fixed size for files. */ + if (mediasz == 0) { + if (sb.st_size % secsz) { + errno = EINVAL; + goto close; + } + mediasz = sb.st_size; } - mediasz = sb.st_size; } /* @@ -717,7 +547,9 @@ static struct { const char *name; } cmdsw[] = { { cmd_add, "add" }, +#ifndef HAVE_NBTOOL_CONFIG_H { cmd_backup, "backup" }, +#endif { cmd_biosboot, "biosboot" }, { cmd_create, "create" }, { cmd_destroy, "destroy" }, @@ -728,9 +560,13 @@ static struct { { cmd_remove, "remove" }, { NULL, "rename" }, { cmd_resize, "resize" }, + { cmd_resizedisk, "resizedisk" }, +#ifndef HAVE_NBTOOL_CONFIG_H { cmd_restore, "restore" }, +#endif { cmd_set, "set" }, { cmd_show, "show" }, + { cmd_type, "type" }, { cmd_unset, "unset" }, { NULL, "verify" }, { NULL, NULL } @@ -739,49 +575,62 @@ static struct { __dead static void usage(void) { - extern const char addmsg1[], addmsg2[], backupmsg[], biosbootmsg[]; + extern const char addmsg1[], addmsg2[], biosbootmsg[]; extern const char createmsg[], destroymsg[], labelmsg1[], labelmsg2[]; extern const char labelmsg3[], migratemsg[], recovermsg[], removemsg1[]; - extern const char removemsg2[], resizemsg[], restoremsg[], setmsg[]; - extern const char showmsg[], unsetmsg[]; + extern const char removemsg2[], resizemsg[], resizediskmsg[]; + extern const char setmsg[], showmsg[], typemsg1[]; + extern const char typemsg2[], typemsg3[], unsetmsg[]; +#ifndef HAVE_NBTOOL_CONFIG_H + extern const char backupmsg[], restoremsg[]; +#endif + const char *p = getprogname(); + const char *f = + "[-rv] [-m <mediasize>] [-p <partitionnum>] [-s <sectorsize>]"; fprintf(stderr, - "usage: %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %*s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n" - " %s %s\n", - getprogname(), addmsg1, - getprogname(), addmsg2, - getprogname(), backupmsg, - getprogname(), biosbootmsg, - getprogname(), createmsg, - getprogname(), destroymsg, - getprogname(), labelmsg1, - getprogname(), labelmsg2, - (int)strlen(getprogname()), "", labelmsg3, - getprogname(), migratemsg, - getprogname(), recovermsg, - getprogname(), removemsg1, - getprogname(), removemsg2, - getprogname(), resizemsg, - getprogname(), restoremsg, - getprogname(), setmsg, - getprogname(), showmsg, - getprogname(), unsetmsg); + "Usage: %s %s <command> [<args>]\n", p, f); + fprintf(stderr, + "Commands:\n" +#ifndef HAVE_NBTOOL_CONFIG_H + " %s\n" + " %s\n" +#endif + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n" + " %s\n", + addmsg1, addmsg2, +#ifndef HAVE_NBTOOL_CONFIG_H + backupmsg, +#endif + biosbootmsg, createmsg, destroymsg, + labelmsg1, labelmsg2, labelmsg3, + migratemsg, recovermsg, + removemsg1, removemsg2, + resizemsg, resizediskmsg, +#ifndef HAVE_NBTOOL_CONFIG_H + restoremsg, +#endif + setmsg, showmsg, + typemsg1, typemsg2, typemsg3, + unsetmsg); exit(1); } @@ -808,8 +657,15 @@ main(int argc, char *argv[]) int ch, i; /* Get the generic options */ - while ((ch = getopt(argc, argv, "p:rv")) != -1) { + while ((ch = getopt(argc, argv, "m:p:rs:v")) != -1) { switch(ch) { + case 'm': + if (mediasz > 0) + usage(); + mediasz = strtoul(optarg, &p, 10); + if (*p != 0 || mediasz < 1) + usage(); + break; case 'p': if (parts > 0) usage(); @@ -820,6 +676,13 @@ main(int argc, char *argv[]) case 'r': readonly = 1; break; + case 's': + if (secsz > 0) + usage(); + secsz = strtoul(optarg, &p, 10); + if (*p != 0 || secsz < 1) + usage(); + break; case 'v': verbose++; break; Index: src/sbin/gpt/gpt.h diff -u src/sbin/gpt/gpt.h:1.11 src/sbin/gpt/gpt.h:1.11.2.1 --- src/sbin/gpt/gpt.h:1.11 Sun Aug 10 18:27:15 2014 +++ src/sbin/gpt/gpt.h Tue Jun 2 19:49:38 2015 @@ -29,17 +29,14 @@ #ifndef _GPT_H_ #define _GPT_H_ -#include <sys/endian.h> -#include <sys/disklabel_gpt.h> -#define GPT_SIZE GPT_HDR_SIZE -#define hdr_uuid hdr_guid -#define ent_uuid ent_guid - -#include <uuid.h> - -#define le_uuid_dec uuid_dec_le -#define le_uuid_enc uuid_enc_le -int parse_uuid(const char *, uuid_t *); +#ifndef HAVE_NBTOOL_CONFIG_H +#include <util.h> +#else +#include "opendisk.h" +#include "namespace.h" +#endif + +#include "gpt_uuid.h" struct mbr_part { uint8_t part_flag; /* bootstrap flags */ @@ -64,7 +61,7 @@ struct mbr { }; extern const char *device_arg; -extern char *device_name; +extern const char *device_name; extern off_t mediasz; extern u_int parts; extern u_int secsz; @@ -72,6 +69,7 @@ extern int readonly, verbose; uint32_t crc32(const void *, size_t); void gpt_close(int); +int gpt_gpt(int, off_t, int); int gpt_open(const char *); void* gpt_read(int, off_t, size_t); int gpt_write(int, map_t *); @@ -89,9 +87,21 @@ 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 *[]); +#ifndef HAVE_NBTOOL_CONFIG_H +# ifdef USE_DRVCTL +int getdisksize(const char *, u_int *, off_t *); +# else +# include "partutil.h" +# endif +#else +# define getdisksize(a, b, c) 0 +#endif + #endif /* _GPT_H_ */ Index: src/sbin/gpt/label.c diff -u src/sbin/gpt/label.c:1.14 src/sbin/gpt/label.c:1.14.4.1 --- src/sbin/gpt/label.c:1.14 Thu Nov 28 01:37:14 2013 +++ src/sbin/gpt/label.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.14 2013/11/28 01:37:14 jnemeth Exp $"); +__RCSID("$NetBSD: label.c,v 1.14.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -43,15 +47,17 @@ __RCSID("$NetBSD: label.c,v 1.14 2013/11 #include "map.h" #include "gpt.h" +#include "gpt_uuid.h" static int all; -static uuid_t type; +static gpt_uuid_t type; static off_t block, size; static unsigned int entry; -static uint8_t *name; +static uint8_t *name, *xlabel; const char labelmsg1[] = "label -a <-l label | -f file> device ..."; -const char labelmsg2[] = "label [-b blocknr] [-i index] [-s sectors]"; +const char labelmsg2[] = "label [-b blocknr] [-i index] [-L label] " + "[-s sectors]"; const char labelmsg3[] = " [-t uuid] <-l label | -f file> device ..."; __dead static void @@ -68,7 +74,6 @@ usage_label(void) static void label(int fd) { - uuid_t uuid; map_t *gpt, *tpg; map_t *tbl, *lbt; map_t *m; @@ -113,9 +118,14 @@ label(int fd) hdr = gpt->map_data; ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_dec(ent->ent_type, &uuid); - if (!uuid_is_nil(&type, NULL) && - !uuid_equal(&type, &uuid, NULL)) + + 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. */ @@ -184,7 +194,7 @@ cmd_label(int argc, char *argv[]) int64_t human_num; /* Get the label options */ - while ((ch = getopt(argc, argv, "ab:f:i:l:s:t:")) != -1) { + while ((ch = getopt(argc, argv, "ab:f:i:L:l:s:t:")) != -1) { switch(ch) { case 'a': if (all > 0) @@ -212,6 +222,11 @@ cmd_label(int argc, char *argv[]) if (*p != 0 || entry < 1) usage_label(); break; + case 'L': + if (xlabel != NULL) + usage_label(); + xlabel = (uint8_t *)strdup(optarg); + break; case 'l': if (name != NULL) usage_label(); @@ -225,9 +240,9 @@ cmd_label(int argc, char *argv[]) usage_label(); break; case 't': - if (!uuid_is_nil(&type, NULL)) + if (!gpt_uuid_is_nil(type)) usage_label(); - if (parse_uuid(optarg, &type) != 0) + if (gpt_uuid_parse(optarg, type) != 0) usage_label(); break; default: @@ -236,7 +251,8 @@ cmd_label(int argc, char *argv[]) } if (!all ^ - (block > 0 || entry > 0 || size > 0 || !uuid_is_nil(&type, NULL))) + (block > 0 || entry > 0 || xlabel != NULL || size > 0 || + !gpt_uuid_is_nil(type))) usage_label(); if (name == NULL || argc == optind) Index: src/sbin/gpt/migrate.c diff -u src/sbin/gpt/migrate.c:1.14 src/sbin/gpt/migrate.c:1.14.4.1 --- src/sbin/gpt/migrate.c:1.14 Wed Dec 4 20:15:51 2013 +++ src/sbin/gpt/migrate.c Tue Jun 2 19:49:38 2015 @@ -24,18 +24,27 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.14 2013/12/04 20:15:51 jakllsch Exp $"); +__RCSID("$NetBSD: migrate.c,v 1.14.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> #include <sys/param.h> +#ifdef HAVE_NBTOOL_CONFIG_H +#include <nbinclude/sys/bootblock.h> +#include <nbinclude/sys/disklabel.h> +#else #include <sys/bootblock.h> #include <sys/disklabel.h> +#endif #include <err.h> #include <stddef.h> @@ -50,6 +59,7 @@ __RCSID("$NetBSD: migrate.c,v 1.14 2013/ /* * Allow compilation on platforms that do not have a BSD label. * The values are valid for amd64, i386 and ia64 disklabels. + * XXX: use disklabel_params from disklabel.c */ #ifndef LABELOFFSET #define LABELOFFSET 0 @@ -57,6 +67,9 @@ __RCSID("$NetBSD: migrate.c,v 1.14 2013/ #ifndef LABELSECTOR #define LABELSECTOR 1 #endif +#ifndef RAW_PART +#define RAW_PART 3 +#endif /* FreeBSD filesystem types that don't match corresponding NetBSD types */ #define FREEBSD_FS_VINUM 14 @@ -112,31 +125,23 @@ migrate_disklabel(int fd, off_t start, s case FS_UNUSED: continue; case FS_SWAP: { - static const uuid_t swap = GPT_ENT_TYPE_FREEBSD_SWAP; - le_uuid_enc(ent->ent_type, &swap); - utf8_to_utf16((const uint8_t *)"FreeBSD swap partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_FREEBSD_SWAP, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FS_BSDFFS: { - static const uuid_t ufs = GPT_ENT_TYPE_FREEBSD_UFS; - le_uuid_enc(ent->ent_type, &ufs); - utf8_to_utf16((const uint8_t *)"FreeBSD UFS partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_FREEBSD_UFS, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FREEBSD_FS_VINUM: { - static const uuid_t vinum = GPT_ENT_TYPE_FREEBSD_VINUM; - le_uuid_enc(ent->ent_type, &vinum); - utf8_to_utf16((const uint8_t *)"FreeBSD vinum partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_FREEBSD_VINUM, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FREEBSD_FS_ZFS: { - static const uuid_t zfs = GPT_ENT_TYPE_FREEBSD_ZFS; - le_uuid_enc(ent->ent_type, &zfs); - utf8_to_utf16((const uint8_t *)"FreeBSD ZFS partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_FREEBSD_ZFS, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } default: @@ -194,45 +199,33 @@ migrate_netbsd_disklabel(int fd, off_t s case FS_UNUSED: continue; case FS_SWAP: { - static const uuid_t swap = GPT_ENT_TYPE_NETBSD_SWAP; - le_uuid_enc(ent->ent_type, &swap); - utf8_to_utf16((const uint8_t *)"NetBSD swap partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_NETBSD_SWAP, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FS_BSDFFS: { - static const uuid_t ufs = GPT_ENT_TYPE_NETBSD_FFS; - le_uuid_enc(ent->ent_type, &ufs); - utf8_to_utf16((const uint8_t *)"NetBSD FFS partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_NETBSD_FFS, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FS_BSDLFS: { - static const uuid_t zfs = GPT_ENT_TYPE_NETBSD_LFS; - le_uuid_enc(ent->ent_type, &zfs); - utf8_to_utf16((const uint8_t *)"NetBSD LFS partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_NETBSD_LFS, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FS_RAID: { - static const uuid_t zfs = GPT_ENT_TYPE_NETBSD_RAIDFRAME; - le_uuid_enc(ent->ent_type, &zfs); - utf8_to_utf16((const uint8_t *)"NetBSD RAIDframe partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_NETBSD_RAIDFRAME, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FS_CCD: { - static const uuid_t zfs = GPT_ENT_TYPE_NETBSD_CCD; - le_uuid_enc(ent->ent_type, &zfs); - utf8_to_utf16((const uint8_t *)"NetBSD CCD partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_NETBSD_CCD, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } case FS_CGD: { - static const uuid_t zfs = GPT_ENT_TYPE_NETBSD_CGD; - le_uuid_enc(ent->ent_type, &zfs); - utf8_to_utf16((const uint8_t *)"NetBSD CGD partition", - ent->ent_name, 36); + gpt_uuid_create(GPT_TYPE_NETBSD_CGD, ent->ent_type, + ent->ent_name, sizeof(ent->ent_name)); break; } default: @@ -257,7 +250,6 @@ migrate_netbsd_disklabel(int fd, off_t s static void migrate(int fd) { - uuid_t uuid; off_t blocks, last; map_t *gpt, *tpg; map_t *tbl, *lbt; @@ -338,13 +330,12 @@ migrate(int fd) * 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_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); - uuid_create(&uuid, NULL); - le_uuid_enc(hdr->hdr_uuid, &uuid); + gpt_uuid_generate(hdr->hdr_guid); hdr->hdr_lba_table = htole64(tbl->map_start); hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent)); if (le32toh(hdr->hdr_entries) > parts) @@ -353,8 +344,7 @@ migrate(int fd) ent = tbl->map_data; for (i = 0; i < le32toh(hdr->hdr_entries); i++) { - uuid_create(&uuid, NULL); - le_uuid_enc(ent[i].ent_uuid, &uuid); + gpt_uuid_generate(ent[i].ent_guid); } /* Mirror partitions. */ @@ -369,12 +359,11 @@ migrate(int fd) continue; case MBR_PTYPE_386BSD: { /* FreeBSD */ if (slice) { - static const uuid_t freebsd = GPT_ENT_TYPE_FREEBSD; - le_uuid_enc(ent->ent_type, &freebsd); + gpt_uuid_create(GPT_TYPE_FREEBSD, + ent->ent_type, ent->ent_name, + sizeof(ent->ent_name)); ent->ent_lba_start = htole64((uint64_t)start); ent->ent_lba_end = htole64(start + size - 1LL); - utf8_to_utf16((const uint8_t *)"FreeBSD disklabel partition", - ent->ent_name, 36); ent++; } else ent = migrate_disklabel(fd, start, ent); @@ -384,12 +373,11 @@ migrate(int fd) ent = migrate_netbsd_disklabel(fd, start, ent); break; case MBR_PTYPE_EFI: { - static const uuid_t efi_slice = GPT_ENT_TYPE_EFI; - le_uuid_enc(ent->ent_type, &efi_slice); + gpt_uuid_create(GPT_TYPE_EFI, + ent->ent_type, ent->ent_name, + sizeof(ent->ent_name)); ent->ent_lba_start = htole64((uint64_t)start); ent->ent_lba_end = htole64(start + size - 1LL); - utf8_to_utf16((const uint8_t *)"EFI system partition", - ent->ent_name, 36); ent++; break; } @@ -429,7 +417,7 @@ migrate(int fd) /* * Turn the MBR into a Protective MBR. */ - bzero(mbr->mbr_part, sizeof(mbr->mbr_part)); + 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; Index: src/sbin/gpt/map.c diff -u src/sbin/gpt/map.c:1.6 src/sbin/gpt/map.c:1.6.4.1 --- src/sbin/gpt/map.c:1.6 Wed Nov 27 20:40:48 2013 +++ src/sbin/gpt/map.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.6 2013/11/27 20:40:48 christos Exp $"); +__RCSID("$NetBSD: map.c,v 1.6.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> Index: src/sbin/gpt/remove.c diff -u src/sbin/gpt/remove.c:1.12 src/sbin/gpt/remove.c:1.12.4.1 --- src/sbin/gpt/remove.c:1.12 Thu Nov 28 01:37:14 2013 +++ src/sbin/gpt/remove.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.12 2013/11/28 01:37:14 jnemeth Exp $"); +__RCSID("$NetBSD: remove.c,v 1.12.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -45,13 +49,14 @@ __RCSID("$NetBSD: remove.c,v 1.12 2013/1 #include "gpt.h" static int all; -static uuid_t type; +static gpt_uuid_t type; static off_t block, size; static unsigned int entry; +static uint8_t *label; const char removemsg1[] = "remove -a device ..."; -const char removemsg2[] = "remove [-b blocknr] [-i index] [-s sectors] " - "[-t type] device ..."; +const char removemsg2[] = "remove [-b blocknr] [-i index] [-L label] " + "[-s sectors] [-t type] device ..."; __dead static void usage_remove(void) @@ -67,7 +72,6 @@ usage_remove(void) static void rem(int fd) { - uuid_t uuid; map_t *gpt, *tpg; map_t *tbl, *lbt; map_t *m; @@ -112,14 +116,18 @@ rem(int fd) hdr = gpt->map_data; ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_dec(ent->ent_type, &uuid); - if (!uuid_is_nil(&type, NULL) && - !uuid_equal(&type, &uuid, NULL)) + + 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. */ - uuid_create_nil(&uuid, NULL); - le_uuid_enc(ent->ent_type, &uuid); + 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))); @@ -134,7 +142,7 @@ rem(int fd) le32toh(hdr->hdr_entsz)); /* Remove the secondary entry. */ - le_uuid_enc(ent->ent_type, &uuid); + 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))); @@ -156,7 +164,7 @@ cmd_remove(int argc, char *argv[]) int64_t human_num; /* Get the remove options */ - while ((ch = getopt(argc, argv, "ab:i:s:t:")) != -1) { + while ((ch = getopt(argc, argv, "ab:i:L:s:t:")) != -1) { switch(ch) { case 'a': if (all > 0) @@ -179,6 +187,11 @@ cmd_remove(int argc, char *argv[]) if (*p != 0 || entry < 1) usage_remove(); break; + case 'L': + if (label != NULL) + usage_remove(); + label = (uint8_t *)strdup(optarg); + break; case 's': if (size > 0) usage_remove(); @@ -187,9 +200,9 @@ cmd_remove(int argc, char *argv[]) usage_remove(); break; case 't': - if (!uuid_is_nil(&type, NULL)) + if (!gpt_uuid_is_nil(type)) usage_remove(); - if (parse_uuid(optarg, &type) != 0) + if (gpt_uuid_parse(optarg, type) != 0) usage_remove(); break; default: @@ -198,7 +211,8 @@ cmd_remove(int argc, char *argv[]) } if (!all ^ - (block > 0 || entry > 0 || size > 0 || !uuid_is_nil(&type, NULL))) + (block > 0 || entry > 0 || label != NULL || size > 0 || + !gpt_uuid_is_nil(type))) usage_remove(); if (argc == optind) Index: src/sbin/gpt/resize.c diff -u src/sbin/gpt/resize.c:1.8 src/sbin/gpt/resize.c:1.8.6.1 --- src/sbin/gpt/resize.c:1.8 Tue Dec 10 01:05:00 2013 +++ src/sbin/gpt/resize.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.8 2013/12/10 01:05:00 jnemeth Exp $"); +__RCSID("$NetBSD: resize.c,v 1.8.6.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -40,7 +44,6 @@ __RCSID("$NetBSD: resize.c,v 1.8 2013/12 #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <inttypes.h> #include "map.h" #include "gpt.h" @@ -62,7 +65,6 @@ usage_resize(void) static void resize(int fd) { - uuid_t uuid; map_t *gpt, *tpg; map_t *tbl, *lbt; map_t *map; @@ -104,8 +106,7 @@ resize(int fd) i = entry - 1; ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_dec(ent->ent_type, &uuid); - if (uuid_is_nil(&uuid, NULL)) { + if (gpt_uuid_is_nil(ent->ent_type)) { warnx("%s: error: entry at index %u is unused", device_name, entry); return; Index: src/sbin/gpt/restore.c diff -u src/sbin/gpt/restore.c:1.1 src/sbin/gpt/restore.c:1.1.2.1 --- src/sbin/gpt/restore.c:1.1 Sun Aug 10 18:27:15 2014 +++ src/sbin/gpt/restore.c Tue Jun 2 19:49:38 2015 @@ -24,16 +24,21 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.1 2014/08/10 18:27:15 jnemeth Exp $"); +__RCSID("$NetBSD: restore.c,v 1.1.2.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> #include <sys/bootblock.h> +#include <sys/disklabel_gpt.h> #include <err.h> #include <stddef.h> @@ -41,12 +46,12 @@ __RCSID("$NetBSD: restore.c,v 1.1 2014/0 #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <prop/proplib.h> #include "map.h" #include "gpt.h" static int force; -static int primary_only; const char restoremsg[] = "restore [-F] device ..."; @@ -59,25 +64,39 @@ usage_restore(void) exit(1); } +#define PROP_ERR(x) if (!(x)) { \ + warn("proplib failure"); \ + return; \ + } + static void restore(int fd) { - uuid_t uuid; - off_t blocks, last; - map_t *gpt, *tpg; - map_t *tbl, *lbt; + gpt_uuid_t gpt_guid, uuid; + off_t firstdata, last, lastdata, gpe_start, gpe_end; map_t *map; struct mbr *mbr; struct gpt_hdr *hdr; - struct gpt_ent *ent; + struct gpt_ent ent; unsigned int i; + prop_dictionary_t props, gpt_dict, mbr_dict, type_dict; + prop_object_iterator_t propiter; + prop_data_t propdata; + prop_array_t mbr_array, gpt_array; + prop_number_t propnum; + prop_string_t propstr; + int entries, gpt_size; + const char *s; + void *secbuf; last = mediasz / 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 (!force) { + warnx("%s: error: device contains a GPT", device_name); + return; + } } map = map_find(MAP_TYPE_MBR); if (map != NULL) { @@ -85,131 +104,284 @@ restore(int fd) warnx("%s: error: device contains a MBR", device_name); return; } - /* Nuke the MBR in our internal map. */ map->map_type = MAP_TYPE_UNUSED; } - /* - * 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; - } - mbr = gpt_read(fd, 0LL, 1); - bzero(mbr, 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); + props = prop_dictionary_internalize_from_file("/dev/stdin"); + if (props == NULL) { + warnx("error: unable to read/parse backup file"); + return; + } + + 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); + prop_object_release(props); + return; } - /* Get the amount of free space after the MBR */ - blocks = map_free(1LL, 0LL); - if (blocks == 0LL) { - warnx("%s: error: no room for the GPT header", device_name); + gpt_dict = prop_dictionary_get(props, "GPT_HDR"); + PROP_ERR(gpt_dict); + + 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"); + prop_object_release(gpt_dict); + prop_object_release(props); return; } - /* 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) - blocks++; - blocks++; /* Don't forget the header itself */ + 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++; + + 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\n", s); + return; } + firstdata = gpt_size + 2; /* PMBR and GPT header */ + lastdata = last - gpt_size - 1; /* alt. GPT table and header */ - /* Never cross the median of the device. */ - if ((blocks + 1LL) > ((last + 1LL) >> 1)) - blocks = ((last + 1LL) >> 1) - 1LL; + type_dict = prop_dictionary_get(props, "GPT_TBL"); + PROP_ERR(type_dict); + gpt_array = prop_dictionary_get(type_dict, "gpt_array"); + PROP_ERR(gpt_array); + propiter = prop_array_iterator(gpt_array); + PROP_ERR(propiter); + while ((gpt_dict = prop_object_iterator_next(propiter)) != NULL) { + propstr = prop_dictionary_get(gpt_dict, "type"); + 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\n", s); + return; + } + if (gpt_uuid_is_nil(uuid)) + continue; + propnum = prop_dictionary_get(gpt_dict, "start"); + PROP_ERR(propnum); + gpe_start = prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(gpt_dict, "end"); + 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; + } + } + prop_object_iterator_release(propiter); - /* - * Get the amount of free space at the end of the device and - * calculate the size for the GPT structures. - */ - map = map_last(); - if (map->map_type != MAP_TYPE_UNUSED) { - warnx("%s: error: no room for the backup header", device_name); + secbuf = calloc(gpt_size + 1, secsz); /* GPT TABLE + GPT HEADER */ + if (secbuf == NULL) { + warnx("not enough memory to create a sector buffer"); return; } - if (map->map_size < blocks) - blocks = map->map_size; - if (blocks == 1LL) { - warnx("%s: error: no room for the GPT table", device_name); + if (lseek(fd, 0LL, SEEK_SET) == -1) { + warnx("%s: error: can't seek to beginning", device_name); return; } + for (i = 0; i < firstdata; i++) { + if (write(fd, secbuf, secsz) == -1) { + warnx("%s: error: can't write", device_name); + return; + } + } + if (lseek(fd, (lastdata + 1) * secsz, SEEK_SET) == -1) { + warnx("%s: error: can't seek to end", device_name); + return; + } + for (i = lastdata + 1; i <= last; i++) { + if (write(fd, secbuf, secsz) == -1) { + warnx("%s: error: can't write", device_name); + return; + } + } - 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) + mbr = (struct mbr *)secbuf; + type_dict = prop_dictionary_get(props, "MBR"); + PROP_ERR(type_dict); + propdata = prop_dictionary_get(type_dict, "code"); + PROP_ERR(propdata); + memcpy(mbr->mbr_code, prop_data_data_nocopy(propdata), + sizeof(mbr->mbr_code)); + mbr_array = prop_dictionary_get(type_dict, "mbr_array"); + PROP_ERR(mbr_array); + propiter = prop_array_iterator(mbr_array); + PROP_ERR(propiter); + while ((mbr_dict = prop_object_iterator_next(propiter)) != NULL) { + propnum = prop_dictionary_get(mbr_dict, "index"); + PROP_ERR(propnum); + i = prop_number_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "flag"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_flag = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "start_head"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_shd = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "start_sector"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_ssect = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "start_cylinder"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_scyl = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "type"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_typ = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "end_head"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_ehd = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "end_sector"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_esect = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "end_cylinder"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_ecyl = + prop_number_unsigned_integer_value(propnum); + propnum = prop_dictionary_get(mbr_dict, "lba_start_low"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_start_lo = + htole16(prop_number_unsigned_integer_value(propnum)); + propnum = prop_dictionary_get(mbr_dict, "lba_start_high"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_start_hi = + htole16(prop_number_unsigned_integer_value(propnum)); + /* adjust PMBR size to size of device */ + if (mbr->mbr_part[i].part_typ == MBR_PTYPE_PMBR) { + 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); + } + } else { + propnum = prop_dictionary_get(mbr_dict, "lba_size_low"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_size_lo = + htole16(prop_number_unsigned_integer_value(propnum)); + propnum = + prop_dictionary_get(mbr_dict, "lba_size_high"); + PROP_ERR(propnum); + mbr->mbr_part[i].part_size_hi = + htole16(prop_number_unsigned_integer_value(propnum)); + } + } + 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; + } + + propiter = prop_array_iterator(gpt_array); + PROP_ERR(propiter); + while ((gpt_dict = prop_object_iterator_next(propiter)) != NULL) { + memset(&ent, 0, sizeof(ent)); + propstr = prop_dictionary_get(gpt_dict, "type"); + 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\n", s); + return; + } + 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\n", s); + return; + } + propnum = prop_dictionary_get(gpt_dict, "start"); + PROP_ERR(propnum); + ent.ent_lba_start = + htole64(prop_number_unsigned_integer_value(propnum)); + propnum = prop_dictionary_get(gpt_dict, "end"); + PROP_ERR(propnum); + ent.ent_lba_end = + htole64(prop_number_unsigned_integer_value(propnum)); + propnum = prop_dictionary_get(gpt_dict, "attributes"); + PROP_ERR(propnum); + ent.ent_attr = + htole64(prop_number_unsigned_integer_value(propnum)); + propstr = prop_dictionary_get(gpt_dict, "name"); + if (propstr != NULL) { + s = prop_string_cstring_nocopy(propstr); + utf8_to_utf16((const uint8_t *)s, ent.ent_name, 36); + } + 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)); + } + 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; + } - hdr = gpt->map_data; + memset(secbuf, 0, secsz); + hdr = (struct gpt_hdr *)secbuf; memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)); hdr->hdr_revision = htole32(GPT_HDR_REVISION); - hdr->hdr_size = htole32(GPT_SIZE); - hdr->hdr_lba_self = htole64(gpt->map_start); + hdr->hdr_size = htole32(GPT_HDR_SIZE); + hdr->hdr_lba_self = htole64(GPT_HDR_BLKNO); hdr->hdr_lba_alt = htole64(last); - hdr->hdr_lba_start = htole64(tbl->map_start + blocks); - hdr->hdr_lba_end = htole64(last - blocks - 1LL); - uuid_create(&uuid, NULL); - le_uuid_enc(hdr->hdr_uuid, &uuid); - hdr->hdr_lba_table = htole64(tbl->map_start); - hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent)); - if (le32toh(hdr->hdr_entries) > parts) - hdr->hdr_entries = htole32(parts); + hdr->hdr_lba_start = htole64(firstdata); + hdr->hdr_lba_end = htole64(lastdata); + gpt_uuid_copy(hdr->hdr_guid, gpt_guid); + 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_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; + } - ent = tbl->map_data; - for (i = 0; i < le32toh(hdr->hdr_entries); i++) { - uuid_create(&uuid, NULL); - le_uuid_enc(ent[i].ent_uuid, &uuid); - } - - 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); - - /* - * 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); + hdr->hdr_lba_self = htole64(last); + hdr->hdr_lba_alt = htole64(GPT_HDR_BLKNO); + 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; } + + prop_object_release(props); + return; } int Index: src/sbin/gpt/set.c diff -u src/sbin/gpt/set.c:1.2 src/sbin/gpt/set.c:1.2.6.1 --- src/sbin/gpt/set.c:1.2 Tue Dec 10 01:05:00 2013 +++ src/sbin/gpt/set.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.2 2013/12/10 01:05:00 jnemeth Exp $"); +__RCSID("$NetBSD: set.c,v 1.2.6.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -40,7 +44,6 @@ __RCSID("$NetBSD: set.c,v 1.2 2013/12/10 #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <inttypes.h> #include "map.h" #include "gpt.h" @@ -62,7 +65,6 @@ usage_set(void) static void set(int fd) { - uuid_t uuid; map_t *gpt, *tpg; map_t *tbl, *lbt; struct gpt_hdr *hdr; @@ -102,8 +104,7 @@ set(int fd) i = entry - 1; ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_dec(ent->ent_type, &uuid); - if (uuid_is_nil(&uuid, NULL)) { + if (gpt_uuid_is_nil(ent->ent_type)) { warnx("%s: error: entry at index %u is unused", device_name, entry); return; Index: src/sbin/gpt/unset.c diff -u src/sbin/gpt/unset.c:1.2 src/sbin/gpt/unset.c:1.2.6.1 --- src/sbin/gpt/unset.c:1.2 Tue Dec 10 01:05:00 2013 +++ src/sbin/gpt/unset.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.2 2013/12/10 01:05:00 jnemeth Exp $"); +__RCSID("$NetBSD: unset.c,v 1.2.6.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -40,7 +44,6 @@ __RCSID("$NetBSD: unset.c,v 1.2 2013/12/ #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <inttypes.h> #include "map.h" #include "gpt.h" @@ -62,7 +65,6 @@ usage_unset(void) static void unset(int fd) { - uuid_t uuid; map_t *gpt, *tpg; map_t *tbl, *lbt; struct gpt_hdr *hdr; @@ -102,8 +104,7 @@ unset(int fd) i = entry - 1; ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz)); - le_uuid_dec(ent->ent_type, &uuid); - if (uuid_is_nil(&uuid, NULL)) { + if (gpt_uuid_is_nil(ent->ent_type)) { warnx("%s: error: entry at index %u is unused", device_name, entry); return; Index: src/sbin/gpt/show.c diff -u src/sbin/gpt/show.c:1.15 src/sbin/gpt/show.c:1.15.4.1 --- src/sbin/gpt/show.c:1.15 Wed Dec 18 03:20:09 2013 +++ src/sbin/gpt/show.c Tue Jun 2 19:49:38 2015 @@ -24,12 +24,16 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + #include <sys/cdefs.h> #ifdef __FBSDID __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.15 2013/12/18 03:20:09 jnemeth Exp $"); +__RCSID("$NetBSD: show.c,v 1.15.4.1 2015/06/02 19:49:38 snj Exp $"); #endif #include <sys/types.h> @@ -60,87 +64,14 @@ usage_show(void) exit(1); } -static const char * -friendly(uuid_t *t) -{ - static const uuid_t efi_slice = GPT_ENT_TYPE_EFI; - static const uuid_t bios_boot = GPT_ENT_TYPE_BIOS; - static const uuid_t msdata = GPT_ENT_TYPE_MS_BASIC_DATA; - static const uuid_t freebsd = GPT_ENT_TYPE_FREEBSD; - static const uuid_t hfs = GPT_ENT_TYPE_APPLE_HFS; - static const uuid_t linuxdata = GPT_ENT_TYPE_LINUX_DATA; - static const uuid_t linuxswap = GPT_ENT_TYPE_LINUX_SWAP; - static const uuid_t msr = GPT_ENT_TYPE_MS_RESERVED; - static const uuid_t swap = GPT_ENT_TYPE_FREEBSD_SWAP; - static const uuid_t ufs = GPT_ENT_TYPE_FREEBSD_UFS; - static const uuid_t vinum = GPT_ENT_TYPE_FREEBSD_VINUM; - static const uuid_t zfs = GPT_ENT_TYPE_FREEBSD_ZFS; - static const uuid_t nb_swap = GPT_ENT_TYPE_NETBSD_SWAP; - static const uuid_t nb_ffs = GPT_ENT_TYPE_NETBSD_FFS; - static const uuid_t nb_lfs = GPT_ENT_TYPE_NETBSD_LFS; - static const uuid_t nb_raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME; - static const uuid_t nb_ccd = GPT_ENT_TYPE_NETBSD_CCD; - static const uuid_t nb_cgd = GPT_ENT_TYPE_NETBSD_CGD; - static char buf[80]; - char *s; - - if (show_uuid) - goto unfriendly; - - if (uuid_equal(t, &efi_slice, NULL)) - return ("EFI System"); - if (uuid_equal(t, &bios_boot, NULL)) - return ("BIOS Boot"); - if (uuid_equal(t, &nb_swap, NULL)) - return ("NetBSD swap"); - if (uuid_equal(t, &nb_ffs, NULL)) - return ("NetBSD FFSv1/FFSv2"); - if (uuid_equal(t, &nb_lfs, NULL)) - return ("NetBSD LFS"); - if (uuid_equal(t, &nb_raid, NULL)) - return ("NetBSD RAIDFrame component"); - if (uuid_equal(t, &nb_ccd, NULL)) - return ("NetBSD ccd component"); - if (uuid_equal(t, &nb_cgd, NULL)) - return ("NetBSD Cryptographic Disk"); - if (uuid_equal(t, &swap, NULL)) - return ("FreeBSD swap"); - if (uuid_equal(t, &ufs, NULL)) - return ("FreeBSD UFS/UFS2"); - if (uuid_equal(t, &vinum, NULL)) - return ("FreeBSD vinum"); - if (uuid_equal(t, &zfs, NULL)) - return ("FreeBSD ZFS"); - if (uuid_equal(t, &freebsd, NULL)) - return ("FreeBSD legacy"); - if (uuid_equal(t, &msdata, NULL)) - return ("Windows basic data"); - if (uuid_equal(t, &msr, NULL)) - return ("Windows reserved"); - if (uuid_equal(t, &linuxdata, NULL)) - return ("Linux data"); - if (uuid_equal(t, &linuxswap, NULL)) - return ("Linux swap"); - if (uuid_equal(t, &hfs, NULL)) - return ("Apple HFS"); - -unfriendly: - uuid_to_string(t, &s, NULL); - strlcpy(buf, s, sizeof buf); - free(s); - return (buf); -} - static void show(void) { - uuid_t guid, type; off_t start; map_t *m, *p; struct mbr *mbr; struct gpt_ent *ent; unsigned int i; - char *s; printf(" %*s", lbawidth, "start"); printf(" %*s", lbawidth, "size"); @@ -198,13 +129,17 @@ show(void) printf("- \"%s\"", utf16_to_utf8(ent->ent_name)); } else if (show_guid) { - le_uuid_dec(ent->ent_guid, &guid); - uuid_to_string(&guid, &s, NULL); - printf("- %s", s); - free(s); + char buf[128]; + gpt_uuid_snprintf( + buf, sizeof(buf), "%d", ent->ent_guid); + printf("- %s", buf); } else { - le_uuid_dec(ent->ent_type, &type); - printf("- %s", friendly(&type)); + char buf[128]; + if (show_uuid || gpt_uuid_snprintf(buf, + sizeof(buf), "%ls", ent->ent_type) == -1) + gpt_uuid_snprintf(buf, sizeof(buf), + "%d", ent->ent_type); + printf("- %s", buf); } break; case MAP_TYPE_PMBR: @@ -219,11 +154,12 @@ show(void) static void show_one(void) { - uuid_t guid, type; map_t *m; struct gpt_ent *ent; - const char *s1; - char *s2, human_num[5]; + char s1[128], s2[128]; +#ifdef HN_AUTOSCALE + char human_num[5]; +#endif for (m = map_first(); m != NULL; m = m->map_next) if (entry == m->map_index) @@ -236,6 +172,7 @@ show_one(void) 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), "", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0) human_num[0] = '\0'; @@ -243,27 +180,26 @@ show_one(void) printf("Start: %llu (%s)\n", (long long)m->map_start, human_num); else +#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), "", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0) human_num[0] = '\0'; if (human_num[0] != '\0') printf("Size: %llu (%s)\n", (long long)m->map_size, human_num); else +#endif printf("Size: %llu\n", (long long)m->map_size); - le_uuid_dec(ent->ent_type, &type); - s1 = friendly(&type); - uuid_to_string(&type, &s2, NULL); + gpt_uuid_snprintf(s1, sizeof(s1), "%s", ent->ent_type); + gpt_uuid_snprintf(s2, sizeof(s2), "%d", ent->ent_type); if (strcmp(s1, s2) == 0) - s1 = "unknown"; + strlcpy(s1, "unknown", sizeof(s1)); printf("Type: %s (%s)\n", s1, s2); - free(s2); - le_uuid_dec(ent->ent_guid, &guid); - uuid_to_string(&guid, &s2, NULL); + gpt_uuid_snprintf(s2, sizeof(s1), "%d", ent->ent_guid); printf("GUID: %s\n", s2); - free(s2); printf("Label: %s\n", utf16_to_utf8(ent->ent_name)); Added files: Index: src/sbin/gpt/drvctl.c diff -u /dev/null src/sbin/gpt/drvctl.c:1.1.2.2 --- /dev/null Tue Jun 2 19:49:38 2015 +++ src/sbin/gpt/drvctl.c Tue Jun 2 19:49:38 2015 @@ -0,0 +1,134 @@ +/* $NetBSD: drvctl.c,v 1.1.2.2 2015/06/02 19:49:38 snj Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE 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/cdefs.h> +__RCSID("$NetBSD: drvctl.c,v 1.1.2.2 2015/06/02 19:49:38 snj Exp $"); + +#include <sys/types.h> +#include <sys/disk.h> +#include <sys/drvctlio.h> + +#include <prop/proplib.h> + +#include <errno.h> +#include <err.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> + +#include "map.h" +#include "gpt.h" + +int +getdisksize(const char *name, u_int *sector_size, off_t *media_size) +{ + prop_dictionary_t command_dict, args_dict, results_dict, data_dict, + disk_info, geometry; + prop_string_t string; + prop_number_t number; + int dfd, res; + char *dname, *p; + + if (*sector_size && *media_size) + return 0; + + if ((dfd = open("/dev/drvctl", O_RDONLY)) == -1) { + warn("%s: /dev/drvctl", __func__); + return -1; + } + + command_dict = prop_dictionary_create(); + args_dict = prop_dictionary_create(); + + string = prop_string_create_cstring_nocopy("get-properties"); + prop_dictionary_set(command_dict, "drvctl-command", string); + prop_object_release(string); + + if ((dname = strdup(name[0] == 'r' ? name + 1 : name)) == NULL) { + (void)close(dfd); + return -1; + } + for (p = dname; *p; p++) + continue; + for (--p; p >= dname && !isdigit((unsigned char)*p); *p-- = '\0') + continue; + + string = prop_string_create_cstring(dname); + free(dname); + prop_dictionary_set(args_dict, "device-name", string); + prop_object_release(string); + + prop_dictionary_set(command_dict, "drvctl-arguments", args_dict); + prop_object_release(args_dict); + + res = prop_dictionary_sendrecv_ioctl(command_dict, dfd, DRVCTLCOMMAND, + &results_dict); + (void)close(dfd); + prop_object_release(command_dict); + if (res) { + warn("%s: prop_dictionary_sendrecv_ioctl", __func__); + errno = res; + return -1; + } + + number = prop_dictionary_get(results_dict, "drvctl-error"); + if ((errno = prop_number_integer_value(number)) != 0) + return -1; + + data_dict = prop_dictionary_get(results_dict, "drvctl-result-data"); + if (data_dict == NULL) + goto out; + + disk_info = prop_dictionary_get(data_dict, "disk-info"); + if (disk_info == NULL) + goto out; + + geometry = prop_dictionary_get(disk_info, "geometry"); + if (geometry == NULL) + goto out; + + number = prop_dictionary_get(geometry, "sector-size"); + if (number == NULL) + goto out; + + if (*sector_size == 0) + *sector_size = prop_number_integer_value(number); + + number = prop_dictionary_get(geometry, "sectors-per-unit"); + if (number == NULL) + goto out; + + if (*media_size == 0) + *media_size = prop_number_integer_value(number) * *sector_size; + + return 0; +out: + errno = EINVAL; + return -1; +} Index: src/sbin/gpt/gpt_uuid.c diff -u /dev/null src/sbin/gpt/gpt_uuid.c:1.10.2.2 --- /dev/null Tue Jun 2 19:49:38 2015 +++ src/sbin/gpt/gpt_uuid.c Tue Jun 2 19:49:38 2015 @@ -0,0 +1,274 @@ +/* $NetBSD: gpt_uuid.c,v 1.10.2.2 2015/06/02 19:49:38 snj Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE 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. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include <sys/cdefs.h> +#ifdef __RCSID +__RCSID("$NetBSD: gpt_uuid.c,v 1.10.2.2 2015/06/02 19:49:38 snj Exp $"); +#endif + +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +#include "map.h" +#include "gpt.h" + +#if defined(HAVE_SYS_ENDIAN_H) || ! defined(HAVE_NBTOOL_CONFIG_H) +#include <sys/endian.h> +#endif + + +const gpt_uuid_t gpt_uuid_nil; + +struct dce_uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[6]; +}; + +static const struct { + struct dce_uuid u; + const char *n; + const char *d; +} gpt_nv[] = { + { GPT_ENT_TYPE_APPLE_HFS, "apple", "Apple HFS" }, + { GPT_ENT_TYPE_APPLE_UFS, "apple-ufs", "Apple UFS" }, + { GPT_ENT_TYPE_BIOS, "bios", "BIOS Boot" }, + { GPT_ENT_TYPE_EFI, "efi", "EFI System" }, + { GPT_ENT_TYPE_FREEBSD, "fbsd-legacy", "FreeBSD legacy" }, + { GPT_ENT_TYPE_FREEBSD_SWAP, "fbsd-swap", "FreeBSD swap" }, + { GPT_ENT_TYPE_FREEBSD_UFS, "fbsd-ufs", "FreeBSD UFS/UFS2" }, + { GPT_ENT_TYPE_FREEBSD_VINUM, "fbsd-vinum", "FreeBSD vinum" }, + { GPT_ENT_TYPE_FREEBSD_ZFS, "fbsd-zfs", "FreeBSD ZFS" }, + { GPT_ENT_TYPE_LINUX_DATA, "linux-data", "Linux data" }, + { GPT_ENT_TYPE_LINUX_RAID, "linux-raid", "Linux RAID" }, + { GPT_ENT_TYPE_LINUX_SWAP, "linux-swap", "Linux swap" }, + { GPT_ENT_TYPE_LINUX_LVM, "linux-lvm", "Linux LVM" }, + { GPT_ENT_TYPE_MS_BASIC_DATA, "windows", "Windows basic data" }, + { GPT_ENT_TYPE_MS_RESERVED, "windows-reserved", "Windows reserved" }, + { GPT_ENT_TYPE_NETBSD_CCD, "ccd", "NetBSD ccd component" }, + { GPT_ENT_TYPE_NETBSD_CGD, "cgd", "NetBSD Cryptographic Disk" }, + { GPT_ENT_TYPE_NETBSD_FFS, "ffs", "NetBSD FFSv1/FFSv2" }, + { GPT_ENT_TYPE_NETBSD_LFS, "lfs", "NetBSD LFS" }, + { GPT_ENT_TYPE_NETBSD_RAIDFRAME, "raid", + "NetBSD RAIDFrame component" }, + { GPT_ENT_TYPE_NETBSD_SWAP, "swap", "NetBSD swap" }, +}; + +static void +gpt_uuid_to_dce(const gpt_uuid_t buf, struct dce_uuid *uuid) +{ + const uint8_t *p = buf; + size_t i; + + uuid->time_low = le32dec(p); + uuid->time_mid = le16dec(p + 4); + uuid->time_hi_and_version = le16dec(p + 6); + uuid->clock_seq_hi_and_reserved = p[8]; + uuid->clock_seq_low = p[9]; + for (i = 0; i < sizeof(uuid->node); i++) + uuid->node[i] = p[10 + i]; +} + +static void +gpt_dce_to_uuid(const struct dce_uuid *uuid, uint8_t *buf) +{ + uint8_t *p = buf; + size_t i; + + le32enc(p, uuid->time_low); + le16enc(p + 4, uuid->time_mid); + le16enc(p + 6, uuid->time_hi_and_version); + p[8] = uuid->clock_seq_hi_and_reserved; + p[9] = uuid->clock_seq_low; + for (i = 0; i < sizeof(uuid->node); i++) + p[10 + i] = uuid->node[i]; +} + +static int +gpt_uuid_numeric(char *buf, size_t bufsiz, const struct dce_uuid *u) +{ + return snprintf(buf, bufsiz, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + u->time_low, u->time_mid, u->time_hi_and_version, + u->clock_seq_hi_and_reserved, u->clock_seq_low, u->node[0], + u->node[1], u->node[2], u->node[3], u->node[4], u->node[5]); +} + + +static int +gpt_uuid_symbolic(char *buf, size_t bufsiz, const struct dce_uuid *u) +{ + size_t i; + + for (i = 0; i < __arraycount(gpt_nv); i++) + if (memcmp(&gpt_nv[i].u, u, sizeof(*u)) == 0) + return strlcpy(buf, gpt_nv[i].n, bufsiz); + return -1; +} + +static int +gpt_uuid_descriptive(char *buf, size_t bufsiz, const struct dce_uuid *u) +{ + size_t i; + + for (i = 0; i < __arraycount(gpt_nv); i++) + if (memcmp(&gpt_nv[i].u, u, sizeof(*u)) == 0) + return strlcpy(buf, gpt_nv[i].d, bufsiz); + return -1; +} + +int +gpt_uuid_snprintf(char *buf, size_t bufsiz, const char *fmt, + const gpt_uuid_t uu) +{ + struct dce_uuid u; + gpt_uuid_to_dce(uu, &u); + + if (fmt[1] == 's') { + int r; + if ((r = gpt_uuid_symbolic(buf, bufsiz, &u)) != -1) + return r; + } + if (fmt[1] == 'l') { + int r; + if ((r = gpt_uuid_descriptive(buf, bufsiz, &u)) != -1) + return r; + } + return gpt_uuid_numeric(buf, bufsiz, &u); +} + +static int +gpt_uuid_parse_numeric(const char *s, struct dce_uuid *u) +{ + int n; + + if (s == NULL || *s == '\0') { + memset(u, 0, sizeof(*u)); + return 0; + } + + n = sscanf(s, + "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", + &u->time_low, &u->time_mid, &u->time_hi_and_version, + &u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0], + &u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]); + + /* Make sure we have all conversions. */ + if (n != 11) + return -1; + + /* We have a successful scan. Check semantics... */ + n = u->clock_seq_hi_and_reserved; + if ((n & 0x80) != 0x00 && /* variant 0? */ + (n & 0xc0) != 0x80 && /* variant 1? */ + (n & 0xe0) != 0xc0) /* variant 2? */ + return -1; + return 0; +} + +static int +gpt_uuid_parse_symbolic(const char *s, struct dce_uuid *u) +{ + size_t i; + + for (i = 0; i < __arraycount(gpt_nv); i++) + if (strcmp(gpt_nv[i].n, s) == 0) { + *u = gpt_nv[i].u; + return 0; + } + return -1; +} + +int +gpt_uuid_parse(const char *s, gpt_uuid_t uuid) +{ + struct dce_uuid u; + + if (gpt_uuid_parse_numeric(s, &u) != -1) { + gpt_dce_to_uuid(&u, uuid); + return 0; + } + + if (gpt_uuid_parse_symbolic(s, &u) == -1) + return -1; + + gpt_dce_to_uuid(&u, uuid); + return 0; +} + +void +gpt_uuid_create(gpt_type_t t, gpt_uuid_t u, uint16_t *b, size_t s) +{ + gpt_dce_to_uuid(&gpt_nv[t].u, u); + if (b) + utf8_to_utf16((const uint8_t *)gpt_nv[t].d, b, s / sizeof(*b)); +} + +void +gpt_uuid_generate(gpt_uuid_t t) +{ + struct dce_uuid u; + int fd; + uint8_t *p; + size_t n; + ssize_t nread; + + /* Randomly generate the content. */ + fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd == -1) + err(1, "open(/dev/urandom)"); + for (p = (void *)&u, n = sizeof u; 0 < n; p += nread, n -= nread) { + nread = read(fd, p, n); + if (nread < 0) + err(1, "read(/dev/urandom)"); + if (nread == 0) + errx(1, "EOF from /dev/urandom"); + if ((size_t)nread > n) + errx(1, "read too much: %zd > %zu", nread, n); + } + (void)close(fd); + + /* Set the version number to 4. */ + u.time_hi_and_version &= ~(uint32_t)0xf000; + u.time_hi_and_version |= 0x4000; + + /* Fix the reserved bits. */ + u.clock_seq_hi_and_reserved &= ~(uint8_t)0x40; + u.clock_seq_hi_and_reserved |= 0x80; + + gpt_dce_to_uuid(&u, t); +} Index: src/sbin/gpt/gpt_uuid.h diff -u /dev/null src/sbin/gpt/gpt_uuid.h:1.3.2.2 --- /dev/null Tue Jun 2 19:49:38 2015 +++ src/sbin/gpt/gpt_uuid.h Tue Jun 2 19:49:38 2015 @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 2014 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. + */ +#ifndef _GPT_UUID_H +#define _GPT_UUID_H + +#include <string.h> +#include <inttypes.h> +#ifndef HAVE_NBTOOL_CONFIG_H +#include <sys/disklabel_gpt.h> +#else +#include <nbinclude/sys/disklabel_gpt.h> +#endif + +/* + * We define our own uuid type so that we don't have to mess around + * with different uuid implementation (linux+macosx which use an + * array, and {Free,Net}BSD who use a struct. We just need minimal + * support anyway + */ + +// Must match the array in gpt_uuid.c +typedef enum { + GPT_TYPE_APPLE_HFS = 0, + GPT_TYPE_BIOS, + GPT_TYPE_EFI, + GPT_TYPE_FREEBSD, + GPT_TYPE_FREEBSD_SWAP, + GPT_TYPE_FREEBSD_UFS, + GPT_TYPE_FREEBSD_VINUM, + GPT_TYPE_FREEBSD_ZFS, + GPT_TYPE_LINUX_DATA, + GPT_TYPE_LINUX_SWAP, + GPT_TYPE_MS_BASIC_DATA, + GPT_TYPE_MS_RESERVED, + GPT_TYPE_NETBSD_CCD, + GPT_TYPE_NETBSD_CGD, + GPT_TYPE_NETBSD_FFS, + GPT_TYPE_NETBSD_LFS, + GPT_TYPE_NETBSD_RAIDFRAME, + GPT_TYPE_NETBSD_SWAP +} gpt_type_t; + +typedef uint8_t gpt_uuid_t[16]; +extern const gpt_uuid_t gpt_uuid_nil; + +__BEGIN_DECLS +static inline int +gpt_uuid_is_nil(const gpt_uuid_t u) { + return memcmp(u, gpt_uuid_nil, sizeof(gpt_uuid_t)) == 0; +} + +static inline int +gpt_uuid_equal(const gpt_uuid_t u1, const gpt_uuid_t u2) { + return memcmp(u1, u2, sizeof(gpt_uuid_t)) == 0; +} + +static inline void +gpt_uuid_copy(gpt_uuid_t u1, const gpt_uuid_t u2) { + memcpy(u1, u2, sizeof(gpt_uuid_t)); +} + +int gpt_uuid_snprintf(char *, size_t, const char *, const gpt_uuid_t); + +void gpt_uuid_create(gpt_type_t, gpt_uuid_t, uint16_t *, size_t); + +int gpt_uuid_parse(const char *, gpt_uuid_t); + +void gpt_uuid_generate(gpt_uuid_t); + +__END_DECLS + +#endif /* _GPT_UUID_T */ Index: src/sbin/gpt/resizedisk.c diff -u /dev/null src/sbin/gpt/resizedisk.c:1.6.2.2 --- /dev/null Tue Jun 2 19:49:38 2015 +++ src/sbin/gpt/resizedisk.c Tue Jun 2 19:49:38 2015 @@ -0,0 +1,292 @@ +/*- + * Copyright (c) 2002 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include <sys/cdefs.h> +#ifdef __FBSDID +__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.6.2.2 2015/06/02 19:49:38 snj Exp $"); +#endif + +#include <sys/bootblock.h> +#include <sys/types.h> + +#include <err.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "map.h" +#include "gpt.h" + +static uint64_t sector, size; + +const char resizediskmsg[] = "resizedisk [-s size] device ..."; + +__dead static void +usage_resizedisk(void) +{ + + fprintf(stderr, + "usage: %s %s\n", getprogname(), resizediskmsg); + exit(1); +} + +/* + * relocate the secondary GPT based on the following criteria: + * - size not specified + * - disk has not changed size, do nothing + * - disk has grown, relocate secondary + * - disk has shrunk, create new secondary + * - size specified + * - size is larger then disk or same as current location, do nothing + * - relocate or create new secondary + * - when shrinking, verify that table fits + */ +static void +resizedisk(int fd) +{ + map_t *gpt, *tpg; + map_t *tbl, *lbt; + map_t *mbrmap; + struct gpt_hdr *hdr; + struct gpt_ent *ent; + struct mbr *mbr; + uint64_t last, oldloc, newloc, lastdata, gpt_size; + int i; + + last = mediasz / secsz - 1; + lastdata = 0; + newloc = 0; + + if (sector > last) { + warnx("%s: specified size is larger then the disk", + device_name); + return; + } + + mbrmap = map_find(MAP_TYPE_PMBR); + if (mbrmap == NULL || mbrmap->map_start != 0) { + warnx("%s: error: no valid Protective MBR found", device_name); + return; + } + mbr = mbrmap->map_data; + + 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; + } + hdr = 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_size = tbl->map_size; + if (sector == oldloc) { + warnx("%s: device is already the specified size", device_name); + return; + } + if (sector == 0 && last == oldloc) { + warnx("%s: device hasn't changed size", device_name); + return; + } + + for (ent = tbl->map_data; ent < + (struct gpt_ent *)((char *)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)) { + 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; + } + if (last - gpt_size <= lastdata) { + warnx("%s: not enough space for new secondary GPT table", + device_name); + return; + } + + if (sector > oldloc) + newloc = sector; + if (sector > 0 && sector < oldloc && last >= oldloc) + newloc = sector; + 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 (lbt == NULL) { + warnx("%s: error: run recover -- trust me", + device_name); + return; + } + tpg->map_start = newloc; + 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); + } + + hdr = gpt->map_data; + hdr->hdr_lba_alt = tpg->map_start; + hdr->hdr_crc_self = 0; + hdr->hdr_lba_end = htole64(lbt->map_start - 1); + hdr->hdr_crc_self = + htole32(crc32(gpt->map_data, GPT_HDR_SIZE)); + gpt_write(fd, 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); + + 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; + } + 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, mbrmap); + + return; +} + +int +cmd_resizedisk(int argc, char *argv[]) +{ + char *p; + int ch, fd; + int64_t human_num; + + while ((ch = getopt(argc, argv, "s:")) != -1) { + switch(ch) { + case 's': + if (sector > 0 || size > 0) + usage_resizedisk(); + sector = strtoll(optarg, &p, 10); + if (sector < 1) + usage_resizedisk(); + if (*p == '\0') + break; + if (*p == 's' || *p == 'S') { + if (*(p + 1) == '\0') + break; + else + usage_resizedisk(); + } + if (*p == 'b' || *p == 'B') { + if (*(p + 1) == '\0') { + size = sector; + sector = 0; + break; + } else + usage_resizedisk(); + } + if (dehumanize_number(optarg, &human_num) < 0) + usage_resizedisk(); + size = human_num; + sector = 0; + break; + default: + usage_resizedisk(); + } + } + + if (argc == optind) + usage_resizedisk(); + + while (optind < argc) { + fd = gpt_open(argv[optind++]); + if (fd == -1) { + warn("unable to open device '%s'", device_name); + 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); + + gpt_close(fd); + } + + return 0; +} Index: src/sbin/gpt/type.c diff -u /dev/null src/sbin/gpt/type.c:1.6.2.2 --- /dev/null Tue Jun 2 19:49:38 2015 +++ src/sbin/gpt/type.c Tue Jun 2 19:49:38 2015 @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +#include <sys/cdefs.h> +#ifdef __FBSDID +__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.6.2.2 2015/06/02 19:49:38 snj Exp $"); +#endif + +#include <sys/types.h> + +#include <err.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "map.h" +#include "gpt.h" + +static int all; +static gpt_uuid_t type, newtype; +static off_t block, size; +static unsigned int entry; +static uint8_t *label; + +const char typemsg1[] = "type -a -T newtype device ..."; +const char typemsg2[] = "type [-b blocknr] [-i index] [-L label] " + "[-s sectors] [-t type]"; +const char typemsg3[] = " -T newtype device ..."; + +__dead static void +usage_type(void) +{ + + fprintf(stderr, + "usage: %s %s\n" + " %s %s\n" + " %*s %s\n", getprogname(), typemsg1, + getprogname(), typemsg2, (int)strlen(getprogname()), "", typemsg3); + exit(1); +} + +static void +chtype(int fd) +{ + map_t *gpt, *tpg; + map_t *tbl, *lbt; + 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; + } + + /* Change type of all matching entries in the map. */ + for (m = map_first(); 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; + + hdr = gpt->map_data; + ent = (void*)((char*)tbl->map_data + i * + le32toh(hdr->hdr_entsz)); + + 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); + + 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)); + + /* 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); + } +} + +int +cmd_type(int argc, char *argv[]) +{ + char *p; + int ch, fd; + int64_t human_num; + + /* Get the type options */ + while ((ch = getopt(argc, argv, "ab:i:L:s:t:T:")) != -1) { + switch(ch) { + case 'a': + if (all > 0) + usage_type(); + all = 1; + break; + case 'b': + if (block > 0) + usage_type(); + if (dehumanize_number(optarg, &human_num) < 0) + usage_type(); + block = human_num; + if (block < 1) + usage_type(); + break; + case 'i': + if (entry > 0) + usage_type(); + entry = strtoul(optarg, &p, 10); + if (*p != 0 || entry < 1) + usage_type(); + break; + case 'L': + if (label != NULL) + usage_type(); + label = (uint8_t *)strdup(optarg); + break; + case 's': + if (size > 0) + usage_type(); + size = strtoll(optarg, &p, 10); + if (*p != 0 || size < 1) + usage_type(); + break; + case 't': + if (!gpt_uuid_is_nil(type)) + usage_type(); + if (gpt_uuid_parse(optarg, type) != 0) + usage_type(); + break; + case 'T': + if (!gpt_uuid_is_nil(newtype)) + usage_type(); + if (gpt_uuid_parse(optarg, newtype) != 0) + usage_type(); + break; + default: + usage_type(); + } + } + + if (!all ^ + (block > 0 || entry > 0 || label != NULL || size > 0 || + !gpt_uuid_is_nil(type))) + usage_type(); + if (gpt_uuid_is_nil(newtype)) + usage_type(); + + if (argc == optind) + usage_type(); + + while (optind < argc) { + fd = gpt_open(argv[optind++]); + if (fd == -1) { + warn("unable to open device '%s'", device_name); + continue; + } + + chtype(fd); + + gpt_close(fd); + } + + return (0); +}