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.
This commit is contained in:
snj 2015-06-02 19:49:38 +00:00
parent 667b53e347
commit b8a7f8b471
24 changed files with 1843 additions and 630 deletions

View File

@ -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>

View File

@ -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/10 01:05:00 jnemeth Exp $");
#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) {

View File

@ -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) {
@ -138,6 +145,11 @@ backup(void)
PROP_ERR(rc);
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);
@ -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);

View File

@ -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();
}

View File

@ -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) *

View File

@ -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);
}
}

134
sbin/gpt/drvctl.c Normal file
View File

@ -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;
}

View File

@ -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 settings, so some general options may not
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 partition type.
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 can be recovered.
.\" ==== 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 label was deleted.
.\" ==== 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 are:
.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

View File

@ -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/10 18:27:15 jnemeth Exp $");
#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_t *s16, size_t s16len)
} 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;
#else
if (getdisksize(device_name, &secsz, &mediasz) == -1)
goto close;
#endif
if (drvctl(device_name, &secsz, &mediasz) == -1)
goto close;
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;

View File

@ -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
#ifndef HAVE_NBTOOL_CONFIG_H
#include <util.h>
#else
#include "opendisk.h"
#include "namespace.h"
#endif
#include <uuid.h>
#define le_uuid_dec uuid_dec_le
#define le_uuid_enc uuid_enc_le
int parse_uuid(const char *, uuid_t *);
#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_ */

274
sbin/gpt/gpt_uuid.c Normal file
View File

@ -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);
}

98
sbin/gpt/gpt_uuid.h Normal file
View File

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

View File

@ -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/28 01:37:14 jnemeth Exp $");
#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)

View File

@ -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>

View File

@ -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/12/04 20:15:51 jakllsch Exp $");
/*
* 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/12/04 20:15:51 jakllsch Exp $");
#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, struct gpt_ent *ent)
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 start, struct gpt_ent *ent)
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 start, struct gpt_ent *ent)
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;

View File

@ -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>

View File

@ -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/11/28 01:37:14 jnemeth Exp $");
#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)

View File

@ -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/10 01:05:00 jnemeth Exp $");
#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;

292
sbin/gpt/resizedisk.c Normal file
View File

@ -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;
}

View File

@ -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/08/10 18:27:15 jnemeth Exp $");
#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);
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;
}
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;
}
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 */
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;
}
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);
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;
}
map = map_add(0LL, 1LL, MAP_TYPE_PMBR, mbr);
gpt_write(fd, map);
}
prop_object_iterator_release(propiter);
/* 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);
secbuf = calloc(gpt_size + 1, secsz); /* GPT TABLE + GPT HEADER */
if (secbuf == NULL) {
warnx("not enough memory to create a sector buffer");
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 */
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;
}
}
/* Never cross the median of the device. */
if ((blocks + 1LL) > ((last + 1LL) >> 1))
blocks = ((last + 1LL) >> 1) - 1LL;
/*
* Get the amount of free space at the end of the device and
* calculate the size for the GPT structures.
*/
map = map_last();
if (map->map_type != MAP_TYPE_UNUSED) {
warnx("%s: error: no room for the backup header", device_name);
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;
}
if (map->map_size < blocks)
blocks = map->map_size;
if (blocks == 1LL) {
warnx("%s: error: no room for the GPT table", 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)
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));
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((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;
}
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

View File

@ -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 01:05:00 jnemeth Exp $");
#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;

View File

@ -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));

243
sbin/gpt/type.c Normal file
View File

@ -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);
}

View File

@ -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/10 01:05:00 jnemeth Exp $");
#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;