Module Name: src
Committed By: christos
Date: Tue Dec 1 09:05:33 UTC 2015
Modified Files:
src/sbin/gpt: Makefile add.c backup.c biosboot.c create.c destroy.c
gpt.8 gpt.c gpt.h header.c label.c main.c map.c map.h migrate.c
recover.c remove.c resize.c resizedisk.c restore.c set.c show.c
type.c unset.c
Added Files:
src/sbin/gpt: gpt_private.h
Log Message:
Firs step of refactoring, remove all globals, factor out some common code,
handle alternate usage but not advertise it.
To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sbin/gpt/Makefile
cvs rdiff -u -r1.30 -r1.31 src/sbin/gpt/add.c
cvs rdiff -u -r1.9 -r1.10 src/sbin/gpt/backup.c src/sbin/gpt/restore.c
cvs rdiff -u -r1.15 -r1.16 src/sbin/gpt/biosboot.c
cvs rdiff -u -r1.13 -r1.14 src/sbin/gpt/create.c
cvs rdiff -u -r1.7 -r1.8 src/sbin/gpt/destroy.c src/sbin/gpt/recover.c \
src/sbin/gpt/resizedisk.c src/sbin/gpt/type.c
cvs rdiff -u -r1.38 -r1.39 src/sbin/gpt/gpt.8
cvs rdiff -u -r1.48 -r1.49 src/sbin/gpt/gpt.c
cvs rdiff -u -r1.22 -r1.23 src/sbin/gpt/gpt.h src/sbin/gpt/migrate.c
cvs rdiff -u -r0 -r1.1 src/sbin/gpt/gpt_private.h
cvs rdiff -u -r1.3 -r1.4 src/sbin/gpt/header.c src/sbin/gpt/map.h
cvs rdiff -u -r1.19 -r1.20 src/sbin/gpt/label.c
cvs rdiff -u -r1.1 -r1.2 src/sbin/gpt/main.c
cvs rdiff -u -r1.10 -r1.11 src/sbin/gpt/map.c
cvs rdiff -u -r1.17 -r1.18 src/sbin/gpt/remove.c
cvs rdiff -u -r1.14 -r1.15 src/sbin/gpt/resize.c
cvs rdiff -u -r1.6 -r1.7 src/sbin/gpt/set.c src/sbin/gpt/unset.c
cvs rdiff -u -r1.23 -r1.24 src/sbin/gpt/show.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sbin/gpt/Makefile
diff -u src/sbin/gpt/Makefile:1.16 src/sbin/gpt/Makefile:1.17
--- src/sbin/gpt/Makefile:1.16 Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/Makefile Tue Dec 1 04:05:33 2015
@@ -1,12 +1,17 @@
-# $NetBSD: Makefile,v 1.16 2015/11/30 19:59:34 christos Exp $
+# $NetBSD: Makefile,v 1.17 2015/12/01 09:05:33 christos Exp $
# $FreeBSD: src/sbin/gpt/Makefile,v 1.7 2005/09/01 02:49:20 marcel Exp $
+.include <bsd.own.mk>
+
PROG= gpt
SRCS= add.c biosboot.c create.c destroy.c gpt.c header.c label.c map.c \
main.c migrate.c recover.c remove.c resize.c resizedisk.c \
set.c show.c type.c unset.c gpt_uuid.c
MAN= gpt.8
+#LINKS= ${BINDIR}/gpt ${BINDIR}/gptlabel
+#MLINKS= gpt.8 gptlabel.8
+
.if (${HOSTPROG:U} == "")
SRCS+= backup.c restore.c
LDADD+= -lprop -lutil
Index: src/sbin/gpt/add.c
diff -u src/sbin/gpt/add.c:1.30 src/sbin/gpt/add.c:1.31
--- src/sbin/gpt/add.c:1.30 Mon Nov 30 21:03:55 2015
+++ src/sbin/gpt/add.c Tue Dec 1 04:05:33 2015
@@ -33,10 +33,12 @@
__FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: add.c,v 1.30 2015/12/01 02:03:55 christos Exp $");
+__RCSID("$NetBSD: add.c,v 1.31 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
#include <err.h>
#include <stddef.h>
@@ -47,6 +49,7 @@ __RCSID("$NetBSD: add.c,v 1.30 2015/12/0
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static gpt_uuid_t type;
static off_t alignment, block, sectors, size;
@@ -54,9 +57,9 @@ static unsigned int entry;
static uint8_t *name;
const char addmsg1[] = "add [-a alignment] [-b blocknr] [-i index] [-l label]";
-const char addmsg2[] = " [-s size] [-t type] device ...";
+const char addmsg2[] = " [-s size] [-t type]";
-__dead static void
+static int
usage_add(void)
{
@@ -64,131 +67,89 @@ usage_add(void)
"usage: %s %s\n"
" %*s %s\n", getprogname(), addmsg1,
(int)strlen(getprogname()), "", addmsg2);
- exit(1);
+ return -1;
}
-static void
-add(int fd)
+static int
+add(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *map;
+ map_t map;
struct gpt_hdr *hdr;
- struct gpt_ent *ent;
+ struct gpt_ent *ent, e;
unsigned int i;
off_t alignsecs;
+ if ((hdr = gpt_hdr(gpt)) == NULL)
+ return -1;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
ent = NULL;
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
-
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
-
- hdr = gpt->map_data;
if (entry > le32toh(hdr->hdr_entries)) {
- warnx("%s: error: index %u out of range (%u max)", device_name,
+ gpt_warnx(gpt, "index %u out of range (%u max)",
entry, le32toh(hdr->hdr_entries));
- return;
+ return -1;
}
if (entry > 0) {
i = entry - 1;
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_primary(gpt, i);
if (!gpt_uuid_is_nil(ent->ent_type)) {
- warnx("%s: error: entry at index %u is not free",
- device_name, entry);
- return;
+ gpt_warnx(gpt, "Entry at index %u is not free", entry);
+ return -1;
}
} else {
/* Find empty slot in GPT table. */
for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_primary(gpt, i);
if (gpt_uuid_is_nil(ent->ent_type))
break;
}
if (i == le32toh(hdr->hdr_entries)) {
- warnx("%s: error: no available table entries",
- device_name);
- return;
+ gpt_warnx(gpt, "No available table entries");
+ return -1;
}
}
if (alignment > 0) {
- alignsecs = alignment / secsz;
- map = map_alloc(block, sectors, alignsecs);
+ alignsecs = alignment / gpt->secsz;
+ map = map_alloc(gpt, block, sectors, alignsecs);
if (map == NULL) {
- warnx("%s: error: not enough space available on "
- "device for an aligned partition", device_name);
- return;
+ gpt_warnx(gpt, "Not enough space available on "
+ "device for an aligned partition");
+ return -1;
}
} else {
- map = map_alloc(block, sectors, 0);
+ map = map_alloc(gpt, block, sectors, 0);
if (map == NULL) {
- warnx("%s: error: not enough space available on "
- "device", device_name);
- return;
+ gpt_warnx(gpt, "Not enough space available on device");
+ return -1;
}
}
- gpt_uuid_copy(ent->ent_type, type);
- ent->ent_lba_start = htole64(map->map_start);
- ent->ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
- if (name != NULL)
- utf8_to_utf16(name, ent->ent_name, 36);
-
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
-
- hdr = tpg->map_data;
- ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
-
- gpt_uuid_copy(ent->ent_type, type);
- ent->ent_lba_start = htole64(map->map_start);
- ent->ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
+ memset(&e, 0, sizeof(e));
+ gpt_uuid_copy(e.ent_type, type);
+ e.ent_lba_start = htole64(map->map_start);
+ e.ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
if (name != NULL)
- utf8_to_utf16(name, ent->ent_name, 36);
+ utf8_to_utf16(name, e.ent_name, 36);
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+ memcpy(ent, &e, sizeof(e));
+ gpt_write_primary(gpt);
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
+ ent = gpt_ent_backup(gpt, i);
+ memcpy(ent, &e, sizeof(e));
+ gpt_write_backup(gpt);
- gpt_msg("Partition %d added: %s %" PRIu64 " %" PRIu64 "\n", i + 1,
+ gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64 "\n", i + 1,
type, map->map_start, map->map_size);
+ return 0;
}
int
-cmd_add(int argc, char *argv[])
+cmd_add(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
int64_t human_num;
while ((ch = getopt(argc, argv, "a:b:i:l:s:t:")) != -1) {
@@ -257,44 +218,23 @@ cmd_add(int argc, char *argv[])
usage_add();
break;
default:
- usage_add();
+ return usage_add();
}
}
if (argc == optind)
- usage_add();
+ return usage_add();
/* Create NetBSD FFS partitions by default. */
if (gpt_uuid_is_nil(type)) {
gpt_uuid_create(GPT_TYPE_NETBSD_FFS, type, NULL, 0);
}
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- if (alignment % secsz != 0) {
- warnx("Alignment must be a multiple of sector size;");
- warnx("the sector size for %s is %d bytes.",
- device_name, secsz);
- continue;
- }
-
- if (size % secsz != 0) {
- warnx("Size in bytes must be a multiple of sector "
- "size;");
- warnx("the sector size for %s is %d bytes.",
- device_name, secsz);
- continue;
- }
- if (size > 0)
- sectors = size / secsz;
-
- add(fd);
+ if (optind != argc)
+ return usage_add();
- gpt_close(fd);
- }
+ if ((sectors = gpt_check(gpt, alignment, size)) == -1)
+ return -1;
- return (0);
+ return add(gpt);
}
Index: src/sbin/gpt/backup.c
diff -u src/sbin/gpt/backup.c:1.9 src/sbin/gpt/backup.c:1.10
--- src/sbin/gpt/backup.c:1.9 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/backup.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: backup.c,v 1.9 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: backup.c,v 1.10 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/bootblock.h>
@@ -49,31 +49,32 @@ __RCSID("$NetBSD: backup.c,v 1.9 2015/11
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
-const char backupmsg[] = "backup device ...";
+const char backupmsg[] = "backup";
-__dead static void
+static int
usage_backup(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), backupmsg);
- exit(1);
+ return -1;
}
-#define PROP_ERR(x) if (!(x)) { \
- warn("proplib failure"); \
- return; \
+#define PROP_ERR(x) if (!(x)) { \
+ gpt_warnx(gpt, "proplib failure"); \
+ return -1; \
}
-static void
-backup(void)
+static int
+backup(gpt_t gpt)
{
- map_t *m;
+ map_t m;
struct mbr *mbr;
- struct gpt_ent *ent;
struct gpt_hdr *hdr;
+ struct gpt_ent *ent;
unsigned int i;
prop_dictionary_t props, mbr_dict, gpt_dict, type_dict;
prop_array_t mbr_array, gpt_array;
@@ -85,11 +86,11 @@ backup(void)
props = prop_dictionary_create();
PROP_ERR(props);
- propnum = prop_number_create_integer(secsz);
+ propnum = prop_number_create_integer(gpt->secsz);
PROP_ERR(propnum);
rc = prop_dictionary_set(props, "sector_size", propnum);
PROP_ERR(rc);
- m = map_first();
+ m = map_first(gpt);
while (m != NULL) {
switch (m->map_type) {
case MAP_TYPE_MBR:
@@ -222,7 +223,7 @@ backup(void)
PROP_ERR(gpt_array);
for (i = 1, ent = m->map_data;
(char *)ent < (char *)(m->map_data) +
- m->map_size * secsz; i++, ent++) {
+ m->map_size * gpt->secsz; i++, ent++) {
gpt_dict = prop_dictionary_create();
PROP_ERR(gpt_dict);
propnum = prop_number_create_integer(i);
@@ -285,24 +286,14 @@ backup(void)
prop_object_release(props);
fputs(propext, stdout);
free(propext);
+ return 0;
}
int
-cmd_backup(int argc, char *argv[])
+cmd_backup(gpt_t gpt, int argc, char *argv[])
{
- int fd;
-
- if (argc == optind)
+ if (argc != optind)
usage_backup();
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
- backup();
-
- gpt_close(fd);
- }
-
- return (0);
+ return backup(gpt);
}
Index: src/sbin/gpt/restore.c
diff -u src/sbin/gpt/restore.c:1.9 src/sbin/gpt/restore.c:1.10
--- src/sbin/gpt/restore.c:1.9 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/restore.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/create.c,v 1.11 2005/08/31 01:47:19 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: restore.c,v 1.9 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: restore.c,v 1.10 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -50,31 +50,32 @@ __RCSID("$NetBSD: restore.c,v 1.9 2015/1
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static int force;
-const char restoremsg[] = "restore [-F] device ...";
+const char restoremsg[] = "restore [-F]";
-__dead static void
+static int
usage_restore(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), restoremsg);
- exit(1);
+ return -1;
}
-#define PROP_ERR(x) if (!(x)) { \
- warn("proplib failure"); \
- return; \
- }
+#define PROP_ERR(x) if (!(x)) { \
+ gpt_warnx(gpt, "proplib failure"); \
+ return -1; \
+}
-static void
-restore(int fd)
+static int
+restore(gpt_t gpt)
{
gpt_uuid_t gpt_guid, uuid;
off_t firstdata, last, lastdata, gpe_start, gpe_end;
- map_t *map;
+ map_t map;
struct mbr *mbr;
struct gpt_hdr *hdr;
struct gpt_ent ent;
@@ -89,20 +90,20 @@ restore(int fd)
const char *s;
void *secbuf;
- last = mediasz / secsz - 1LL;
+ last = gpt->mediasz / gpt->secsz - 1LL;
- if (map_find(MAP_TYPE_PRI_GPT_HDR) != NULL ||
- map_find(MAP_TYPE_SEC_GPT_HDR) != NULL) {
+ if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL ||
+ map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) {
if (!force) {
- warnx("%s: error: device contains a GPT", device_name);
- return;
+ gpt_warnx(gpt, "Device contains a GPT");
+ return -1;
}
}
- map = map_find(MAP_TYPE_MBR);
+ map = map_find(gpt, MAP_TYPE_MBR);
if (map != NULL) {
if (!force) {
- warnx("%s: error: device contains a MBR", device_name);
- return;
+ gpt_warnx(gpt, "Device contains an MBR");
+ return -1;
}
/* Nuke the MBR in our internal map. */
map->map_type = MAP_TYPE_UNUSED;
@@ -110,17 +111,16 @@ restore(int fd)
props = prop_dictionary_internalize_from_file("/dev/stdin");
if (props == NULL) {
- warnx("error: unable to read/parse backup file");
- return;
+ gpt_warnx(gpt, "Unable to read/parse backup file");
+ return -1;
}
propnum = prop_dictionary_get(props, "sector_size");
PROP_ERR(propnum);
- if (!prop_number_equals_integer(propnum, secsz)) {
- warnx("%s: error: sector size does not match backup",
- device_name);
+ if (!prop_number_equals_integer(propnum, gpt->secsz)) {
+ gpt_warnx(gpt, "Sector size does not match backup");
prop_object_release(props);
- return;
+ return -1;
}
gpt_dict = prop_dictionary_get(props, "GPT_HDR");
@@ -129,25 +129,26 @@ restore(int fd)
propnum = prop_dictionary_get(gpt_dict, "revision");
PROP_ERR(propnum);
if (!prop_number_equals_unsigned_integer(propnum, 0x10000)) {
- warnx("backup is not revision 1.0");
+ gpt_warnx(gpt, "backup is not revision 1.0");
prop_object_release(gpt_dict);
prop_object_release(props);
- return;
+ return -1;
}
propnum = prop_dictionary_get(gpt_dict, "entries");
PROP_ERR(propnum);
entries = prop_number_integer_value(propnum);
- gpt_size = entries * sizeof(struct gpt_ent) / secsz;
- if (gpt_size * sizeof(struct gpt_ent) % secsz)
+ gpt_size = entries * sizeof(struct gpt_ent) / gpt->secsz;
+ if (gpt_size * sizeof(struct gpt_ent) % gpt->secsz)
gpt_size++;
propstr = prop_dictionary_get(gpt_dict, "guid");
PROP_ERR(propstr);
s = prop_string_cstring_nocopy(propstr);
if (gpt_uuid_parse(s, gpt_guid) != 0) {
- warnx("%s: not able to convert to an UUID", s);
- return;
+ gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+ // XXX: leak
+ return -1;
}
firstdata = gpt_size + 2; /* PMBR and GPT header */
lastdata = last - gpt_size - 1; /* alt. GPT table and header */
@@ -163,8 +164,8 @@ restore(int fd)
PROP_ERR(propstr);
s = prop_string_cstring_nocopy(propstr);
if (gpt_uuid_parse(s, uuid) != 0) {
- warnx("%s: not able to convert to an UUID", s);
- return;
+ gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+ return -1;
}
if (gpt_uuid_is_nil(uuid))
continue;
@@ -175,36 +176,36 @@ restore(int fd)
PROP_ERR(propnum);
gpe_end = prop_number_unsigned_integer_value(propnum);
if (gpe_start < firstdata || gpe_end > lastdata) {
- warnx("%s: error: backup GPT doesn't fit", device_name);
- return;
+ gpt_warnx(gpt, "Backup GPT doesn't fit");
+ return -1;
}
}
prop_object_iterator_release(propiter);
- secbuf = calloc(gpt_size + 1, secsz); /* GPT TABLE + GPT HEADER */
+ secbuf = calloc(gpt_size + 1, gpt->secsz); /* GPT TABLE + GPT HEADER */
if (secbuf == NULL) {
- warnx("not enough memory to create a sector buffer");
- return;
+ gpt_warnx(gpt, "not enough memory to create a sector buffer");
+ return -1;
}
- if (lseek(fd, 0LL, SEEK_SET) == -1) {
- warnx("%s: error: can't seek to beginning", device_name);
- return;
+ if (lseek(gpt->fd, 0LL, SEEK_SET) == -1) {
+ gpt_warnx(gpt, "Can't seek to beginning");
+ return -1;
}
for (i = 0; i < firstdata; i++) {
- if (write(fd, secbuf, secsz) == -1) {
- warnx("%s: error: can't write", device_name);
- return;
+ if (write(gpt->fd, secbuf, gpt->secsz) == -1) {
+ gpt_warnx(gpt, "Error writing");
+ return -1;
}
}
- if (lseek(fd, (lastdata + 1) * secsz, SEEK_SET) == -1) {
- warnx("%s: error: can't seek to end", device_name);
- return;
+ if (lseek(gpt->fd, (lastdata + 1) * gpt->secsz, SEEK_SET) == -1) {
+ gpt_warnx(gpt, "Can't seek to end");
+ return -1;
}
for (i = lastdata + 1; i <= last; i++) {
- if (write(fd, secbuf, secsz) == -1) {
- warnx("%s: error: can't write", device_name);
- return;
+ if (write(gpt->fd, secbuf, gpt->secsz) == -1) {
+ gpt_warnx(gpt, "Error writing");
+ return -1;
}
}
@@ -287,10 +288,10 @@ restore(int fd)
}
prop_object_iterator_release(propiter);
mbr->mbr_sig = htole16(MBR_SIG);
- if (lseek(fd, 0LL, SEEK_SET) == -1 ||
- write(fd, mbr, secsz) == -1) {
- warnx("%s: error: unable to write MBR", device_name);
- return;
+ if (lseek(gpt->fd, 0LL, SEEK_SET) == -1 ||
+ write(gpt->fd, mbr, gpt->secsz) == -1) {
+ gpt_warnx(gpt, "Unable to write MBR");
+ return -1;
}
propiter = prop_array_iterator(gpt_array);
@@ -301,15 +302,15 @@ restore(int fd)
PROP_ERR(propstr);
s = prop_string_cstring_nocopy(propstr);
if (gpt_uuid_parse(s, ent.ent_type) != 0) {
- warnx("%s: not able to convert to an UUID", s);
- return;
+ gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+ return -1;
}
propstr = prop_dictionary_get(gpt_dict, "guid");
PROP_ERR(propstr);
s = prop_string_cstring_nocopy(propstr);
if (gpt_uuid_parse(s, ent.ent_guid) != 0) {
- warnx("%s: not able to convert to an UUID", s);
- return;
+ gpt_warnx(gpt, "%s: not able to convert to an UUID", s);
+ return -1;
}
propnum = prop_dictionary_get(gpt_dict, "start");
PROP_ERR(propnum);
@@ -331,22 +332,24 @@ restore(int fd)
propnum = prop_dictionary_get(gpt_dict, "index");
PROP_ERR(propnum);
i = prop_number_integer_value(propnum);
- memcpy((char *)secbuf + secsz + ((i - 1) * sizeof(ent)), &ent,
- sizeof(ent));
+ memcpy((char *)secbuf + gpt->secsz + ((i - 1) * sizeof(ent)),
+ &ent, sizeof(ent));
}
prop_object_iterator_release(propiter);
- if (lseek(fd, 2 * secsz, SEEK_SET) == -1 ||
- write(fd, (char *)secbuf + 1 * secsz, gpt_size * secsz) == -1) {
- warnx("%s: error: unable to write primary GPT", device_name);
- return;
- }
- if (lseek(fd, (lastdata + 1) * secsz, SEEK_SET) == -1 ||
- write(fd, (char *)secbuf + 1 * secsz, gpt_size * secsz) == -1) {
- warnx("%s: error: unable to write secondary GPT", device_name);
- return;
+ if (lseek(gpt->fd, 2 * gpt->secsz, SEEK_SET) == -1 ||
+ write(gpt->fd, (char *)secbuf + 1 * gpt->secsz,
+ gpt_size * gpt->secsz) == -1) {
+ gpt_warnx(gpt, "Unable to write primary GPT");
+ return -1;
+ }
+ if (lseek(gpt->fd, (lastdata + 1) * gpt->secsz, SEEK_SET) == -1 ||
+ write(gpt->fd, (char *)secbuf + 1 * gpt->secsz,
+ gpt_size * gpt->secsz) == -1) {
+ gpt_warnx(gpt, "Unable to write secondary GPT");
+ return -1;
}
- memset(secbuf, 0, secsz);
+ memset(secbuf, 0, gpt->secsz);
hdr = (struct gpt_hdr *)secbuf;
memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
hdr->hdr_revision = htole32(GPT_HDR_REVISION);
@@ -359,13 +362,13 @@ restore(int fd)
hdr->hdr_lba_table = htole64(2);
hdr->hdr_entries = htole32(entries);
hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));
- hdr->hdr_crc_table =
- htole32(crc32((char *)secbuf + 1 * secsz, gpt_size * secsz));
+ hdr->hdr_crc_table = htole32(crc32((char *)secbuf + 1 * gpt->secsz,
+ gpt_size * gpt->secsz));
hdr->hdr_crc_self = htole32(crc32(hdr, GPT_HDR_SIZE));
- if (lseek(fd, 1 * secsz, SEEK_SET) == -1 ||
- write(fd, hdr, secsz) == -1) {
- warnx("%s: error: unable to write primary header", device_name);
- return;
+ if (lseek(gpt->fd, 1 * gpt->secsz, SEEK_SET) == -1 ||
+ write(gpt->fd, hdr, gpt->secsz) == -1) {
+ gpt_warnx(gpt, "Unable to write primary header");
+ return -1;
}
hdr->hdr_lba_self = htole64(last);
@@ -373,21 +376,20 @@ restore(int fd)
hdr->hdr_lba_table = htole64(lastdata + 1);
hdr->hdr_crc_self = 0;
hdr->hdr_crc_self = htole32(crc32(hdr, GPT_HDR_SIZE));
- if (lseek(fd, last * secsz, SEEK_SET) == -1 ||
- write(fd, hdr, secsz) == -1) {
- warnx("%s: error: unable to write secondary header",
- device_name);
- return;
+ if (lseek(gpt->fd, last * gpt->secsz, SEEK_SET) == -1 ||
+ write(gpt->fd, hdr, gpt->secsz) == -1) {
+ gpt_warnx(gpt, "Unable to write secondary header");
+ return -1;
}
prop_object_release(props);
- return;
+ return 0;
}
int
-cmd_restore(int argc, char *argv[])
+cmd_restore(gpt_t gpt, int argc, char *argv[])
{
- int ch, fd;
+ int ch;
while ((ch = getopt(argc, argv, "F")) != -1) {
switch(ch) {
@@ -395,22 +397,12 @@ cmd_restore(int argc, char *argv[])
force = 1;
break;
default:
- usage_restore();
+ return usage_restore();
}
}
- if (argc == optind)
- usage_restore();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- restore(fd);
-
- gpt_close(fd);
- }
+ if (argc != optind)
+ return usage_restore();
- return (0);
+ return restore(gpt);
}
Index: src/sbin/gpt/biosboot.c
diff -u src/sbin/gpt/biosboot.c:1.15 src/sbin/gpt/biosboot.c:1.16
--- src/sbin/gpt/biosboot.c:1.15 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/biosboot.c Tue Dec 1 04:05:33 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: biosboot.c,v 1.15 2015/11/29 00:14:46 christos Exp $ */
+/* $NetBSD: biosboot.c,v 1.16 2015/12/01 09:05:33 christos Exp $ */
/*
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#ifdef __RCSID
-__RCSID("$NetBSD: biosboot.c,v 1.15 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: biosboot.c,v 1.16 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/stat.h>
@@ -60,6 +60,7 @@ __RCSID("$NetBSD: biosboot.c,v 1.15 2015
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
#define DEFAULT_BOOTDIR "/usr/mdec"
#define DEFAULT_BOOTCODE "gptmbr.bin"
@@ -72,61 +73,65 @@ static unsigned int entry;
static uint8_t *label;
const char biosbootmsg[] = "biosboot [-c bootcode] [-i index] "
- "[-L label] device ...";
+ "[-L label]";
-__dead static void
+static int
usage_biosboot(void)
{
fprintf(stderr, "usage: %s %s\n", getprogname(), biosbootmsg);
- exit(1);
+ return -1;
}
static struct mbr*
-read_boot(void)
+read_boot(gpt_t gpt)
{
int bfd, ret = 0;
struct mbr *buf;
struct stat st;
- /* XXX how to do the following better? */
- if (bootpath == NULL) {
+ buf = NULL;
+ bfd = -1;
+
+ if (bootpath == NULL)
bootpath = strdup(DEFAULT_BOOTDIR "/" DEFAULT_BOOTCODE);
- } else {
- if (strchr(bootpath, '/') == 0) {
- char *p;
- if ((p = strdup(bootpath)) == NULL)
- err(1, "Malloc failed");
- free(bootpath);
- (void)asprintf(&bootpath, "%s/%s", DEFAULT_BOOTDIR, p);
- free(p);
- }
+ else if (*bootpath == '/')
+ bootpath = strdup(bootpath);
+ else {
+ if (asprintf(&bootpath, "%s/%s", DEFAULT_BOOTDIR, bootpath) < 0)
+ bootpath = NULL;
+ }
+
+ if (bootpath == NULL) {
+ gpt_warn(gpt, "Can't allocate memory for bootpath");
+ goto fail;
+ }
+
+ if ((buf = malloc((size_t)gpt->secsz)) == NULL) {
+ gpt_warn(gpt, "Can't allocate memory for sector");
+ goto fail;
}
- if (bootpath == NULL)
- err(1, "Malloc failed");
- if ((buf = malloc((size_t)secsz)) == NULL)
- err(1, "Malloc failed");
if ((bfd = open(bootpath, O_RDONLY)) < 0 || fstat(bfd, &st) == -1) {
- warn("%s", bootpath);
+ gpt_warn(gpt, "Can't open `%s'", bootpath);
goto fail;
}
if (st.st_size != MBR_DSN_OFFSET) {
- warnx("%s: the bootcode does not match expected size",
- bootpath);
+ gpt_warnx(gpt, "The bootcode in `%s' does not match the"
+ " expected size %u", bootpath, MBR_DSN_OFFSET);
goto fail;
}
if (read(bfd, buf, st.st_size) != st.st_size) {
- warn("%s", bootpath);
+ gpt_warn(gpt, "Error reading from `%s'", bootpath);
goto fail;
}
ret++;
fail:
- if (bfd >= 0)
+ if (bfd != -1)
close(bfd);
if (ret == 0) {
free(buf);
@@ -135,45 +140,43 @@ read_boot(void)
return buf;
}
-static void
-biosboot(int fd)
+static int
+set_bootable(gpt_t gpt, map_t map, map_t tbl, unsigned int i)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *mbrmap, *m;
+ unsigned int j;
+ struct gpt_hdr *hdr = map->map_data;
+ struct gpt_ent *ent;
+ unsigned int ne = le32toh(hdr->hdr_entries);
+
+ for (j = 0; j < ne; j++) {
+ ent = gpt_ent(map, tbl, j);
+ ent->ent_attr &= ~GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
+ }
+
+ ent = gpt_ent(map, tbl, i);
+ ent->ent_attr |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
+
+ return gpt_write_crc(gpt, map, tbl);
+}
+
+static int
+biosboot(gpt_t gpt)
+{
+ map_t mbrmap, m;
struct mbr *mbr, *bootcode;
- struct gpt_hdr *hdr;
+ unsigned int i;
struct gpt_ent *ent;
- unsigned int i, j;
/*
* Parse and validate partition maps
*/
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
+ if (gpt_hdr(gpt) == NULL)
+ return -1;
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
-
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
-
- mbrmap = map_find(MAP_TYPE_PMBR);
+ mbrmap = map_find(gpt, MAP_TYPE_PMBR);
if (mbrmap == NULL || mbrmap->map_start != 0) {
- warnx("%s: error: no valid Protective MBR found", device_name);
- return;
+ gpt_warnx(gpt, "No valid Protective MBR found");
+ return -1;
}
mbr = mbrmap->map_data;
@@ -181,9 +184,9 @@ biosboot(int fd)
/*
* Update the boot code
*/
- if ((bootcode = read_boot()) == NULL) {
- warnx("error reading bootcode");
- return;
+ if ((bootcode = read_boot(gpt)) == NULL) {
+ gpt_warnx(gpt, "Error reading bootcode");
+ return -1;
}
(void)memcpy(&mbr->mbr_code, &bootcode->mbr_code,
sizeof(mbr->mbr_code));
@@ -192,7 +195,7 @@ biosboot(int fd)
/*
* Walk through the GPT and see where we can boot from
*/
- for (m = map_first(); m != NULL; m = m->map_next) {
+ for (m = map_first(gpt); m != NULL; m = m->map_next) {
if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
continue;
@@ -214,69 +217,37 @@ biosboot(int fd)
}
if (m == NULL) {
- warnx("error: no bootable partition");
- return;
+ gpt_warnx(gpt, "No bootable partition");
+ return -1;
}
i = m->map_index - 1;
- hdr = gpt->map_data;
-
- for (j = 0; j < le32toh(hdr->hdr_entries); j++) {
- ent = (void*)((char*)tbl->map_data + j * le32toh(hdr->hdr_entsz));
- ent->ent_attr &= ~GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
- }
-
- ent = (void*)((char*)tbl->map_data + i * le32toh(hdr->hdr_entsz));
- ent->ent_attr |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
-
-
- hdr = tpg->map_data;
-
- for (j = 0; j < le32toh(hdr->hdr_entries); j++) {
- ent = (void*)((char*)lbt->map_data + j * le32toh(hdr->hdr_entsz));
- ent->ent_attr &= ~GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
- }
-
- ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
- ent->ent_attr |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE;
-
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
+ if (set_bootable(gpt, gpt->gpt, gpt->tbl, i) == -1)
+ return -1;
+ if (set_bootable(gpt, gpt->tpg, gpt->lbt, i) == -1)
+ return -1;
- if (gpt_write(fd, mbrmap) == -1) {
- warnx("error: cannot update Protective MBR");
- return;
+ if (gpt_write(gpt, mbrmap) == -1) {
+ gpt_warnx(gpt, "Cannot update Protective MBR");
+ return -1;
}
- printf("partition %d marked as bootable\n", i + 1);
+ gpt_msg(gpt, "Partition %d marked as bootable", i + 1);
+ return 0;
}
int
-cmd_biosboot(int argc, char *argv[])
+cmd_biosboot(gpt_t gpt, int argc, char *argv[])
{
#ifdef DIOCGWEDGEINFO
struct dkwedge_info dkw;
#endif
- struct stat sb;
- char devpath[MAXPATHLEN];
char *dev, *p;
- int ch, fd;
+ int ch;
+ gpt_t ngpt = gpt;
while ((ch = getopt(argc, argv, "c:i:L:")) != -1) {
switch(ch) {
@@ -299,51 +270,34 @@ cmd_biosboot(int argc, char *argv[])
label = (uint8_t *)strdup(optarg);
break;
default:
- usage_biosboot();
+ return usage_biosboot();
}
}
- if (argc == optind)
- usage_biosboot();
+ if (argc != optind)
+ return usage_biosboot();
- while (optind < argc) {
- dev = argv[optind++];
- start = 0;
- size = 0;
-
- /*
- * If a dk wedge was specified, loader should be
- * installed onto parent device
- */
- if ((fd = opendisk(dev, O_RDONLY, devpath, sizeof(devpath), 0))
- == -1)
- goto next;
- if (fstat(fd, &sb) == -1)
- goto close;
+ start = 0;
+ size = 0;
#ifdef DIOCGWEDGEINFO
- if ((sb.st_mode & S_IFMT) != S_IFREG &&
- ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
- if (entry > 0)
- /* wedges and indexes are mutually exclusive */
- usage_biosboot();
- dev = dkw.dkw_parent;
- start = dkw.dkw_offset;
- size = dkw.dkw_size;
- }
-#endif
- close:
- close(fd);
-
- fd = gpt_open(dev, 0);
- next:
- if (fd == -1)
- continue;
-
- biosboot(fd);
-
- gpt_close(fd);
+ if ((gpt->sb.st_mode & S_IFMT) != S_IFREG &&
+ ioctl(gpt->fd, DIOCGWEDGEINFO, &dkw) != -1) {
+ if (entry > 0)
+ /* wedges and indexes are mutually exclusive */
+ return usage_biosboot();
+ dev = dkw.dkw_parent;
+ start = dkw.dkw_offset;
+ size = dkw.dkw_size;
+ ngpt = gpt_open(dev, gpt->flags, gpt->verbose,
+ gpt->mediasz, gpt->secsz);
+ if (ngpt == NULL)
+ return -1;
}
+#endif
+ biosboot(ngpt);
+ if (ngpt != gpt)
+ gpt_close(ngpt);
- return (0);
+ return 0;
}
Index: src/sbin/gpt/create.c
diff -u src/sbin/gpt/create.c:1.13 src/sbin/gpt/create.c:1.14
--- src/sbin/gpt/create.c:1.13 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/create.c Tue Dec 1 04:05:33 2015
@@ -33,10 +33,12 @@
__FBSDID("$FreeBSD: src/sbin/gpt/create.c,v 1.11 2005/08/31 01:47:19 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: create.c,v 1.13 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: create.c,v 1.14 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
#include <sys/bootblock.h>
#include <err.h>
@@ -48,47 +50,47 @@ __RCSID("$NetBSD: create.c,v 1.13 2015/1
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static int force;
+static u_int parts;
static int primary_only;
-const char createmsg[] = "create [-fp] device ...";
+const char createmsg[] = "create [-fP] [-p <partitions>]";
-__dead static void
+static int
usage_create(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), createmsg);
- exit(1);
+ return -1;
}
-static void
-create(int fd)
+static int
+create(gpt_t gpt)
{
off_t blocks, last;
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *map;
+ map_t map;
struct mbr *mbr;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
unsigned int i;
+ void *p;
- last = mediasz / secsz - 1LL;
+ last = gpt->mediasz / gpt->secsz - 1LL;
- if (map_find(MAP_TYPE_PRI_GPT_HDR) != NULL ||
- map_find(MAP_TYPE_SEC_GPT_HDR) != NULL) {
- warnx("%s: error: device already contains a GPT", device_name);
- return;
+ if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL ||
+ map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) {
+ gpt_warnx(gpt, "Device already contains a GPT");
+ return -1;
}
- map = map_find(MAP_TYPE_MBR);
+ map = map_find(gpt, MAP_TYPE_MBR);
if (map != NULL) {
if (!force) {
- warnx("%s: error: device contains a MBR", device_name);
- return;
+ gpt_warnx(gpt, "Device contains a MBR");
+ return -1;
}
-
/* Nuke the MBR in our internal map. */
map->map_type = MAP_TYPE_UNUSED;
}
@@ -96,44 +98,36 @@ create(int fd)
/*
* Create PMBR.
*/
- if (map_find(MAP_TYPE_PMBR) == NULL) {
- if (map_free(0LL, 1LL) == 0) {
- warnx("%s: error: no room for the PMBR", device_name);
- return;
+ if (map_find(gpt, MAP_TYPE_PMBR) == NULL) {
+ if (map_free(gpt, 0LL, 1LL) == 0) {
+ gpt_warnx(gpt, "No room for the PMBR");
+ return -1;
+ }
+ mbr = gpt_read(gpt, 0LL, 1);
+ if (mbr == NULL) {
+ gpt_warnx(gpt, "Error reading MBR");
+ return -1;
}
- mbr = gpt_read(fd, 0LL, 1);
memset(mbr, 0, sizeof(*mbr));
mbr->mbr_sig = htole16(MBR_SIG);
- mbr->mbr_part[0].part_shd = 0x00;
- mbr->mbr_part[0].part_ssect = 0x02;
- mbr->mbr_part[0].part_scyl = 0x00;
- mbr->mbr_part[0].part_typ = MBR_PTYPE_PMBR;
- mbr->mbr_part[0].part_ehd = 0xfe;
- mbr->mbr_part[0].part_esect = 0xff;
- mbr->mbr_part[0].part_ecyl = 0xff;
- mbr->mbr_part[0].part_start_lo = htole16(1);
- if (last > 0xffffffff) {
- mbr->mbr_part[0].part_size_lo = htole16(0xffff);
- mbr->mbr_part[0].part_size_hi = htole16(0xffff);
- } else {
- mbr->mbr_part[0].part_size_lo = htole16(last);
- mbr->mbr_part[0].part_size_hi = htole16(last >> 16);
- }
- map = map_add(0LL, 1LL, MAP_TYPE_PMBR, mbr);
- gpt_write(fd, map);
+ gpt_create_pmbr_part(mbr->mbr_part, last);
+
+ map = map_add(gpt, 0LL, 1LL, MAP_TYPE_PMBR, mbr);
+ gpt_write(gpt, map);
}
/* Get the amount of free space after the MBR */
- blocks = map_free(1LL, 0LL);
+ blocks = map_free(gpt, 1LL, 0LL);
if (blocks == 0LL) {
- warnx("%s: error: no room for the GPT header", device_name);
- return;
+ gpt_warnx(gpt, "No room for the GPT header");
+ return -1;
}
/* Don't create more than parts entries. */
- if ((uint64_t)(blocks - 1) * secsz > parts * sizeof(struct gpt_ent)) {
- blocks = (parts * sizeof(struct gpt_ent)) / secsz;
- if ((parts * sizeof(struct gpt_ent)) % secsz)
+ if ((uint64_t)(blocks - 1) * gpt->secsz >
+ parts * sizeof(struct gpt_ent)) {
+ blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz;
+ if ((parts * sizeof(struct gpt_ent)) % gpt->secsz)
blocks++;
blocks++; /* Don't forget the header itself */
}
@@ -146,103 +140,111 @@ create(int fd)
* Get the amount of free space at the end of the device and
* calculate the size for the GPT structures.
*/
- map = map_last();
+ map = map_last(gpt);
if (map->map_type != MAP_TYPE_UNUSED) {
- warnx("%s: error: no room for the backup header", device_name);
- return;
+ gpt_warnx(gpt, "No room for the backup header");
+ return -1;
}
if (map->map_size < blocks)
blocks = map->map_size;
if (blocks == 1LL) {
- warnx("%s: error: no room for the GPT table", device_name);
- return;
+ gpt_warnx(gpt, "No room for the GPT table");
+ return -1;
+ }
+
+ if ((p = calloc(1, gpt->secsz)) == NULL) {
+ gpt_warnx(gpt, "Can't allocate the GPT");
+ return -1;
+ }
+ if ((gpt->gpt = map_add(gpt, 1LL, 1LL,
+ MAP_TYPE_PRI_GPT_HDR, p)) == NULL) {
+ free(p);
+ gpt_warnx(gpt, "Can't add the GPT");
+ return -1;
}
blocks--; /* Number of blocks in the GPT table. */
- gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR, calloc(1, secsz));
- tbl = map_add(2LL, blocks, MAP_TYPE_PRI_GPT_TBL,
- calloc(blocks, secsz));
- if (gpt == NULL || tbl == NULL)
- return;
+ if ((p = calloc(blocks, gpt->secsz)) == NULL) {
+ gpt_warnx(gpt, "Can't allocate the GPT table");
+ return -1;
+ }
+ if ((gpt->tbl = map_add(gpt, 2LL, blocks,
+ MAP_TYPE_PRI_GPT_TBL, p)) == NULL) {
+ free(p);
+ gpt_warnx(gpt, "Can't add the GPT table");
+ return -1;
+ }
- hdr = gpt->map_data;
+ hdr = gpt->gpt->map_data;
memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
hdr->hdr_revision = htole32(GPT_HDR_REVISION);
hdr->hdr_size = htole32(GPT_HDR_SIZE);
- hdr->hdr_lba_self = htole64(gpt->map_start);
+ hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
hdr->hdr_lba_alt = htole64(last);
- hdr->hdr_lba_start = htole64(tbl->map_start + blocks);
+ hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks);
hdr->hdr_lba_end = htole64(last - blocks - 1LL);
gpt_uuid_generate(hdr->hdr_guid);
- hdr->hdr_lba_table = htole64(tbl->map_start);
- hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent));
+ hdr->hdr_lba_table = htole64(gpt->tbl->map_start);
+ hdr->hdr_entries = htole32((blocks * gpt->secsz) /
+ sizeof(struct gpt_ent));
if (le32toh(hdr->hdr_entries) > parts)
hdr->hdr_entries = htole32(parts);
hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));
- ent = tbl->map_data;
+ ent = gpt->tbl->map_data;
for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
gpt_uuid_generate(ent[i].ent_guid);
}
- hdr->hdr_crc_table = htole32(crc32(ent, le32toh(hdr->hdr_entries) *
- le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
/*
* Create backup GPT if the user didn't suppress it.
*/
if (!primary_only) {
- tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR,
- calloc(1, secsz));
- lbt = map_add(last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,
- tbl->map_data);
- memcpy(tpg->map_data, gpt->map_data, secsz);
- hdr = tpg->map_data;
- hdr->hdr_lba_self = htole64(tpg->map_start);
- hdr->hdr_lba_alt = htole64(gpt->map_start);
- hdr->hdr_lba_table = htole64(lbt->map_start);
- hdr->hdr_crc_self = 0; /* Don't ever forget this! */
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
+ // XXX: error checks
+ gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR,
+ calloc(1, gpt->secsz));
+ gpt->lbt = map_add(gpt, last - blocks, blocks,
+ MAP_TYPE_SEC_GPT_TBL, gpt->tbl->map_data);
+ memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
+ hdr = gpt->tpg->map_data;
+ hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+ hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+ hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
}
+ return 0;
}
int
-cmd_create(int argc, char *argv[])
+cmd_create(gpt_t gpt, int argc, char *argv[])
{
- int ch, fd;
+ int ch;
- while ((ch = getopt(argc, argv, "fp")) != -1) {
+ parts = 128;
+
+ while ((ch = getopt(argc, argv, "fPp:")) != -1) {
switch(ch) {
case 'f':
force = 1;
break;
- case 'p':
+ case 'P':
primary_only = 1;
break;
+ case 'p':
+ parts = atoi(optarg);
+ break;
default:
- usage_create();
+ return usage_create();
}
}
- if (argc == optind)
- usage_create();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], force);
- if (fd == -1)
- continue;
-
- create(fd);
-
- gpt_close(fd);
- }
+ if (argc != optind)
+ return usage_create();
- return (0);
+ return create(gpt);
}
Index: src/sbin/gpt/destroy.c
diff -u src/sbin/gpt/destroy.c:1.7 src/sbin/gpt/destroy.c:1.8
--- src/sbin/gpt/destroy.c:1.7 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/destroy.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/destroy.c,v 1.6 2005/08/31 01:47:19 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: destroy.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: destroy.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,54 +47,63 @@ __RCSID("$NetBSD: destroy.c,v 1.7 2015/1
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static int recoverable;
static int force;
-const char destroymsg[] = "destroy [-rf] device ...";
+const char destroymsg[] = "destroy [-rf]";
-__dead static void
+static int
usage_destroy(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), destroymsg);
- exit(1);
+ return -1;
}
-static void
-destroy(int fd)
+static int
+destroy(gpt_t gpt)
{
- map_t *pri_hdr, *sec_hdr;
+ map_t pri_hdr, sec_hdr;
- pri_hdr = map_find(MAP_TYPE_PRI_GPT_HDR);
- sec_hdr = map_find(MAP_TYPE_SEC_GPT_HDR);
+ pri_hdr = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+ sec_hdr = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
if (pri_hdr == NULL && sec_hdr == NULL) {
- warnx("%s: error: device doesn't contain a GPT", device_name);
- return;
+ gpt_warnx(gpt, "Device doesn't contain a GPT");
+ return -1;
}
if (recoverable && sec_hdr == NULL) {
- warnx("%s: error: recoverability not possible", device_name);
- return;
+ gpt_warnx(gpt, "Recoverability not possible");
+ return -1;
}
if (pri_hdr != NULL) {
- memset(pri_hdr->map_data, 0, secsz);
- gpt_write(fd, pri_hdr);
+ memset(pri_hdr->map_data, 0, gpt->secsz);
+ if (gpt_write(gpt, pri_hdr) == -1) {
+ gpt_warnx(gpt, "Error writing primary header");
+ return -1;
+ }
}
if (!recoverable && sec_hdr != NULL) {
- memset(sec_hdr->map_data, 0, secsz);
- gpt_write(fd, sec_hdr);
+ memset(sec_hdr->map_data, 0, gpt->secsz);
+ if (gpt_write(gpt, sec_hdr) == -1) {
+ gpt_warnx(gpt, "Error writing backup header");
+ return -1;
+ }
}
+
+ return 0;
}
int
-cmd_destroy(int argc, char *argv[])
+cmd_destroy(gpt_t gpt, int argc, char *argv[])
{
- int ch, fd;
+ int ch;
while ((ch = getopt(argc, argv, "fr")) != -1) {
switch(ch) {
@@ -105,22 +114,12 @@ cmd_destroy(int argc, char *argv[])
recoverable = 1;
break;
default:
- usage_destroy();
+ return usage_destroy();
}
}
- if (argc == optind)
- usage_destroy();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], force);
- if (fd == -1)
- continue;
-
- destroy(fd);
-
- gpt_close(fd);
- }
+ if (argc != optind)
+ return usage_destroy();
- return (0);
+ return destroy(gpt);
}
Index: src/sbin/gpt/recover.c
diff -u src/sbin/gpt/recover.c:1.7 src/sbin/gpt/recover.c:1.8
--- src/sbin/gpt/recover.c:1.7 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/recover.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/recover.c,v 1.8 2005/08/31 01:47:19 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: recover.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: recover.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,125 +47,130 @@ __RCSID("$NetBSD: recover.c,v 1.7 2015/1
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static int recoverable;
-const char recovermsg[] = "recover device ...";
+const char recovermsg[] = "recover";
-__dead static void
+static int
usage_recover(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), recovermsg);
- exit(1);
+ return -1;
}
-static void
-recover(int fd)
+static int
+recover(gpt_t gpt)
{
uint64_t last;
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
struct gpt_hdr *hdr;
- if (map_find(MAP_TYPE_MBR) != NULL) {
- warnx("%s: error: device contains a MBR", device_name);
- return;
- }
-
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
-
- if (gpt == NULL && tpg == NULL) {
- warnx("%s: no primary or secondary GPT headers, can't recover",
- device_name);
- return;
- }
- if (tbl == NULL && lbt == NULL) {
- warnx("%s: no primary or secondary GPT tables, can't recover",
- device_name);
- return;
- }
-
- last = mediasz / secsz - 1LL;
-
- if (gpt != NULL &&
- ((struct gpt_hdr *)(gpt->map_data))->hdr_lba_alt != last) {
- warnx("%s: media size has changed, please use 'gpt resizedisk'",
- device_name);
- return;
- }
-
- if (tbl != NULL && lbt == NULL) {
- lbt = map_add(last - tbl->map_size, tbl->map_size,
- MAP_TYPE_SEC_GPT_TBL, tbl->map_data);
- if (lbt == NULL) {
- warnx("%s: adding secondary GPT table failed",
- device_name);
- return;
- }
- gpt_write(fd, lbt);
- warnx("%s: recovered secondary GPT table from primary",
- device_name);
- } else if (tbl == NULL && lbt != NULL) {
- tbl = map_add(2LL, lbt->map_size, MAP_TYPE_PRI_GPT_TBL,
- lbt->map_data);
- if (tbl == NULL) {
- warnx("%s: adding primary GPT table failed",
- device_name);
- return;
- }
- gpt_write(fd, tbl);
- warnx("%s: recovered primary GPT table from secondary",
- device_name);
- }
-
- if (gpt != NULL && tpg == NULL) {
- tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR,
- calloc(1, secsz));
- if (tpg == NULL) {
- warnx("%s: adding secondary GPT header failed",
- device_name);
- return;
- }
- memcpy(tpg->map_data, gpt->map_data, secsz);
- hdr = tpg->map_data;
- hdr->hdr_lba_self = htole64(tpg->map_start);
- hdr->hdr_lba_alt = htole64(gpt->map_start);
- hdr->hdr_lba_table = htole64(lbt->map_start);
+ if (map_find(gpt, MAP_TYPE_MBR) != NULL) {
+ gpt_warnx(gpt, "Device contains an MBR");
+ return -1;
+ }
+
+ gpt->gpt = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+ gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+ gpt->tbl = map_find(gpt, MAP_TYPE_PRI_GPT_TBL);
+ gpt->lbt = map_find(gpt, MAP_TYPE_SEC_GPT_TBL);
+
+ if (gpt->gpt == NULL && gpt->tpg == NULL) {
+ gpt_warnx(gpt, "No primary or secondary GPT headers, "
+ "can't recover");
+ return -1;
+ }
+ if (gpt->tbl == NULL && gpt->lbt == NULL) {
+ gpt_warnx(gpt, "No primary or secondary GPT tables, "
+ "can't recover");
+ return -1;
+ }
+
+ last = gpt->mediasz / gpt->secsz - 1LL;
+
+ if (gpt->gpt != NULL &&
+ ((struct gpt_hdr *)(gpt->gpt->map_data))->hdr_lba_alt != last) {
+ gpt_warnx(gpt, "Media size has changed, please use "
+ "'gpt resizedisk'");
+ return -1;
+ }
+
+ if (gpt->tbl != NULL && gpt->lbt == NULL) {
+ gpt->lbt = map_add(gpt, last - gpt->tbl->map_size,
+ gpt->tbl->map_size, MAP_TYPE_SEC_GPT_TBL,
+ gpt->tbl->map_data);
+ if (gpt->lbt == NULL) {
+ gpt_warnx(gpt, "Adding secondary GPT table failed");
+ return -1;
+ }
+ if (gpt_write(gpt, gpt->lbt) == -1) {
+ gpt_warnx(gpt, "Writing secondary GPT table failed");
+ return -1;
+ }
+ gpt_msg(gpt, "Recovered secondary GPT table from primary");
+ } else if (gpt->tbl == NULL && gpt->lbt != NULL) {
+ gpt->tbl = map_add(gpt, 2LL, gpt->lbt->map_size,
+ MAP_TYPE_PRI_GPT_TBL, gpt->lbt->map_data);
+ if (gpt->tbl == NULL) {
+ gpt_warnx(gpt, "Adding primary GPT table failed");
+ return -1;
+ }
+ if (gpt_write(gpt, gpt->tbl) == -1) {
+ gpt_warnx(gpt, "Writing primary GPT table failed");
+ return -1;
+ }
+ gpt_msg(gpt, "Recovered primary GPT table from secondary");
+ }
+
+ if (gpt->gpt != NULL && gpt->tpg == NULL) {
+ gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR,
+ calloc(1, gpt->secsz));
+ if (gpt->tpg == NULL) {
+ gpt_warnx(gpt, "Adding secondary GPT header failed");
+ return -1;
+ }
+ memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
+ hdr = gpt->tpg->map_data;
+ hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+ hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+ hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
hdr->hdr_crc_self = 0;
hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
- gpt_write(fd, tpg);
- warnx("%s: recovered secondary GPT header from primary",
- device_name);
- } else if (gpt == NULL && tpg != NULL) {
- gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
- calloc(1, secsz));
- if (gpt == NULL) {
- warnx("%s: adding primary GPT header failed",
- device_name);
- return;
- }
- memcpy(gpt->map_data, tpg->map_data, secsz);
- hdr = gpt->map_data;
- hdr->hdr_lba_self = htole64(gpt->map_start);
- hdr->hdr_lba_alt = htole64(tpg->map_start);
- hdr->hdr_lba_table = htole64(tbl->map_start);
+ if (gpt_write(gpt, gpt->tpg) == -1) {
+ gpt_warnx(gpt, "Writing secondary GPT header failed");
+ return -1;
+ }
+ gpt_msg(gpt, "Recovered secondary GPT header from primary");
+ } else if (gpt->gpt == NULL && gpt->tpg != NULL) {
+ gpt->gpt = map_add(gpt, 1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
+ calloc(1, gpt->secsz));
+ if (gpt->gpt == NULL) {
+ gpt_warnx(gpt, "Adding primary GPT header failed");
+ return -1;
+ }
+ memcpy(gpt->gpt->map_data, gpt->tpg->map_data, gpt->secsz);
+ hdr = gpt->gpt->map_data;
+ hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
+ hdr->hdr_lba_alt = htole64(gpt->tpg->map_start);
+ hdr->hdr_lba_table = htole64(gpt->tbl->map_start);
hdr->hdr_crc_self = 0;
hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
- gpt_write(fd, gpt);
- warnx("%s: recovered primary GPT header from secondary",
- device_name);
+ if (gpt_write(gpt, gpt->gpt) == -1) {
+ gpt_warnx(gpt, "Writing primary GPT header failed");
+ return -1;
+ }
+ gpt_msg(gpt, "Recovered primary GPT header from secondary");
}
+ return 0;
}
int
-cmd_recover(int argc, char *argv[])
+cmd_recover(gpt_t gpt, int argc, char *argv[])
{
- int ch, fd;
+ int ch;
while ((ch = getopt(argc, argv, "r")) != -1) {
switch(ch) {
@@ -173,22 +178,12 @@ cmd_recover(int argc, char *argv[])
recoverable = 1;
break;
default:
- usage_recover();
+ return usage_recover();
}
}
- if (argc == optind)
+ if (argc != optind)
usage_recover();
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- recover(fd);
-
- gpt_close(fd);
- }
-
- return (0);
+ return recover(gpt);
}
Index: src/sbin/gpt/resizedisk.c
diff -u src/sbin/gpt/resizedisk.c:1.7 src/sbin/gpt/resizedisk.c:1.8
--- src/sbin/gpt/resizedisk.c:1.7 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/resizedisk.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: resizedisk.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: resizedisk.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/bootblock.h>
@@ -48,18 +48,19 @@ __RCSID("$NetBSD: resizedisk.c,v 1.7 201
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
-static uint64_t sector, size;
+static off_t sector, size;
-const char resizediskmsg[] = "resizedisk [-s size] device ...";
+const char resizediskmsg[] = "resizedisk [-s size]";
-__dead static void
+static int
usage_resizedisk(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), resizediskmsg);
- exit(1);
+ return -1;
}
/*
@@ -73,84 +74,78 @@ usage_resizedisk(void)
* - relocate or create new secondary
* - when shrinking, verify that table fits
*/
-static void
-resizedisk(int fd)
+static int
+resizedisk(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *mbrmap;
+ map_t mbrmap;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
struct mbr *mbr;
- uint64_t last, oldloc, newloc, lastdata, gpt_size;
+ off_t last, oldloc, newloc, lastdata, gpt_size;
int i;
- last = mediasz / secsz - 1;
+ last = gpt->mediasz / gpt->secsz - 1;
lastdata = 0;
newloc = 0;
if (sector > last) {
- warnx("%s: specified size is larger then the disk",
- device_name);
- return;
+ gpt_warnx(gpt, "specified size is larger then the disk");
+ return -1;
}
- mbrmap = map_find(MAP_TYPE_PMBR);
+ mbrmap = map_find(gpt, MAP_TYPE_PMBR);
if (mbrmap == NULL || mbrmap->map_start != 0) {
- warnx("%s: error: no valid Protective MBR found", device_name);
- return;
+ gpt_warnx(gpt, "No valid PMBR found");
+ return -1;
}
mbr = mbrmap->map_data;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
+ gpt->gpt = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
ent = NULL;
if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
+ gpt_warnx(gpt, "No primary GPT header; run create or recover");
+ return -1;
}
- hdr = gpt->map_data;
+ hdr = gpt->gpt->map_data;
oldloc = le64toh(hdr->hdr_lba_alt);
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL)
- if (gpt_gpt(fd, oldloc, 1))
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
-
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
+ gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+ if (gpt->tpg == NULL)
+ if (gpt_gpt(gpt, oldloc, 1))
+ gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+
+ gpt->tbl = map_find(gpt, MAP_TYPE_PRI_GPT_TBL);
+ if (gpt->tbl == NULL) {
+ gpt_warnx(gpt, "Run recover");
+ return -1;
}
- gpt_size = tbl->map_size;
+ gpt_size = gpt->tbl->map_size;
if (sector == oldloc) {
- warnx("%s: device is already the specified size", device_name);
- return;
+ gpt_warnx(gpt, "Device is already the specified size");
+ return 0;
}
if (sector == 0 && last == oldloc) {
- warnx("%s: device hasn't changed size", device_name);
- return;
+ gpt_warnx(gpt, "Device hasn't changed size");
+ return 0;
}
- for (ent = tbl->map_data; ent <
- (struct gpt_ent *)((char *)tbl->map_data +
+ for (ent = gpt->tbl->map_data; ent <
+ (struct gpt_ent *)((char *)gpt->tbl->map_data +
le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)); ent++) {
if (!gpt_uuid_is_nil(ent->ent_type) &&
- (le64toh(ent->ent_lba_end) > lastdata)) {
+ ((off_t)le64toh(ent->ent_lba_end) > lastdata)) {
lastdata = le64toh(ent->ent_lba_end);
}
}
if (sector - gpt_size <= lastdata) {
- warnx("%s: not enough space at %" PRIu64
- " for secondary GPT table", device_name, sector);
- return;
+ gpt_warnx(gpt, "Not enough space at %" PRIu64
+ " for secondary GPT table", sector);
+ return -1;
}
if (last - gpt_size <= lastdata) {
- warnx("%s: not enough space for new secondary GPT table",
- device_name);
- return;
+ gpt_warnx(gpt, "Not enough space for new secondary GPT table");
+ return -1;
}
if (sector > oldloc)
@@ -160,55 +155,51 @@ resizedisk(int fd)
if (sector == 0 && last > oldloc)
newloc = last;
if (newloc > 0) {
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
+ if (gpt->tpg == NULL) {
+ gpt_warnx(gpt, "No secondary GPT header; run recover");
+ return -1;
}
- if (lbt == NULL) {
- warnx("%s: error: run recover -- trust me",
- device_name);
- return;
+ if (gpt->lbt == NULL) {
+ gpt_warnx(gpt, "Run recover");
+ return -1;
}
- tpg->map_start = newloc;
- lbt->map_start = newloc - gpt_size;
+ gpt->tpg->map_start = newloc;
+ gpt->lbt->map_start = newloc - gpt_size;
} else {
if (sector > 0)
newloc = sector;
else
newloc = last;
- tpg = map_add(newloc, 1LL, MAP_TYPE_SEC_GPT_HDR,
- calloc(1, secsz));
- lbt = map_add(newloc - gpt_size, gpt_size, MAP_TYPE_SEC_GPT_TBL,
- tbl->map_data);
- memcpy(tpg->map_data, gpt->map_data, secsz);
+ gpt->tpg = map_add(gpt, newloc, 1LL, MAP_TYPE_SEC_GPT_HDR,
+ calloc(1, gpt->secsz));
+ gpt->lbt = map_add(gpt, newloc - gpt_size, gpt_size,
+ MAP_TYPE_SEC_GPT_TBL, gpt->tbl->map_data);
+ memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
}
- hdr = gpt->map_data;
- hdr->hdr_lba_alt = tpg->map_start;
+ hdr = gpt->gpt->map_data;
+ hdr->hdr_lba_alt = gpt->tpg->map_start;
hdr->hdr_crc_self = 0;
- hdr->hdr_lba_end = htole64(lbt->map_start - 1);
+ hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1);
hdr->hdr_crc_self =
- htole32(crc32(gpt->map_data, GPT_HDR_SIZE));
- gpt_write(fd, gpt);
+ htole32(crc32(gpt->gpt->map_data, GPT_HDR_SIZE));
+ gpt_write(gpt, gpt->gpt);
- hdr = tpg->map_data;
- hdr->hdr_lba_self = htole64(tpg->map_start);
- hdr->hdr_lba_alt = htole64(gpt->map_start);
- hdr->hdr_lba_end = htole64(lbt->map_start - 1);
- hdr->hdr_lba_table = htole64(lbt->map_start);
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self =
- htole32(crc32(tpg->map_data, GPT_HDR_SIZE));
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
+ hdr = gpt->tpg->map_data;
+ hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+ hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+ hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1);
+ hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
+
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
for (i = 0; i < 4; i++)
if (mbr->mbr_part[0].part_typ == MBR_PTYPE_PMBR)
break;
if (i == 4) {
- warnx("%s: no valid PMBR partition found", device_name);
- return;
+ gpt_warnx(gpt, "No valid PMBR partition found");
+ return -1;
}
if (last > 0xffffffff) {
mbr->mbr_part[0].part_size_lo = htole16(0xffff);
@@ -217,33 +208,36 @@ resizedisk(int fd)
mbr->mbr_part[0].part_size_lo = htole16(last);
mbr->mbr_part[0].part_size_hi = htole16(last >> 16);
}
- gpt_write(fd, mbrmap);
+ if (gpt_write(gpt, mbrmap) == -1) {
+ gpt_warnx(gpt, "Error writing PMBR");
+ return -1;
+ }
- return;
+ return 0;
}
int
-cmd_resizedisk(int argc, char *argv[])
+cmd_resizedisk(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
int64_t human_num;
while ((ch = getopt(argc, argv, "s:")) != -1) {
switch(ch) {
case 's':
if (sector > 0 || size > 0)
- usage_resizedisk();
+ return usage_resizedisk();
sector = strtoll(optarg, &p, 10);
if (sector < 1)
- usage_resizedisk();
+ return usage_resizedisk();
if (*p == '\0')
break;
if (*p == 's' || *p == 'S') {
if (*(p + 1) == '\0')
break;
else
- usage_resizedisk();
+ return usage_resizedisk();
}
if (*p == 'b' || *p == 'B') {
if (*(p + 1) == '\0') {
@@ -251,40 +245,23 @@ cmd_resizedisk(int argc, char *argv[])
sector = 0;
break;
} else
- usage_resizedisk();
+ return usage_resizedisk();
}
if (dehumanize_number(optarg, &human_num) < 0)
- usage_resizedisk();
+ return usage_resizedisk();
size = human_num;
sector = 0;
break;
default:
- usage_resizedisk();
+ return usage_resizedisk();
}
}
- if (argc == optind)
- usage_resizedisk();
+ if (argc != optind)
+ return usage_resizedisk();
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- if (size % secsz != 0) {
- warnx("Size in bytes must be a multiple of sector "
- "size;");
- warnx("the sector size for %s is %d bytes.",
- device_name, secsz);
- continue;
- }
- if (size > 0)
- sector = size / secsz - 1;
-
- resizedisk(fd);
+ if ((sector = gpt_check(gpt, 0, size)) == -1)
+ return -1;
- gpt_close(fd);
- }
-
- return 0;
+ return resizedisk(gpt);
}
Index: src/sbin/gpt/type.c
diff -u src/sbin/gpt/type.c:1.7 src/sbin/gpt/type.c:1.8
--- src/sbin/gpt/type.c:1.7 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/type.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: type.c,v 1.7 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: type.c,v 1.8 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,6 +47,7 @@ __RCSID("$NetBSD: type.c,v 1.7 2015/11/2
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static int all;
static gpt_uuid_t type, newtype;
@@ -54,12 +55,12 @@ static off_t block, size;
static unsigned int entry;
static uint8_t *label;
-const char typemsg1[] = "type -a -T newtype device ...";
+const char typemsg1[] = "type -a -T newtype";
const char typemsg2[] = "type [-b blocknr] [-i index] [-L label] "
"[-s sectors] [-t type]";
-const char typemsg3[] = " -T newtype device ...";
+const char typemsg3[] = " -T newtype";
-__dead static void
+static int
usage_type(void)
{
@@ -68,42 +69,21 @@ usage_type(void)
" %s %s\n"
" %*s %s\n", getprogname(), typemsg1,
getprogname(), typemsg2, (int)strlen(getprogname()), "", typemsg3);
- exit(1);
+ return -1;
}
-static void
-chtype(int fd)
+static int
+chtype(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *m;
- struct gpt_hdr *hdr;
+ map_t m;
struct gpt_ent *ent;
unsigned int i;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
-
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
-
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
+ if (gpt_hdr(gpt) == NULL)
+ return -1;
/* Change type of all matching entries in the map. */
- for (m = map_first(); m != NULL; m = m->map_next) {
+ for (m = map_first(gpt); m != NULL; m = m->map_next) {
if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
continue;
if (entry > 0 && entry != m->map_index)
@@ -115,9 +95,7 @@ chtype(int fd)
i = m->map_index - 1;
- hdr = gpt->map_data;
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_primary(gpt, i);
if (label != NULL)
if (strcmp((char *)label,
@@ -131,37 +109,27 @@ chtype(int fd)
/* Change the primary entry. */
gpt_uuid_copy(ent->ent_type, newtype);
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
-
- hdr = tpg->map_data;
- ent = (void*)((char*)lbt->map_data + i *
- le32toh(hdr->hdr_entsz));
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
+
+ ent = gpt_ent_backup(gpt, i);
/* Change the secondary entry. */
gpt_uuid_copy(ent->ent_type, newtype);
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
- printf("partition %d type changed\n", m->map_index);
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
+
+ gpt_msg(gpt, "Partition %d type changed", m->map_index);
}
+ return 0;
}
int
-cmd_type(int argc, char *argv[])
+cmd_type(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
int64_t human_num;
/* Get the type options */
@@ -169,73 +137,63 @@ cmd_type(int argc, char *argv[])
switch(ch) {
case 'a':
if (all > 0)
- usage_type();
+ return usage_type();
all = 1;
break;
case 'b':
if (block > 0)
- usage_type();
+ return usage_type();
if (dehumanize_number(optarg, &human_num) < 0)
- usage_type();
+ return usage_type();
block = human_num;
if (block < 1)
- usage_type();
+ return usage_type();
break;
case 'i':
if (entry > 0)
- usage_type();
+ return usage_type();
entry = strtoul(optarg, &p, 10);
if (*p != 0 || entry < 1)
- usage_type();
+ return usage_type();
break;
case 'L':
if (label != NULL)
- usage_type();
+ return usage_type();
label = (uint8_t *)strdup(optarg);
break;
case 's':
if (size > 0)
- usage_type();
+ return usage_type();
size = strtoll(optarg, &p, 10);
if (*p != 0 || size < 1)
- usage_type();
+ return usage_type();
break;
case 't':
if (!gpt_uuid_is_nil(type))
- usage_type();
+ return usage_type();
if (gpt_uuid_parse(optarg, type) != 0)
- usage_type();
+ return usage_type();
break;
case 'T':
if (!gpt_uuid_is_nil(newtype))
- usage_type();
+ return usage_type();
if (gpt_uuid_parse(optarg, newtype) != 0)
- usage_type();
+ return usage_type();
break;
default:
- usage_type();
+ return usage_type();
}
}
if (!all ^
(block > 0 || entry > 0 || label != NULL || size > 0 ||
!gpt_uuid_is_nil(type)))
- usage_type();
+ return usage_type();
if (gpt_uuid_is_nil(newtype))
- usage_type();
-
- if (argc == optind)
- usage_type();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- chtype(fd);
+ return usage_type();
- gpt_close(fd);
- }
+ if (argc != optind)
+ return usage_type();
- return (0);
+ return chtype(gpt);
}
Index: src/sbin/gpt/gpt.8
diff -u src/sbin/gpt/gpt.8:1.38 src/sbin/gpt/gpt.8:1.39
--- src/sbin/gpt/gpt.8:1.38 Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/gpt.8 Tue Dec 1 04:05:33 2015
@@ -1,4 +1,4 @@
-.\" $NetBSD: gpt.8,v 1.38 2015/11/30 19:59:34 christos Exp $
+.\" $NetBSD: gpt.8,v 1.39 2015/12/01 09:05:33 christos Exp $
.\"
.\" Copyright (c) 2002 Marcel Moolenaar
.\" All rights reserved.
@@ -34,9 +34,8 @@
.Nd GUID partition table maintenance utility
.Sh SYNOPSIS
.Nm
-.Op Fl mnprqv
+.Op Fl nrqv
.Op Fl m Ar mediasize
-.Op Fl p Ar partitions
.Op Fl s Ar sectorsize
.Ar command
.Op Ar command_options
@@ -81,13 +80,6 @@ changed.
You need to use the
.Xr dkctl 8
command manually update the device's wedge configuration if you do that.
-.It Fl p Ar partitions
-Change the default number of partitions the GPT can
-accommodate.
-This is used whenever a new GPT is created.
-By default, the
-.Nm
-utility will create space for 128 partitions (or 32 sectors of 512 bytes).
.It Fl r
Open the device for reading only.
.Nm
@@ -244,7 +236,7 @@ option selects the partition by label.
If there are multiple partitions with the same label, it will use the
first one found.
.\" ==== create ====
-.It Nm Ic create Oo Fl fp Oc Ar device ...
+.It Nm Ic create Oo Fl fP Oc Oo Fl p Ar partitions Oc Ar device ...
The
.Ic create
command allows the user to create a new (empty) GPT.
@@ -258,11 +250,20 @@ option is specified, an existing MBR is
described by the MBR are lost.
.Pp
The
-.Fl p
+.Fl P
option tells
.Nm
to create only the primary table and not the backup table.
This option is only useful for debugging and should not be used otherwise.
+.Pp
+The
+.Fl p
+option changes the default number of partitions the GPT can
+accommodate.
+This is used whenever a new GPT is created.
+By default, the
+.Nm
+utility will create space for 128 partitions (or 32 sectors of 512 bytes).
.\" ==== destroy ====
.It Nm Ic destroy Oo Fl r Oc Ar device ...
The
@@ -340,7 +341,7 @@ The
option is used to specify the label in the command line.
The label is assumed to be encoded in UTF-8.
.\" ==== migrate ====
-.It Nm Ic migrate Oo Fl fs Oc Ar device ...
+.It Nm Ic migrate Oo Fl fs Oc Oo Fl p Ar partitions Oc Ar device ...
The
.Ic migrate
command allows the user to migrate an MBR-based disk partitioning into a
@@ -368,6 +369,15 @@ option isn't applicable to
partitions.
.Pp
The
+.Fl p
+option changes the default number of partitions the GPT can
+accommodate.
+This is used whenever a new GPT is created.
+By default, the
+.Nm
+utility will create space for 128 partitions (or 32 sectors of 512 bytes).
+.Pp
+The
.Ic migrate
command requires space at the beginning and the end of the device outside
any partitions to store the GPTs.
Index: src/sbin/gpt/gpt.c
diff -u src/sbin/gpt/gpt.c:1.48 src/sbin/gpt/gpt.c:1.49
--- src/sbin/gpt/gpt.c:1.48 Mon Nov 30 21:03:55 2015
+++ src/sbin/gpt/gpt.c Tue Dec 1 04:05:33 2015
@@ -35,7 +35,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: gpt.c,v 1.48 2015/12/01 02:03:55 christos Exp $");
+__RCSID("$NetBSD: gpt.c,v 1.49 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/param.h>
@@ -58,19 +58,7 @@ __RCSID("$NetBSD: gpt.c,v 1.48 2015/12/0
#include "map.h"
#include "gpt.h"
-
-char device_path[MAXPATHLEN];
-const char *device_arg;
-const char *device_name;
-
-off_t mediasz;
-
-u_int parts;
-u_int secsz;
-
-int readonly, verbose, quiet, nosync;
-
-static int modified;
+#include "gpt_private.h"
static uint32_t crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
@@ -243,61 +231,61 @@ utf8_to_utf16(const uint8_t *s8, uint16_
} while (c != 0);
}
-void*
-gpt_read(int fd, off_t lba, size_t count)
+void *
+gpt_read(gpt_t gpt, off_t lba, size_t count)
{
off_t ofs;
void *buf;
- count *= secsz;
+ count *= gpt->secsz;
buf = malloc(count);
if (buf == NULL)
- return (NULL);
+ return NULL;
- ofs = lba * secsz;
- if (lseek(fd, ofs, SEEK_SET) == ofs &&
- read(fd, buf, count) == (ssize_t)count)
- return (buf);
+ ofs = lba * gpt->secsz;
+ if (lseek(gpt->fd, ofs, SEEK_SET) == ofs &&
+ read(gpt->fd, buf, count) == (ssize_t)count)
+ return buf;
free(buf);
- return (NULL);
+ return NULL;
}
int
-gpt_write(int fd, map_t *map)
+gpt_write(gpt_t gpt, map_t map)
{
off_t ofs;
size_t count;
- count = map->map_size * secsz;
- ofs = map->map_start * secsz;
- if (lseek(fd, ofs, SEEK_SET) != ofs ||
- write(fd, map->map_data, count) != (ssize_t)count)
+ count = map->map_size * gpt->secsz;
+ ofs = map->map_start * gpt->secsz;
+ if (lseek(gpt->fd, ofs, SEEK_SET) != ofs ||
+ write(gpt->fd, map->map_data, count) != (ssize_t)count)
return -1;
- modified = 1;
+ gpt->flags |= GPT_MODIFIED;
return 0;
}
static int
-gpt_mbr(int fd, off_t lba)
+gpt_mbr(gpt_t gpt, off_t lba)
{
struct mbr *mbr;
- map_t *m, *p;
+ map_t m, p;
off_t size, start;
unsigned int i, pmbr;
- mbr = gpt_read(fd, lba, 1);
+ mbr = gpt_read(gpt, lba, 1);
if (mbr == NULL) {
- if (!quiet)
- warn("%s: read failed", device_name);
- return (-1);
+ gpt_warn(gpt, "Read failed");
+ return -1;
}
if (mbr->mbr_sig != htole16(MBR_SIG)) {
- if (verbose)
- gpt_msg("MBR not found at sector %ju", (uintmax_t)lba);
+ if (gpt->verbose)
+ gpt_msg(gpt,
+ "MBR not found at sector %ju", (uintmax_t)lba);
free(mbr);
- return (0);
+ return 0;
}
/*
@@ -315,23 +303,23 @@ gpt_mbr(int fd, off_t lba)
break;
}
if (pmbr && i == 4 && lba == 0) {
- if (pmbr != 1 && !quiet)
- warnx("%s: Suspicious PMBR at sector %ju",
- device_name, (uintmax_t)lba);
- else if (verbose > 1)
- gpt_msg("PMBR at sector %ju", (uintmax_t)lba);
- p = map_add(lba, 1LL, MAP_TYPE_PMBR, mbr);
- return ((p == NULL) ? -1 : 0);
- }
- if (pmbr && !quiet)
- warnx("%s: Suspicious MBR at sector %ju", device_name,
- (uintmax_t)lba);
- else if (verbose > 1)
- gpt_msg("MBR at sector %ju", (uintmax_t)lba);
+ if (pmbr != 1)
+ gpt_warnx(gpt, "Suspicious PMBR at sector %ju",
+ (uintmax_t)lba);
+ else if (gpt->verbose > 1)
+ gpt_msg(gpt, "PMBR at sector %ju", (uintmax_t)lba);
+ p = map_add(gpt, lba, 1LL, MAP_TYPE_PMBR, mbr);
+ goto out;
+ }
+ if (pmbr)
+ gpt_warnx(gpt, "Suspicious MBR at sector %ju", (uintmax_t)lba);
+ else if (gpt->verbose > 1)
+ gpt_msg(gpt, "MBR at sector %ju", (uintmax_t)lba);
- p = map_add(lba, 1LL, MAP_TYPE_MBR, mbr);
+ p = map_add(gpt, lba, 1LL, MAP_TYPE_MBR, mbr);
if (p == NULL)
- return (-1);
+ goto out;
+
for (i = 0; i < 4; i++) {
if (mbr->mbr_part[i].part_typ == MBR_PTYPE_UNUSED ||
mbr->mbr_part[i].part_typ == MBR_PTYPE_PMBR)
@@ -341,44 +329,50 @@ gpt_mbr(int fd, off_t lba)
size = le16toh(mbr->mbr_part[i].part_size_hi);
size = (size << 16) + le16toh(mbr->mbr_part[i].part_size_lo);
if (start == 0 && size == 0) {
- warnx("%s: Malformed MBR at sector %llu", device_name,
- (long long)lba);
+ gpt_warnx(gpt, "Malformed MBR at sector %ju",
+ (uintmax_t)lba);
continue;
}
/* start is relative to the offset of the MBR itself. */
start += lba;
- if (verbose > 2)
- gpt_msg("MBR part: type=%d, start=%ju, size=%ju",
+ if (gpt->verbose > 2)
+ gpt_msg(gpt, "MBR part: type=%d, start=%ju, size=%ju",
mbr->mbr_part[i].part_typ,
(uintmax_t)start, (uintmax_t)size);
if (mbr->mbr_part[i].part_typ != MBR_PTYPE_EXT_LBA) {
- m = map_add(start, size, MAP_TYPE_MBR_PART, p);
+ m = map_add(gpt, start, size, MAP_TYPE_MBR_PART, p);
if (m == NULL)
- return (-1);
+ return -1;
m->map_index = i + 1;
} else {
- if (gpt_mbr(fd, start) == -1)
- return (-1);
+ if (gpt_mbr(gpt, start) == -1)
+ return -1;
}
}
- return (0);
+ return 0;
+out:
+ if (p == NULL) {
+ free(mbr);
+ return -1;
+ }
+ return 0;
}
int
-gpt_gpt(int fd, off_t lba, int found)
+gpt_gpt(gpt_t gpt, off_t lba, int found)
{
off_t size;
struct gpt_ent *ent;
struct gpt_hdr *hdr;
char *p;
- map_t *m;
+ map_t m;
size_t blocks, tblsz;
unsigned int i;
uint32_t crc;
- hdr = gpt_read(fd, lba, 1);
+ hdr = gpt_read(gpt, lba, 1);
if (hdr == NULL)
- return (-1);
+ return -1;
if (memcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)))
goto fail_hdr;
@@ -386,46 +380,45 @@ gpt_gpt(int fd, off_t lba, int found)
crc = le32toh(hdr->hdr_crc_self);
hdr->hdr_crc_self = 0;
if (crc32(hdr, le32toh(hdr->hdr_size)) != crc) {
- if (verbose)
- warnx("%s: Bad CRC in GPT header at sector %llu",
- device_name, (long long)lba);
+ if (gpt->verbose)
+ gpt_msg(gpt, "Bad CRC in GPT header at sector %ju",
+ (uintmax_t)lba);
goto fail_hdr;
}
tblsz = le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz);
- blocks = tblsz / secsz + ((tblsz % secsz) ? 1 : 0);
+ blocks = tblsz / gpt->secsz + ((tblsz % gpt->secsz) ? 1 : 0);
/* Use generic pointer to deal with hdr->hdr_entsz != sizeof(*ent). */
- p = gpt_read(fd, le64toh(hdr->hdr_lba_table), blocks);
+ p = gpt_read(gpt, le64toh(hdr->hdr_lba_table), blocks);
if (p == NULL) {
if (found) {
- if (verbose)
- warn("%s: Cannot read LBA table at sector %llu",
- device_name, (unsigned long long)
- le64toh(hdr->hdr_lba_table));
- return (-1);
+ if (gpt->verbose)
+ gpt_msg(gpt,
+ "Cannot read LBA table at sector %ju",
+ (uintmax_t)le64toh(hdr->hdr_lba_table));
+ return -1;
}
goto fail_hdr;
}
if (crc32(p, tblsz) != le32toh(hdr->hdr_crc_table)) {
- if (verbose)
- warnx("%s: Bad CRC in GPT table at sector %llu",
- device_name,
- (long long)le64toh(hdr->hdr_lba_table));
+ if (gpt->verbose)
+ gpt_msg(gpt, "Bad CRC in GPT table at sector %ju",
+ (uintmax_t)le64toh(hdr->hdr_lba_table));
goto fail_ent;
}
- if (verbose > 1)
- warnx("%s: %s GPT at sector %llu", device_name,
- (lba == 1) ? "Pri" : "Sec", (long long)lba);
+ if (gpt->verbose > 1)
+ gpt_msg(gpt, "%s GPT at sector %ju",
+ (lba == 1) ? "Pri" : "Sec", (uintmax_t)lba);
- m = map_add(lba, 1, (lba == 1)
+ m = map_add(gpt, lba, 1, (lba == 1)
? MAP_TYPE_PRI_GPT_HDR : MAP_TYPE_SEC_GPT_HDR, hdr);
if (m == NULL)
return (-1);
- m = map_add(le64toh(hdr->hdr_lba_table), blocks, (lba == 1)
+ m = map_add(gpt, le64toh(hdr->hdr_lba_table), blocks, (lba == 1)
? MAP_TYPE_PRI_GPT_TBL : MAP_TYPE_SEC_GPT_TBL, p);
if (m == NULL)
return (-1);
@@ -440,16 +433,16 @@ gpt_gpt(int fd, off_t lba, int found)
size = le64toh(ent->ent_lba_end) - le64toh(ent->ent_lba_start) +
1LL;
- if (verbose > 2) {
+ if (gpt->verbose > 2) {
char buf[128];
gpt_uuid_snprintf(buf, sizeof(buf), "%s",
ent->ent_type);
- warnx("%s: GPT partition: type=%s, start=%llu, "
- "size=%llu", device_name, buf,
- (long long)le64toh(ent->ent_lba_start),
- (long long)size);
+ gpt_msg(gpt, "GPT partition: type=%s, start=%ju, "
+ "size=%ju", buf,
+ (uintmax_t)le64toh(ent->ent_lba_start),
+ (uintmax_t)size);
}
- m = map_add(le64toh(ent->ent_lba_start), size,
+ m = map_add(gpt, le64toh(ent->ent_lba_start), size,
MAP_TYPE_GPT_PART, ent);
if (m == NULL)
return (-1);
@@ -465,72 +458,73 @@ gpt_gpt(int fd, off_t lba, int found)
return (0);
}
-int
-gpt_open(const char *dev, int flags)
+gpt_t
+gpt_open(const char *dev, int flags, int verbose, off_t mediasz, u_int secsz)
{
- struct stat sb;
- int fd, mode, found;
+ int mode, found;
off_t devsz;
+ gpt_t gpt;
- mode = readonly ? O_RDONLY : O_RDWR|O_EXCL;
- device_arg = device_name = dev;
- fd = opendisk(dev, mode, device_path, sizeof(device_path), 0);
- if (fd == -1) {
- if (!quiet)
- warn("Cannot open `%s'", device_name);
- return -1;
+ if ((gpt = calloc(1, sizeof(*gpt))) == NULL) {
+ if (!(gpt->flags & GPT_QUIET))
+ warn("Cannot allocate `%s'", dev);
+ return NULL;
+ }
+ gpt->flags = flags;
+ gpt->verbose = verbose;
+ gpt->mediasz = mediasz;
+ gpt->secsz = secsz;
+
+ mode = (gpt->flags & GPT_READONLY) ? O_RDONLY : O_RDWR|O_EXCL;
+
+ gpt->fd = opendisk(dev, mode, gpt->device_name,
+ sizeof(gpt->device_name), 0);
+ if (gpt->fd == -1) {
+ strlcpy(gpt->device_name, dev, sizeof(gpt->device_name));
+ gpt_warn(gpt, "Cannot open");
+ goto close;
}
- device_name = device_path;
- if (fstat(fd, &sb) == -1) {
- if (!quiet)
- warn("Cannot stat `%s'", device_name);
+ if (fstat(gpt->fd, &gpt->sb) == -1) {
+ gpt_warn(gpt, "Cannot stat");
goto close;
}
- if ((sb.st_mode & S_IFMT) != S_IFREG) {
- if (secsz == 0) {
+ if ((gpt->sb.st_mode & S_IFMT) != S_IFREG) {
+ if (gpt->secsz == 0) {
#ifdef DIOCGSECTORSIZE
- if (ioctl(fd, DIOCGSECTORSIZE, &secsz) == -1) {
- if (!quiet)
- warn("Cannot get sector size for `%s'",
- device_name);
+ if (ioctl(gpt->fd, DIOCGSECTORSIZE, &gpt->secsz) == -1) {
+ gpt_warn(gpt, "Cannot get sector size");
goto close;
}
#endif
- if (secsz == 0) {
- if (!quiet)
- warnx("Sector size for `%s' can't be 0",
- device_name);
+ if (gpt->secsz == 0) {
+ gpt_warnx(gpt, "Sector size can't be 0");
goto close;
}
}
- if (mediasz == 0) {
+ if (gpt->mediasz == 0) {
#ifdef DIOCGMEDIASIZE
- if (ioctl(fd, DIOCGMEDIASIZE, &mediasz) == -1) {
- if (!quiet)
- warn("Cannot get media size for `%s'",
- device_name);
+ if (ioctl(gpt->fd, DIOCGMEDIASIZE, &gpt->mediasz) == -1) {
+ gpt_warn(gpt, "Cannot get media size");
goto close;
}
#endif
- if (mediasz == 0) {
- if (!quiet)
- warnx("Media size for `%s' can't be 0",
- device_name);
+ if (gpt->mediasz == 0) {
+ gpt_warnx(gpt, "Media size can't be 0");
goto close;
}
}
} else {
- if (secsz == 0)
- secsz = 512; /* Fixed size for files. */
- if (mediasz == 0) {
- if (sb.st_size % secsz) {
+ if (gpt->secsz == 0)
+ gpt->secsz = 512; /* Fixed size for files. */
+ if (gpt->mediasz == 0) {
+ if (gpt->sb.st_size % gpt->secsz) {
errno = EINVAL;
goto close;
}
- mediasz = sb.st_size;
+ gpt->mediasz = gpt->sb.st_size;
}
}
@@ -540,68 +534,217 @@ gpt_open(const char *dev, int flags)
* user data. Let's catch this extreme border case here so that
* we don't have to worry about it later.
*/
- devsz = mediasz / secsz;
+ devsz = gpt->mediasz / gpt->secsz;
if (devsz < 6) {
- if (!quiet)
- warnx("Need 6 sectors on '%s' we have %ju",
- device_name, (uintmax_t)devsz);
+ gpt_warnx(gpt, "Need 6 sectorso, we have %ju",
+ (uintmax_t)devsz);
goto close;
}
- if (verbose) {
- gpt_msg("mediasize=%ju; sectorsize=%u; blocks=%ju",
- (uintmax_t)mediasz, secsz, (uintmax_t)devsz);
+ if (gpt->verbose) {
+ gpt_msg(gpt, "mediasize=%ju; sectorsize=%u; blocks=%ju",
+ (uintmax_t)gpt->mediasz, gpt->secsz, (uintmax_t)devsz);
}
- map_init(devsz);
+ map_init(gpt, devsz);
- if (gpt_mbr(fd, 0LL) == -1)
+ if (gpt_mbr(gpt, 0LL) == -1)
goto close;
- if ((found = gpt_gpt(fd, 1LL, 1)) == -1)
+ if ((found = gpt_gpt(gpt, 1LL, 1)) == -1)
goto close;
- if (gpt_gpt(fd, devsz - 1LL, found) == -1)
+ if (gpt_gpt(gpt, devsz - 1LL, found) == -1)
goto close;
- return (fd);
+ return gpt;
close:
- close(fd);
- return (-1);
+ if (gpt->fd != -1)
+ close(gpt->fd);
+ free(gpt);
+ return NULL;
}
void
-gpt_close(int fd)
+gpt_close(gpt_t gpt)
{
- if (!modified)
+ if (!(gpt->flags & GPT_MODIFIED))
goto out;
- if (!nosync) {
+ if (!(gpt->flags & GPT_NOSYNC)) {
#ifdef DIOCMWEDGES
int bits;
- if (ioctl(fd, DIOCMWEDGES, &bits) == -1)
- warn("Can't update wedge information");
+ if (ioctl(gpt->fd, DIOCMWEDGES, &bits) == -1)
+ gpt_warn(gpt, "Can't update wedge information");
else
goto out;
#endif
}
- gpt_msg("You need to run \"dkctl %s makewedges\""
- " for the changes to take effect\n", device_name);
+ gpt_msg(gpt, "You need to run \"dkctl %s makewedges\""
+ " for the changes to take effect\n", gpt->device_name);
out:
- close(fd);
+ close(gpt->fd);
}
void
-gpt_msg(const char *fmt, ...)
+gpt_warnx(gpt_t gpt, const char *fmt, ...)
{
va_list ap;
- if (quiet)
+ if (gpt->flags & GPT_QUIET)
return;
- printf("%s: ", device_name);
+ fprintf(stderr, "%s: %s: ", getprogname(), gpt->device_name);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+void
+gpt_warn(gpt_t gpt, const char *fmt, ...)
+{
+ va_list ap;
+ int e = errno;
+
+ if (gpt->flags & GPT_QUIET)
+ return;
+ fprintf(stderr, "%s: %s: ", getprogname(), gpt->device_name);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, " (%s)\n", strerror(e));
+ errno = e;
+}
+
+void
+gpt_msg(gpt_t gpt, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (gpt->flags & GPT_QUIET)
+ return;
+ printf("%s: ", gpt->device_name);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\n");
}
+
+struct gpt_hdr *
+gpt_hdr(gpt_t gpt)
+{
+ gpt->gpt = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+ if (gpt->gpt == NULL) {
+ gpt_warnx(gpt, "No primary GPT header; run create or recover");
+ return NULL;
+ }
+
+ gpt->tpg = map_find(gpt, MAP_TYPE_SEC_GPT_HDR);
+ if (gpt->tpg == NULL) {
+ gpt_warnx(gpt, "No secondary GPT header; run recover");
+ return NULL;
+ }
+
+ gpt->tbl = map_find(gpt, MAP_TYPE_PRI_GPT_TBL);
+ gpt->lbt = map_find(gpt, MAP_TYPE_SEC_GPT_TBL);
+ if (gpt->tbl == NULL || gpt->lbt == NULL) {
+ gpt_warnx(gpt, "Corrupt maps, run recover");
+ return NULL;
+ }
+
+ return gpt->gpt->map_data;
+}
+
+int
+gpt_write_crc(gpt_t gpt, map_t map, map_t tbl)
+{
+ struct gpt_hdr *hdr = map->map_data;
+
+ hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
+ le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
+ hdr->hdr_crc_self = 0;
+ hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+
+ if (gpt_write(gpt, map) == -1) {
+ gpt_warn(gpt, "Error writing crc map");
+ return -1;
+ }
+
+ if (gpt_write(gpt, tbl) == -1) {
+ gpt_warn(gpt, "Error writing crc table");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+gpt_write_primary(gpt_t gpt)
+{
+ return gpt_write_crc(gpt, gpt->gpt, gpt->tbl);
+}
+
+
+int
+gpt_write_backup(gpt_t gpt)
+{
+ return gpt_write_crc(gpt, gpt->tpg, gpt->lbt);
+}
+
+void
+gpt_create_pmbr_part(struct mbr_part *part, off_t last)
+{
+ part->part_shd = 0x00;
+ part->part_ssect = 0x02;
+ part->part_scyl = 0x00;
+ part->part_typ = MBR_PTYPE_PMBR;
+ part->part_ehd = 0xfe;
+ part->part_esect = 0xff;
+ part->part_ecyl = 0xff;
+ part->part_start_lo = htole16(1);
+ if (last > 0xffffffff) {
+ part->part_size_lo = htole16(0xffff);
+ part->part_size_hi = htole16(0xffff);
+ } else {
+ part->part_size_lo = htole16(last);
+ part->part_size_hi = htole16(last >> 16);
+ }
+}
+
+off_t
+gpt_check(gpt_t gpt, off_t alignment, off_t size)
+{
+ if (alignment % gpt->secsz != 0) {
+ gpt_warnx(gpt, "Alignment (%#jx) must be a multiple of "
+ "sector size (%#x)", (uintmax_t)alignment, gpt->secsz);
+ return -1;
+ }
+
+ if (size % gpt->secsz != 0) {
+ gpt_warnx(gpt, "Size (%#jx) must be a multiple of "
+ "sector size (%#x)", (uintmax_t)size, gpt->secsz);
+ return -1;
+ }
+ if (size > 0)
+ return size / gpt->secsz;
+ return 0;
+}
+struct gpt_ent *
+gpt_ent(map_t map, map_t tbl, unsigned int i)
+{
+ struct gpt_hdr *hdr = map->map_data;
+ return (void *)((char *)tbl->map_data + i * le32toh(hdr->hdr_entsz));
+}
+
+struct gpt_ent *
+gpt_ent_primary(gpt_t gpt, unsigned int i)
+{
+ return gpt_ent(gpt->gpt, gpt->tbl, i);
+}
+
+struct gpt_ent *
+gpt_ent_backup(gpt_t gpt, unsigned int i)
+{
+ return gpt_ent(gpt->tpg, gpt->lbt, i);
+}
Index: src/sbin/gpt/gpt.h
diff -u src/sbin/gpt/gpt.h:1.22 src/sbin/gpt/gpt.h:1.23
--- src/sbin/gpt/gpt.h:1.22 Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/gpt.h Tue Dec 1 04:05:33 2015
@@ -60,40 +60,52 @@ struct mbr {
#define MBR_SIG 0xAA55
};
-extern const char *device_arg;
-extern const char *device_name;
-extern off_t mediasz;
-extern u_int parts;
-extern u_int secsz;
-extern int readonly, verbose, quiet, nosync;
+typedef struct gpt *gpt_t;
+typedef struct map *map_t;
uint32_t crc32(const void *, size_t);
-void gpt_close(int);
-int gpt_gpt(int, off_t, int);
-int gpt_open(const char *, int);
-void* gpt_read(int, off_t, size_t);
-int gpt_write(int, map_t *);
-void gpt_msg(const char *, ...) __printflike(1, 2);
+void gpt_close(gpt_t);
+int gpt_gpt(gpt_t, off_t, int);
+gpt_t gpt_open(const char *, int, int, off_t, u_int);
+void* gpt_read(gpt_t, off_t, size_t);
+int gpt_write(gpt_t, map_t);
+int gpt_write_crc(gpt_t, map_t, map_t);
+int gpt_write_primary(gpt_t);
+int gpt_write_backup(gpt_t);
+struct gpt_hdr *gpt_hdr(gpt_t);
+void gpt_msg(gpt_t, const char *, ...) __printflike(2, 3);
+void gpt_warn(gpt_t, const char *, ...) __printflike(2, 3);
+void gpt_warnx(gpt_t, const char *, ...) __printflike(2, 3);
+void gpt_create_pmbr_part(struct mbr_part *, off_t);
+off_t gpt_check(gpt_t, off_t, off_t);
+struct gpt_ent *gpt_ent(map_t, map_t, unsigned int);
+struct gpt_ent *gpt_ent_primary(gpt_t, unsigned int);
+struct gpt_ent *gpt_ent_backup(gpt_t, unsigned int);
uint8_t *utf16_to_utf8(uint16_t *);
void utf8_to_utf16(const uint8_t *, uint16_t *, size_t);
-int cmd_add(int, char *[]);
-int cmd_backup(int, char *[]);
-int cmd_biosboot(int, char *[]);
-int cmd_create(int, char *[]);
-int cmd_destroy(int, char *[]);
-int cmd_header(int, char *[]);
-int cmd_label(int, char *[]);
-int cmd_migrate(int, char *[]);
-int cmd_recover(int, char *[]);
-int cmd_remove(int, char *[]);
-int cmd_resize(int, char *[]);
-int cmd_resizedisk(int, char *[]);
-int cmd_restore(int, char *[]);
-int cmd_set(int, char *[]);
-int cmd_show(int, char *[]);
-int cmd_type(int, char *[]);
-int cmd_unset(int, char *[]);
+int cmd_add(gpt_t, int, char *[]);
+int cmd_backup(gpt_t, int, char *[]);
+int cmd_biosboot(gpt_t, int, char *[]);
+int cmd_create(gpt_t, int, char *[]);
+int cmd_destroy(gpt_t, int, char *[]);
+int cmd_header(gpt_t, int, char *[]);
+int cmd_label(gpt_t, int, char *[]);
+int cmd_migrate(gpt_t, int, char *[]);
+int cmd_recover(gpt_t, int, char *[]);
+int cmd_remove(gpt_t, int, char *[]);
+int cmd_resize(gpt_t, int, char *[]);
+int cmd_resizedisk(gpt_t, int, char *[]);
+int cmd_restore(gpt_t, int, char *[]);
+int cmd_set(gpt_t, int, char *[]);
+int cmd_show(gpt_t, int, char *[]);
+int cmd_type(gpt_t, int, char *[]);
+int cmd_unset(gpt_t, int, char *[]);
+
+#define GPT_READONLY 1
+#define GPT_MODIFIED 2
+#define GPT_QUIET 4
+#define GPT_NOSYNC 8
#endif /* _GPT_H_ */
Index: src/sbin/gpt/migrate.c
diff -u src/sbin/gpt/migrate.c:1.22 src/sbin/gpt/migrate.c:1.23
--- src/sbin/gpt/migrate.c:1.22 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/migrate.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/migrate.c,v 1.16 2005/09/01 02:42:52 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: migrate.c,v 1.22 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: migrate.c,v 1.23 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -55,6 +55,7 @@ __RCSID("$NetBSD: migrate.c,v 1.22 2015/
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
/*
* Allow compilation on platforms that do not have a BSD label.
@@ -77,33 +78,37 @@ __RCSID("$NetBSD: migrate.c,v 1.22 2015/
static int force;
static int slice;
+static u_int parts;
-const char migratemsg[] = "migrate [-fs] device ...";
+const char migratemsg[] = "migrate [-fs] [-p <partitions>]";
-__dead static void
+static int
usage_migrate(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), migratemsg);
- exit(1);
+ return -1;
}
-static struct gpt_ent*
-migrate_disklabel(int fd, off_t start, struct gpt_ent *ent)
+static struct gpt_ent *
+migrate_disklabel(gpt_t gpt, off_t start, struct gpt_ent *ent)
{
char *buf;
struct disklabel *dl;
off_t ofs, rawofs;
int i;
- buf = gpt_read(fd, start + LABELSECTOR, 1);
+ buf = gpt_read(gpt, start + LABELSECTOR, 1);
+ if (buf == NULL) {
+ gpt_warn(gpt, "Error reading label");
+ return NULL;
+ }
dl = (void*)(buf + LABELOFFSET);
if (le32toh(dl->d_magic) != DISKMAGIC ||
le32toh(dl->d_magic2) != DISKMAGIC) {
- warnx("%s: warning: FreeBSD slice without disklabel",
- device_name);
+ gpt_warnx(gpt, "FreeBSD slice without disklabel");
free(buf);
return (ent);
}
@@ -118,7 +123,7 @@ migrate_disklabel(int fd, off_t start, s
if (ofs < rawofs)
rawofs = 0;
}
- rawofs /= secsz;
+ rawofs /= gpt->secsz;
for (i = 0; i < le16toh(dl->d_npartitions); i++) {
switch (dl->d_partitions[i].p_fstype) {
@@ -145,13 +150,13 @@ migrate_disklabel(int fd, off_t start, s
break;
}
default:
- warnx("%s: warning: unknown FreeBSD partition (%d)",
- device_name, dl->d_partitions[i].p_fstype);
+ gpt_warnx(gpt, "Unknown FreeBSD partition (%d)",
+ dl->d_partitions[i].p_fstype);
continue;
}
ofs = (le32toh(dl->d_partitions[i].p_offset) *
- le32toh(dl->d_secsize)) / secsz;
+ le32toh(dl->d_secsize)) / gpt->secsz;
ofs = (ofs > 0) ? ofs - rawofs : 0;
ent->ent_lba_start = htole64(start + ofs);
ent->ent_lba_end = htole64(start + ofs +
@@ -160,26 +165,29 @@ migrate_disklabel(int fd, off_t start, s
}
free(buf);
- return (ent);
+ return ent;
}
static struct gpt_ent*
-migrate_netbsd_disklabel(int fd, off_t start, struct gpt_ent *ent)
+migrate_netbsd_disklabel(gpt_t gpt, off_t start, struct gpt_ent *ent)
{
char *buf;
struct disklabel *dl;
off_t ofs, rawofs;
int i;
- buf = gpt_read(fd, start + LABELSECTOR, 1);
+ buf = gpt_read(gpt, start + LABELSECTOR, 1);
+ if (buf == NULL) {
+ gpt_warn(gpt, "Error reading label");
+ return NULL;
+ }
dl = (void*)(buf + LABELOFFSET);
if (le32toh(dl->d_magic) != DISKMAGIC ||
le32toh(dl->d_magic2) != DISKMAGIC) {
- warnx("%s: warning: NetBSD slice without disklabel",
- device_name);
+ gpt_warnx(gpt, "NetBSD slice without disklabel");
free(buf);
- return (ent);
+ return ent;
}
rawofs = le32toh(dl->d_partitions[RAW_PART].p_offset) *
@@ -192,7 +200,7 @@ migrate_netbsd_disklabel(int fd, off_t s
if (ofs < rawofs)
rawofs = 0;
}
- rawofs /= secsz;
+ rawofs /= gpt->secsz;
for (i = 0; i < le16toh(dl->d_npartitions); i++) {
switch (dl->d_partitions[i].p_fstype) {
@@ -229,13 +237,13 @@ migrate_netbsd_disklabel(int fd, off_t s
break;
}
default:
- warnx("%s: warning: unknown NetBSD partition (%d)",
- device_name, dl->d_partitions[i].p_fstype);
+ gpt_warnx(gpt, "Unknown NetBSD partition (%d)",
+ dl->d_partitions[i].p_fstype);
continue;
}
ofs = (le32toh(dl->d_partitions[i].p_offset) *
- le32toh(dl->d_secsize)) / secsz;
+ le32toh(dl->d_secsize)) / gpt->secsz;
ofs = (ofs > 0) ? ofs - rawofs : 0;
ent->ent_lba_start = htole64(ofs);
ent->ent_lba_end = htole64(ofs +
@@ -244,49 +252,48 @@ migrate_netbsd_disklabel(int fd, off_t s
}
free(buf);
- return (ent);
+ return ent;
}
-static void
-migrate(int fd)
+static int
+migrate(gpt_t gpt)
{
off_t blocks, last;
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *map;
+ map_t map;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
struct mbr *mbr;
uint32_t start, size;
unsigned int i;
- last = mediasz / secsz - 1LL;
+ last = gpt->mediasz / gpt->secsz - 1LL;
- map = map_find(MAP_TYPE_MBR);
+ map = map_find(gpt, MAP_TYPE_MBR);
if (map == NULL || map->map_start != 0) {
- warnx("%s: error: no partitions to convert", device_name);
- return;
+ gpt_warnx(gpt, "No partitions to convert");
+ return -1;
}
mbr = map->map_data;
- if (map_find(MAP_TYPE_PRI_GPT_HDR) != NULL ||
- map_find(MAP_TYPE_SEC_GPT_HDR) != NULL) {
- warnx("%s: error: device already contains a GPT", device_name);
- return;
+ if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL ||
+ map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) {
+ gpt_warnx(gpt, "Device already contains a GPT");
+ return -1;
}
/* Get the amount of free space after the MBR */
- blocks = map_free(1LL, 0LL);
+ blocks = map_free(gpt, 1LL, 0LL);
if (blocks == 0LL) {
- warnx("%s: error: no room for the GPT header", device_name);
- return;
+ gpt_warnx(gpt, "No room for the GPT header");
+ return -1;
}
/* Don't create more than parts entries. */
- if ((uint64_t)(blocks - 1) * secsz > parts * sizeof(struct gpt_ent)) {
- blocks = (parts * sizeof(struct gpt_ent)) / secsz;
- if ((parts * sizeof(struct gpt_ent)) % secsz)
+ if ((uint64_t)(blocks - 1) * gpt->secsz >
+ parts * sizeof(struct gpt_ent)) {
+ blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz;
+ if ((parts * sizeof(struct gpt_ent)) % gpt->secsz)
blocks++;
blocks++; /* Don't forget the header itself */
}
@@ -299,50 +306,53 @@ migrate(int fd)
* Get the amount of free space at the end of the device and
* calculate the size for the GPT structures.
*/
- map = map_last();
+ map = map_last(gpt);
if (map->map_type != MAP_TYPE_UNUSED) {
- warnx("%s: error: no room for the backup header", device_name);
- return;
+ gpt_warnx(gpt, "No room for the backup header");
+ return -1;
}
if (map->map_size < blocks)
blocks = map->map_size;
if (blocks == 1LL) {
- warnx("%s: error: no room for the GPT table", device_name);
- return;
+ gpt_warnx(gpt, "No room for the GPT table");
+ return -1;
}
blocks--; /* Number of blocks in the GPT table. */
- gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR, calloc(1, secsz));
- tbl = map_add(2LL, blocks, MAP_TYPE_PRI_GPT_TBL,
- calloc(blocks, secsz));
- if (gpt == NULL || tbl == NULL)
- return;
-
- lbt = map_add(last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,
- tbl->map_data);
- tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR, calloc(1, secsz));
+ gpt->gpt = map_add(gpt, 1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
+ calloc(1, gpt->secsz));
+ gpt->tbl = map_add(gpt, 2LL, blocks, MAP_TYPE_PRI_GPT_TBL,
+ calloc(blocks, gpt->secsz));
+ if (gpt->gpt == NULL || gpt->tbl == NULL)
+ return -1;
+
+ gpt->lbt = map_add(gpt, last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,
+ gpt->tbl->map_data);
+ gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR,
+ calloc(1, gpt->secsz));
- hdr = gpt->map_data;
+ hdr = gpt->gpt->map_data;
memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
hdr->hdr_revision = htole32(GPT_HDR_REVISION);
+
/*
* XXX struct gpt_hdr is not a multiple of 8 bytes in size and thus
* contains padding we must not include in the size.
*/
hdr->hdr_size = htole32(GPT_HDR_SIZE);
- hdr->hdr_lba_self = htole64(gpt->map_start);
- hdr->hdr_lba_alt = htole64(tpg->map_start);
- hdr->hdr_lba_start = htole64(tbl->map_start + blocks);
- hdr->hdr_lba_end = htole64(lbt->map_start - 1LL);
+ hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
+ hdr->hdr_lba_alt = htole64(gpt->tpg->map_start);
+ hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks);
+ hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1LL);
gpt_uuid_generate(hdr->hdr_guid);
- hdr->hdr_lba_table = htole64(tbl->map_start);
- hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent));
+ hdr->hdr_lba_table = htole64(gpt->tbl->map_start);
+ hdr->hdr_entries = htole32((blocks * gpt->secsz) / sizeof(struct gpt_ent));
if (le32toh(hdr->hdr_entries) > parts)
hdr->hdr_entries = htole32(parts);
hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));
- ent = tbl->map_data;
+ ent = gpt->tbl->map_data;
for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
gpt_uuid_generate(ent[i].ent_guid);
}
@@ -366,11 +376,11 @@ migrate(int fd)
ent->ent_lba_end = htole64(start + size - 1LL);
ent++;
} else
- ent = migrate_disklabel(fd, start, ent);
+ ent = migrate_disklabel(gpt, start, ent);
break;
}
case MBR_PTYPE_NETBSD:
- ent = migrate_netbsd_disklabel(fd, start, ent);
+ ent = migrate_netbsd_disklabel(gpt, start, ent);
break;
case MBR_PTYPE_EFI: {
gpt_uuid_create(GPT_TYPE_EFI,
@@ -383,90 +393,66 @@ migrate(int fd)
}
default:
if (!force) {
- warnx("%s: error: unknown partition type (%d)",
- device_name, mbr->mbr_part[i].part_typ);
- return;
+ gpt_warnx(gpt, "unknown partition type (%d)",
+ mbr->mbr_part[i].part_typ);
+ return -1;
}
+ break;
}
}
- ent = tbl->map_data;
- hdr->hdr_crc_table = htole32(crc32(ent, le32toh(hdr->hdr_entries) *
- le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
/*
* Create backup GPT.
*/
- memcpy(tpg->map_data, gpt->map_data, secsz);
- hdr = tpg->map_data;
- hdr->hdr_lba_self = htole64(tpg->map_start);
- hdr->hdr_lba_alt = htole64(gpt->map_start);
- hdr->hdr_lba_table = htole64(lbt->map_start);
- hdr->hdr_crc_self = 0; /* Don't ever forget this! */
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+ memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
+ hdr = gpt->tpg->map_data;
+ hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
+ hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
+ hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
- map = map_find(MAP_TYPE_MBR);
+ map = map_find(gpt, MAP_TYPE_MBR);
mbr = map->map_data;
/*
* Turn the MBR into a Protective MBR.
*/
memset(mbr->mbr_part, 0, sizeof(mbr->mbr_part));
- mbr->mbr_part[0].part_shd = 0x00;
- mbr->mbr_part[0].part_ssect = 0x02;
- mbr->mbr_part[0].part_scyl = 0x00;
- mbr->mbr_part[0].part_typ = MBR_PTYPE_PMBR;
- mbr->mbr_part[0].part_ehd = 0xfe;
- mbr->mbr_part[0].part_esect = 0xff;
- mbr->mbr_part[0].part_ecyl = 0xff;
- mbr->mbr_part[0].part_start_lo = htole16(1);
- if (last > 0xffffffff) {
- mbr->mbr_part[0].part_size_lo = htole16(0xffff);
- mbr->mbr_part[0].part_size_hi = htole16(0xffff);
- } else {
- mbr->mbr_part[0].part_size_lo = htole16(last);
- mbr->mbr_part[0].part_size_hi = htole16(last >> 16);
- }
- gpt_write(fd, map);
+ gpt_create_pmbr_part(mbr->mbr_part, last);
+ gpt_write(gpt, map);
+ return 0;
}
int
-cmd_migrate(int argc, char *argv[])
+cmd_migrate(gpt_t gpt, int argc, char *argv[])
{
- int ch, fd;
+ int ch;
+
+ parts = 128;
/* Get the migrate options */
- while ((ch = getopt(argc, argv, "fs")) != -1) {
+ while ((ch = getopt(argc, argv, "fp:s")) != -1) {
switch(ch) {
case 'f':
force = 1;
break;
+ case 'p':
+ parts = atoi(optarg);
+ break;
case 's':
slice = 1;
break;
default:
- usage_migrate();
+ return usage_migrate();
}
}
- if (argc == optind)
- usage_migrate();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- migrate(fd);
-
- gpt_close(fd);
- }
+ if (argc != optind)
+ return usage_migrate();
- return (0);
+ return migrate(gpt);
}
Index: src/sbin/gpt/header.c
diff -u src/sbin/gpt/header.c:1.3 src/sbin/gpt/header.c:1.4
--- src/sbin/gpt/header.c:1.3 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/header.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
#include <sys/cdefs.h>
#ifdef __RCSID
-__RCSID("$NetBSD: header.c,v 1.3 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: header.c,v 1.4 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,23 +47,24 @@ __RCSID("$NetBSD: header.c,v 1.3 2015/11
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
-const char headermsg[] = "header device ...";
+const char headermsg[] = "header";
-__dead static void
+static int
usage_header(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), headermsg);
- exit(1);
+ return -1;
}
-static void
-header(void)
+static int
+header(gpt_t gpt)
{
unsigned int revision;
- map_t *gpt;
+ map_t map;
struct gpt_hdr *hdr;
char buf[128];
#ifdef HN_AUTOSCALE
@@ -71,76 +72,66 @@ header(void)
#endif
#ifdef HN_AUTOSCALE
- if (humanize_number(human_num, 5, mediasz,
+ if (humanize_number(human_num, 5, gpt->mediasz,
"", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
human_num[0] = '\0';
if (human_num[0] != '\0')
- printf("Media Size: %llu (%s)\n", (long long unsigned)mediasz,
+ printf("Media Size: %ju (%s)\n", (uintmax_t)gpt->mediasz,
human_num);
else
#endif
- printf("Media Size: %llu\n", (long long unsigned)mediasz);
+ printf("Media Size: %ju\n", (uintmax_t)gpt->mediasz);
- printf("Sector Size: %u\n", secsz);
+ printf("Sector Size: %u\n", gpt->secsz);
#ifdef HN_AUTOSCALE
- if (humanize_number(human_num, 5, mediasz / secsz,
+ if (humanize_number(human_num, 5, gpt->mediasz / gpt->secsz,
"", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
human_num[0] = '\0';
if (human_num[0] != '\0')
- printf("Number of Sectors: %llu (%s)\n",
- (long long unsigned)(mediasz / secsz), human_num);
+ printf("Number of Sectors: %ju (%s)\n",
+ (uintmax_t)(gpt->mediasz / gpt->secsz), human_num);
else
#endif
- printf("Number of Sectors: %llu\n",
- (long long unsigned)(mediasz / secsz));
+ printf("Number of Sectors: %ju\n",
+ (uintmax_t)(gpt->mediasz / gpt->secsz));
printf("\nHeader Information:\n");
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- if (gpt == NULL) {
- printf("- GPT Header not found\n");
- return;
+ map = map_find(gpt, MAP_TYPE_PRI_GPT_HDR);
+ if (map == NULL) {
+ printf("- GPT Header not found");
+ return 0;
}
- hdr = gpt->map_data;
+ hdr = map->map_data;
revision = le32toh(hdr->hdr_revision);
printf("- GPT Header Revision: %u.%u\n", revision >> 16,
revision & 0xffff);
- printf("- First Data Sector: %llu\n",
- (long long unsigned)hdr->hdr_lba_start);
+ printf("- First Data Sector: %ju\n",
+ (uintmax_t)hdr->hdr_lba_start);
#ifdef HN_AUTOSCALE
if (humanize_number(human_num, 5, hdr->hdr_lba_end,
"", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
human_num[0] = '\0';
if (human_num[0] != '\0')
- printf("- Last Data Sector: %llu (%s)\n",
- (long long unsigned)hdr->hdr_lba_end, human_num);
+ printf("- Last Data Sector: %ju (%s)\n",
+ (uintmax_t)hdr->hdr_lba_end, human_num);
else
#endif
- printf("- Last Data Sector: %llu\n",
- (long long unsigned)hdr->hdr_lba_end);
+ printf("- Last Data Sector: %ju\n",
+ (uintmax_t)hdr->hdr_lba_end);
gpt_uuid_snprintf(buf, sizeof(buf), "%d", hdr->hdr_guid);
printf("- Media GUID: %s\n", buf);
printf("- Number of GPT Entries: %u\n", hdr->hdr_entries);
+ return 0;
}
int
-cmd_header(int argc, char *argv[])
+cmd_header(gpt_t gpt, int argc, char *argv[])
{
- int fd;
+ if (argc != optind)
+ return usage_header();
- if (argc == optind)
- usage_header();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
- header();
-
- gpt_close(fd);
- }
-
- return (0);
+ return header(gpt);
}
Index: src/sbin/gpt/map.h
diff -u src/sbin/gpt/map.h:1.3 src/sbin/gpt/map.h:1.4
--- src/sbin/gpt/map.h:1.3 Wed Nov 20 03:08:47 2013
+++ src/sbin/gpt/map.h Tue Dec 1 04:05:33 2015
@@ -29,7 +29,7 @@
#ifndef _MAP_H_
#define _MAP_H_
-typedef struct map {
+struct map {
off_t map_start;
off_t map_size;
struct map *map_next;
@@ -46,19 +46,17 @@ typedef struct map {
#define MAP_TYPE_PMBR 8
unsigned int map_index;
void *map_data;
-} map_t;
+};
-extern int lbawidth;
+struct gpt;
-map_t *map_add(off_t, off_t, int, void*);
-map_t *map_alloc(off_t, off_t, off_t);
-map_t *map_find(int);
-map_t *map_first(void);
-map_t *map_last(void);
-off_t map_resize(map_t *, off_t, off_t);
-
-off_t map_free(off_t, off_t);
-
-void map_init(off_t);
+struct map *map_add(struct gpt *, off_t, off_t, int, void *);
+struct map *map_alloc(struct gpt *, off_t, off_t, off_t);
+struct map *map_find(struct gpt *, int);
+struct map *map_first(struct gpt *);
+struct map *map_last(struct gpt *);
+off_t map_resize(struct gpt *, struct map *, off_t, off_t);
+off_t map_free(struct gpt *, off_t, off_t);
+void map_init(struct gpt *, off_t);
#endif /* _MAP_H_ */
Index: src/sbin/gpt/label.c
diff -u src/sbin/gpt/label.c:1.19 src/sbin/gpt/label.c:1.20
--- src/sbin/gpt/label.c:1.19 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/label.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/label.c,v 1.3 2006/10/04 18:20:25 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: label.c,v 1.19 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: label.c,v 1.20 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,6 +47,7 @@ __RCSID("$NetBSD: label.c,v 1.19 2015/11
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
#include "gpt_uuid.h"
static int all;
@@ -55,12 +56,12 @@ static off_t block, size;
static unsigned int entry;
static uint8_t *name, *xlabel;
-const char labelmsg1[] = "label -a <-l label | -f file> device ...";
+const char labelmsg1[] = "label -a <-l label | -f file>";
const char labelmsg2[] = "label [-b blocknr] [-i index] [-L label] "
"[-s sectors]";
-const char labelmsg3[] = " [-t uuid] <-l label | -f file> device ...";
+const char labelmsg3[] = " [-t uuid] <-l label | -f file>";
-__dead static void
+static int
usage_label(void)
{
fprintf(stderr,
@@ -68,42 +69,22 @@ usage_label(void)
" %s %s\n"
" %*s %s\n", getprogname(), labelmsg1,
getprogname(), labelmsg2, (int)strlen(getprogname()), "", labelmsg3);
- exit(1);
+ return -1;
}
-static void
-label(int fd)
+static int
+label(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *m;
+ map_t m;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
unsigned int i;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
-
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
-
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
+ if ((hdr = gpt_hdr(gpt)) == NULL)
+ return -1;
/* Relabel all matching entries in the map. */
- for (m = map_first(); m != NULL; m = m->map_next) {
+ for (m = map_first(gpt); m != NULL; m = m->map_next) {
if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
continue;
if (entry > 0 && entry != m->map_index)
@@ -115,10 +96,7 @@ label(int fd)
i = m->map_index - 1;
- hdr = gpt->map_data;
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
-
+ ent = gpt_ent_primary(gpt, i);
if (xlabel != NULL)
if (strcmp((char *)xlabel,
(char *)utf16_to_utf8(ent->ent_name)) != 0)
@@ -131,32 +109,19 @@ label(int fd)
/* Label the primary entry. */
utf8_to_utf16(name, ent->ent_name, 36);
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
-
- hdr = tpg->map_data;
- ent = (void*)((char*)lbt->map_data + i *
- le32toh(hdr->hdr_entsz));
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
+ ent = gpt_ent_backup(gpt, i);
/* Label the secondary entry. */
utf8_to_utf16(name, ent->ent_name, 36);
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
-
- printf("partition %d on %s labeled %s\n", m->map_index,
- device_name, name);
+ gpt_msg(gpt, "Partition %d labeled %s", m->map_index, name);
}
+ return 0;
}
static void
@@ -187,10 +152,10 @@ name_from_file(const char *fn)
}
int
-cmd_label(int argc, char *argv[])
+cmd_label(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
int64_t human_num;
/* Get the label options */
@@ -246,27 +211,17 @@ cmd_label(int argc, char *argv[])
usage_label();
break;
default:
- usage_label();
+ return usage_label();
}
}
if (!all ^
(block > 0 || entry > 0 || xlabel != NULL || size > 0 ||
!gpt_uuid_is_nil(type)))
- usage_label();
-
- if (name == NULL || argc == optind)
- usage_label();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- label(fd);
+ return usage_label();
- gpt_close(fd);
- }
+ if (name == NULL || argc != optind)
+ return usage_label();
- return (0);
+ return label(gpt);
}
Index: src/sbin/gpt/main.c
diff -u src/sbin/gpt/main.c:1.1 src/sbin/gpt/main.c:1.2
--- src/sbin/gpt/main.c:1.1 Mon Nov 30 14:59:34 2015
+++ src/sbin/gpt/main.c Tue Dec 1 04:05:33 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.1 2015/11/30 19:59:34 christos Exp $ */
+/* $NetBSD: main.c,v 1.2 2015/12/01 09:05:33 christos Exp $ */
/*-
* Copyright (c) 2002 Marcel Moolenaar
@@ -34,7 +34,7 @@
#include <sys/cdefs.h>
#ifdef __RCSID
-__RCSID("$NetBSD: main.c,v 1.1 2015/11/30 19:59:34 christos Exp $");
+__RCSID("$NetBSD: main.c,v 1.2 2015/12/01 09:05:33 christos Exp $");
#endif
#include <stdio.h>
@@ -46,7 +46,7 @@ __RCSID("$NetBSD: main.c,v 1.1 2015/11/3
#include "gpt.h"
static struct {
- int (*fptr)(int, char *[]);
+ int (*fptr)(gpt_t, int, char *[]);
const char *name;
} cmdsw[] = {
{ cmd_add, "add" },
@@ -90,10 +90,14 @@ usage(void)
#endif
const char *p = getprogname();
const char *f =
- "[-nrqv] [-m <mediasize>] [-p <partitionnum>] [-s <sectorsize>]";
+ "[-nrqv] [-m <mediasize>] [-s <sectorsize>]";
- fprintf(stderr,
- "Usage: %s %s <command> [<args>]\n", p, f);
+ if (strcmp(p, "gpt") == 0)
+ fprintf(stderr,
+ "Usage: %s %s <command> [<args>] <device>\n", p, f);
+ else
+ fprintf(stderr,
+ "Usage: %s %s <device> <command> [<args>]\n", p, f);
fprintf(stderr,
"Commands:\n"
#ifndef HAVE_NBTOOL_CONFIG_H
@@ -153,11 +157,24 @@ prefix(const char *cmd)
int
main(int argc, char *argv[])
{
- char *cmd, *p;
+ char *cmd, *p, *dev = NULL;
int ch, i;
+ u_int secsz = 0;
+ off_t mediasz = 0;
+ int flags = 0;
+ int verbose = 0;
+ gpt_t gpt;
+
+ setprogname(argv[0]);
+
+ if (strcmp(getprogname(), "gpt") == 0) {
+ if (argc < 3)
+ usage();
+ dev = argv[--argc];
+ }
/* Get the generic options */
- while ((ch = getopt(argc, argv, "m:np:qrs:v")) != -1) {
+ while ((ch = getopt(argc, argv, "m:nqrs:v")) != -1) {
switch(ch) {
case 'm':
if (mediasz > 0)
@@ -167,20 +184,13 @@ main(int argc, char *argv[])
usage();
break;
case 'n':
- nosync = 1;
- break;
- case 'p':
- if (parts > 0)
- usage();
- parts = strtoul(optarg, &p, 10);
- if (*p != 0 || parts < 1)
- usage();
+ flags |= GPT_NOSYNC;
break;
case 'r':
- readonly = 1;
+ flags |= GPT_READONLY;
break;
case 'q':
- quiet = 1;
+ flags |= GPT_QUIET;
break;
case 's':
if (secsz > 0)
@@ -196,18 +206,32 @@ main(int argc, char *argv[])
usage();
}
}
- if (!parts)
- parts = 128;
+
+ if (argc == optind)
+ usage();
+
+ if (dev == NULL)
+ dev = argv[optind++];
if (argc == optind)
usage();
cmd = argv[optind++];
- for (i = 0; cmdsw[i].name != NULL && strcmp(cmd, cmdsw[i].name); i++);
+ for (i = 0; cmdsw[i].name != NULL && strcmp(cmd, cmdsw[i].name); i++)
+ continue;
if (cmdsw[i].fptr == NULL)
- errx(1, "unknown command: %s", cmd);
+ errx(EXIT_FAILURE, "Unknown command: %s", cmd);
prefix(cmd);
- return ((*cmdsw[i].fptr)(argc, argv));
+
+ gpt = gpt_open(dev, flags, verbose, mediasz, secsz);
+ if (gpt == NULL)
+ return EXIT_FAILURE;
+
+ if ((*cmdsw[i].fptr)(gpt, argc, argv) == -1)
+ return EXIT_FAILURE;
+
+ gpt_close(gpt);
+ return EXIT_SUCCESS;
}
Index: src/sbin/gpt/map.c
diff -u src/sbin/gpt/map.c:1.10 src/sbin/gpt/map.c:1.11
--- src/sbin/gpt/map.c:1.10 Sun Nov 29 09:12:35 2015
+++ src/sbin/gpt/map.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/map.c,v 1.6 2005/08/31 01:47:19 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: map.c,v 1.10 2015/11/29 14:12:35 christos Exp $");
+__RCSID("$NetBSD: map.c,v 1.11 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -43,15 +43,12 @@ __RCSID("$NetBSD: map.c,v 1.10 2015/11/2
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
-int lbawidth;
-
-static map_t *mediamap;
-
-static map_t *
+static map_t
mkmap(off_t start, off_t size, int type)
{
- map_t *m;
+ map_t m;
m = calloc(1, sizeof(*m));
if (m == NULL)
@@ -85,31 +82,31 @@ map_type(int t)
return maptypes[t];
}
-map_t *
-map_add(off_t start, off_t size, int type, void *data)
+map_t
+map_add(gpt_t gpt, off_t start, off_t size, int type, void *data)
{
- map_t *m, *n, *p;
+ map_t m, n, p;
#ifdef DEBUG
printf("add: %s %#jx %#jx\n", map_type(type), (uintmax_t)start,
(uintmax_t)size);
- for (n = mediamap; n; n = n->map_next)
+ for (n = gpt->mediamap; n; n = n->map_next)
printf("have: %s %#jx %#jx\n", map_type(n->map_type),
(uintmax_t)n->map_start, (uintmax_t)n->map_size);
#endif
- n = mediamap;
+ n = gpt->mediamap;
while (n != NULL && n->map_start + n->map_size <= start)
n = n->map_next;
if (n == NULL) {
- if (!quiet)
- warnx("Can't find map");
+ if (!(gpt->flags & GPT_QUIET))
+ gpt_warnx(gpt, "Can't find map");
return (NULL);
}
if (n->map_start + n->map_size < start + size) {
- if (!quiet)
- warnx("map entry doesn't fit media");
+ if (!(gpt->flags & GPT_QUIET))
+ gpt_warnx(gpt, "map entry doesn't fit media");
return (NULL);
}
@@ -117,8 +114,8 @@ map_add(off_t start, off_t size, int typ
if (n->map_type != MAP_TYPE_UNUSED) {
if (n->map_type != MAP_TYPE_MBR_PART ||
type != MAP_TYPE_GPT_PART) {
- if (!quiet)
- warnx("partition(%ju,%ju) mirrored",
+ if (!(gpt->flags & GPT_QUIET))
+ gpt_warnx(gpt, "partition(%ju,%ju) mirrored",
(uintmax_t)start, (uintmax_t)size);
}
}
@@ -130,7 +127,7 @@ map_add(off_t start, off_t size, int typ
if (n->map_type != MAP_TYPE_UNUSED) {
if (n->map_type != MAP_TYPE_MBR_PART ||
type != MAP_TYPE_GPT_PART) {
- warnx("bogus map current=%s new=%s",
+ gpt_warnx(gpt, "bogus map current=%s new=%s",
map_type(n->map_type), map_type(type));
return (NULL);
}
@@ -149,7 +146,7 @@ map_add(off_t start, off_t size, int typ
if (m->map_prev != NULL)
m->map_prev->map_next = m;
else
- mediamap = m;
+ gpt->mediamap = m;
n->map_prev = m;
n->map_start += size;
n->map_size -= size;
@@ -173,17 +170,17 @@ map_add(off_t start, off_t size, int typ
if (p->map_prev != NULL)
p->map_prev->map_next = p;
else
- mediamap = p;
+ gpt->mediamap = p;
}
return (m);
}
-map_t *
-map_alloc(off_t start, off_t size, off_t alignment)
+map_t
+map_alloc(gpt_t gpt, off_t start, off_t size, off_t alignment)
{
off_t delta;
- map_t *m;
+ map_t m;
if (alignment > 0) {
if ((start % alignment) != 0)
@@ -192,7 +189,7 @@ map_alloc(off_t start, off_t size, off_t
size = (size + alignment) / alignment * alignment;
}
- for (m = mediamap; m != NULL; m = m->map_next) {
+ for (m = gpt->mediamap; m != NULL; m = m->map_next) {
if (m->map_type != MAP_TYPE_UNUSED || m->map_start < 2)
continue;
if (start != 0 && m->map_start > start)
@@ -217,7 +214,7 @@ map_alloc(off_t start, off_t size, off_t
else
size = m->map_size - delta;
}
- return map_add(m->map_start + delta, size,
+ return map_add(gpt, m->map_start + delta, size,
MAP_TYPE_GPT_PART, NULL);
}
}
@@ -226,15 +223,15 @@ map_alloc(off_t start, off_t size, off_t
}
off_t
-map_resize(map_t *m, off_t size, off_t alignment)
+map_resize(gpt_t gpt, map_t m, off_t size, off_t alignment)
{
- map_t *n, *o;
+ map_t n, o;
off_t alignsize, prevsize;
n = m->map_next;
if (size < 0 || alignment < 0) {
- warnx("negative size or alignment");
+ gpt_warnx(gpt, "negative size or alignment");
return 0;
}
if (size == 0 && alignment == 0) {
@@ -319,40 +316,40 @@ map_resize(map_t *m, off_t size, off_t a
return alignsize;
}
-map_t *
-map_find(int type)
+map_t
+map_find(gpt_t gpt, int type)
{
- map_t *m;
+ map_t m;
- m = mediamap;
+ m = gpt->mediamap;
while (m != NULL && m->map_type != type)
m = m->map_next;
return (m);
}
-map_t *
-map_first(void)
+map_t
+map_first(gpt_t gpt)
{
- return mediamap;
+ return gpt->mediamap;
}
-map_t *
-map_last(void)
+map_t
+map_last(gpt_t gpt)
{
- map_t *m;
+ map_t m;
- m = mediamap;
+ m = gpt->mediamap;
while (m != NULL && m->map_next != NULL)
m = m->map_next;
return (m);
}
off_t
-map_free(off_t start, off_t size)
+map_free(gpt_t gpt, off_t start, off_t size)
{
- map_t *m;
+ map_t m;
- m = mediamap;
+ m = gpt->mediamap;
while (m != NULL && m->map_start + m->map_size <= start)
m = m->map_next;
@@ -364,12 +361,12 @@ map_free(off_t start, off_t size)
}
void
-map_init(off_t size)
+map_init(gpt_t gpt, off_t size)
{
char buf[32];
- mediamap = mkmap(0LL, size, MAP_TYPE_UNUSED);
- lbawidth = snprintf(buf, sizeof(buf), "%ju", (uintmax_t)size);
- if (lbawidth < 5)
- lbawidth = 5;
+ gpt->mediamap = mkmap(0LL, size, MAP_TYPE_UNUSED);
+ gpt->lbawidth = snprintf(buf, sizeof(buf), "%ju", (uintmax_t)size);
+ if (gpt->lbawidth < 5)
+ gpt->lbawidth = 5;
}
Index: src/sbin/gpt/remove.c
diff -u src/sbin/gpt/remove.c:1.17 src/sbin/gpt/remove.c:1.18
--- src/sbin/gpt/remove.c:1.17 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/remove.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: remove.c,v 1.17 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: remove.c,v 1.18 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,6 +47,7 @@ __RCSID("$NetBSD: remove.c,v 1.17 2015/1
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static int all;
static gpt_uuid_t type;
@@ -54,11 +55,11 @@ static off_t block, size;
static unsigned int entry;
static uint8_t *label;
-const char removemsg1[] = "remove -a device ...";
+const char removemsg1[] = "remove -a";
const char removemsg2[] = "remove [-b blocknr] [-i index] [-L label] "
- "[-s sectors] [-t type] device ...";
+ "[-s sectors] [-t type]";
-__dead static void
+static int
usage_remove(void)
{
@@ -66,42 +67,21 @@ usage_remove(void)
"usage: %s %s\n"
" %s %s\n",
getprogname(), removemsg1, getprogname(), removemsg2);
- exit(1);
+ return -1;
}
-static void
-rem(int fd)
+static int
+rem(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *m;
- struct gpt_hdr *hdr;
+ map_t m;
struct gpt_ent *ent;
unsigned int i;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
-
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
-
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
+ if (gpt_hdr(gpt) == NULL)
+ return -1;
/* Remove all matching entries in the map. */
- for (m = map_first(); m != NULL; m = m->map_next) {
+ for (m = map_first(gpt); m != NULL; m = m->map_next) {
if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
continue;
if (entry > 0 && entry != m->map_index)
@@ -113,9 +93,7 @@ rem(int fd)
i = m->map_index - 1;
- hdr = gpt->map_data;
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_primary(gpt, i);
if (label != NULL)
if (strcmp((char *)label,
@@ -129,38 +107,26 @@ rem(int fd)
/* Remove the primary entry by clearing the partition type. */
gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
-
- hdr = tpg->map_data;
- ent = (void*)((char*)lbt->map_data + i *
- le32toh(hdr->hdr_entsz));
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
+
+ ent = gpt_ent_backup(gpt, i);
/* Remove the secondary entry. */
gpt_uuid_copy(ent->ent_type, gpt_uuid_nil);
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
- printf("partition %d removed from %s\n", m->map_index,
- device_name);
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
+ gpt_msg(gpt, "partition %d removed", m->map_index);
}
+ return 0;
}
int
-cmd_remove(int argc, char *argv[])
+cmd_remove(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
int64_t human_num;
/* Get the remove options */
@@ -168,28 +134,28 @@ cmd_remove(int argc, char *argv[])
switch(ch) {
case 'a':
if (all > 0)
- usage_remove();
+ return usage_remove();
all = 1;
break;
case 'b':
if (block > 0)
- usage_remove();
+ return usage_remove();
if (dehumanize_number(optarg, &human_num) < 0)
- usage_remove();
+ return usage_remove();
block = human_num;
if (block < 1)
- usage_remove();
+ return usage_remove();
break;
case 'i':
if (entry > 0)
- usage_remove();
+ return usage_remove();
entry = strtoul(optarg, &p, 10);
if (*p != 0 || entry < 1)
- usage_remove();
+ return usage_remove();
break;
case 'L':
if (label != NULL)
- usage_remove();
+ return usage_remove();
label = (uint8_t *)strdup(optarg);
break;
case 's':
@@ -197,36 +163,26 @@ cmd_remove(int argc, char *argv[])
usage_remove();
size = strtoll(optarg, &p, 10);
if (*p != 0 || size < 1)
- usage_remove();
+ return usage_remove();
break;
case 't':
if (!gpt_uuid_is_nil(type))
- usage_remove();
+ return usage_remove();
if (gpt_uuid_parse(optarg, type) != 0)
- usage_remove();
+ return usage_remove();
break;
default:
- usage_remove();
+ return usage_remove();
}
}
if (!all ^
(block > 0 || entry > 0 || label != NULL || size > 0 ||
!gpt_uuid_is_nil(type)))
- usage_remove();
+ return usage_remove();
- if (argc == optind)
- usage_remove();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- rem(fd);
-
- gpt_close(fd);
- }
+ if (argc != optind)
+ return usage_remove();
- return (0);
+ return rem(gpt);
}
Index: src/sbin/gpt/resize.c
diff -u src/sbin/gpt/resize.c:1.14 src/sbin/gpt/resize.c:1.15
--- src/sbin/gpt/resize.c:1.14 Mon Nov 30 21:03:55 2015
+++ src/sbin/gpt/resize.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: resize.c,v 1.14 2015/12/01 02:03:55 christos Exp $");
+__RCSID("$NetBSD: resize.c,v 1.15 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,167 +47,129 @@ __RCSID("$NetBSD: resize.c,v 1.14 2015/1
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static off_t alignment, sectors, size;
static unsigned int entry;
-const char resizemsg[] = "resize -i index [-a alignment] [-s size] device ...";
+const char resizemsg[] = "resize -i index [-a alignment] [-s size]";
-__dead static void
+static int
usage_resize(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), resizemsg);
- exit(1);
+ return -1;
}
-static void
-resize(int fd)
+static int
+resize(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
- map_t *map;
+ map_t map;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
unsigned int i;
off_t alignsecs, newsize;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- ent = NULL;
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
-
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
-
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
+ if ((hdr = gpt_hdr(gpt)) == NULL)
+ return -1;
- hdr = gpt->map_data;
- if (entry > le32toh(hdr->hdr_entries)) {
- warnx("%s: error: index %u out of range (%u max)", device_name,
- entry, le32toh(hdr->hdr_entries));
- return;
- }
+ ent = NULL;
i = entry - 1;
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_primary(gpt, i);
if (gpt_uuid_is_nil(ent->ent_type)) {
- warnx("%s: error: entry at index %u is unused",
- device_name, entry);
- return;
+ gpt_warnx(gpt, "Entry at index %u is unused", entry);
+ return -1;
}
- alignsecs = alignment / secsz;
+ alignsecs = alignment / gpt->secsz;
- for (map = map_first(); map != NULL; map = map->map_next) {
+ for (map = map_first(gpt); map != NULL; map = map->map_next) {
if (entry == map->map_index)
break;
}
if (map == NULL) {
- warnx("%s: error: could not find map entry corresponding "
- "to index", device_name);
- return;
+ gpt_warnx(gpt, "Could not find map entry corresponding "
+ "to index");
+ return -1;
}
if (sectors > 0 && sectors == map->map_size)
if (alignment == 0 ||
(alignment > 0 && sectors % alignsecs == 0)) {
/* nothing to do */
- warnx("%s: partition does not need resizing",
- device_name);
- return;
+ gpt_warnx(gpt, "partition does not need resizing");
+ return 0;
}
- newsize = map_resize(map, sectors, alignsecs);
+ newsize = map_resize(gpt, map, sectors, alignsecs);
if (newsize == 0 && alignment > 0) {
- warnx("%s: could not resize partition with alignment "
- "constraint", device_name);
- return;
+ gpt_warnx(gpt, "Could not resize partition with alignment "
+ "constraint");
+ return -1;
} else if (newsize == 0) {
- warnx("%s: could not resize partition", device_name);
- return;
+ gpt_warnx(gpt, "Could not resize partition");
+ return -1;
}
ent->ent_lba_end = htole64(map->map_start + newsize - 1LL);
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
-
- hdr = tpg->map_data;
- ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
+ ent = gpt_ent(gpt->gpt, gpt->lbt, i);
ent->ent_lba_end = htole64(map->map_start + newsize - 1LL);
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
-
- gpt_msg("Partition %d resized: %" PRIu64 " %" PRIu64 "\n", entry,
+ gpt_msg(gpt, "Partition %d resized: %" PRIu64 " %" PRIu64 "\n", entry,
map->map_start, newsize);
+
+ return 0;
}
int
-cmd_resize(int argc, char *argv[])
+cmd_resize(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
int64_t human_num;
while ((ch = getopt(argc, argv, "a:i:s:")) != -1) {
switch(ch) {
case 'a':
if (alignment > 0)
- usage_resize();
+ return usage_resize();
if (dehumanize_number(optarg, &human_num) < 0)
- usage_resize();
+ return usage_resize();
alignment = human_num;
if (alignment < 1)
- usage_resize();
+ return usage_resize();
break;
case 'i':
if (entry > 0)
- usage_resize();
+ return usage_resize();
entry = strtoul(optarg, &p, 10);
if (*p != 0 || entry < 1)
- usage_resize();
+ return usage_resize();
break;
case 's':
if (sectors > 0 || size > 0)
- usage_resize();
+ return usage_resize();
sectors = strtoll(optarg, &p, 10);
if (sectors < 1)
- usage_resize();
+ return usage_resize();
if (*p == '\0')
break;
if (*p == 's' || *p == 'S') {
if (*(p + 1) == '\0')
break;
else
- usage_resize();
+ return usage_resize();
}
if (*p == 'b' || *p == 'B') {
if (*(p + 1) == '\0') {
@@ -215,50 +177,26 @@ cmd_resize(int argc, char *argv[])
sectors = 0;
break;
} else
- usage_resize();
+ return usage_resize();
}
if (dehumanize_number(optarg, &human_num) < 0)
- usage_resize();
+ return usage_resize();
size = human_num;
sectors = 0;
break;
default:
- usage_resize();
+ return usage_resize();
}
}
- if (argc == optind)
- usage_resize();
+ if (argc != optind)
+ return usage_resize();
if (entry == 0)
- usage_resize();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- if (alignment % secsz != 0) {
- warnx("Alignment must be a multiple of sector size;");
- warnx("the sector size for %s is %d bytes.",
- device_name, secsz);
- continue;
- }
+ return usage_resize();
- if (size % secsz != 0) {
- warnx("Size in bytes must be a multiple of sector "
- "size;");
- warnx("the sector size for %s is %d bytes.",
- device_name, secsz);
- continue;
- }
- if (size > 0)
- sectors = size / secsz;
-
- resize(fd);
+ if ((sectors = gpt_check(gpt, alignment, size)) == -1)
+ return -1;
- gpt_close(fd);
- }
-
- return 0;
+ return resize(gpt);
}
Index: src/sbin/gpt/set.c
diff -u src/sbin/gpt/set.c:1.6 src/sbin/gpt/set.c:1.7
--- src/sbin/gpt/set.c:1.6 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/set.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: set.c,v 1.6 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: set.c,v 1.7 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,99 +47,67 @@ __RCSID("$NetBSD: set.c,v 1.6 2015/11/29
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static unsigned int entry;
static uint64_t attributes;
-const char setmsg[] = "set -a attribute -i index device ...";
+const char setmsg[] = "set -a attribute -i index";
-__dead static void
+static int
usage_set(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), setmsg);
- exit(1);
+ return -1;
}
-static void
-set(int fd)
+static int
+set(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
unsigned int i;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- ent = NULL;
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
-
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
+ if ((hdr = gpt_hdr(gpt)) == NULL)
+ return -1;
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
- hdr = gpt->map_data;
if (entry > le32toh(hdr->hdr_entries)) {
- warnx("%s: error: index %u out of range (%u max)", device_name,
+ gpt_warnx(gpt, "Index %u out of range (%u max)",
entry, le32toh(hdr->hdr_entries));
- return;
+ return -1;
}
i = entry - 1;
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_primary(gpt, i);
if (gpt_uuid_is_nil(ent->ent_type)) {
- warnx("%s: error: entry at index %u is unused",
- device_name, entry);
- return;
+ gpt_warnx(gpt, "Entry at index %u is unused", entry);
+ return -1;
}
ent->ent_attr |= attributes;
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
- hdr = tpg->map_data;
- ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_backup(gpt, i);
ent->ent_attr |= attributes;
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
- printf("Partition %d attributes updated\n", entry);
+ gpt_msg(gpt, "Partition %d attributes updated", entry);
+ return 0;
}
int
-cmd_set(int argc, char *argv[])
+cmd_set(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
while ((ch = getopt(argc, argv, "a:i:")) != -1) {
switch(ch) {
@@ -163,25 +131,15 @@ cmd_set(int argc, char *argv[])
usage_set();
break;
default:
- usage_set();
+ return usage_set();
}
}
- if (argc == optind)
- usage_set();
+ if (argc != optind)
+ return usage_set();
if (entry == 0 || attributes == 0)
- usage_set();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- set(fd);
+ return usage_set();
- gpt_close(fd);
- }
-
- return 0;
+ return set(gpt);
}
Index: src/sbin/gpt/unset.c
diff -u src/sbin/gpt/unset.c:1.6 src/sbin/gpt/unset.c:1.7
--- src/sbin/gpt/unset.c:1.6 Sat Nov 28 19:14:46 2015
+++ src/sbin/gpt/unset.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: unset.c,v 1.6 2015/11/29 00:14:46 christos Exp $");
+__RCSID("$NetBSD: unset.c,v 1.7 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,99 +47,65 @@ __RCSID("$NetBSD: unset.c,v 1.6 2015/11/
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static unsigned int entry;
static uint64_t attributes;
-const char unsetmsg[] = "unset -a attribute -i index device ...";
+const char unsetmsg[] = "unset -a attribute -i index";
-__dead static void
+static int
usage_unset(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), unsetmsg);
- exit(1);
+ return -1;
}
-static void
-unset(int fd)
+static int
+unset(gpt_t gpt)
{
- map_t *gpt, *tpg;
- map_t *tbl, *lbt;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
unsigned int i;
- gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
- ent = NULL;
- if (gpt == NULL) {
- warnx("%s: error: no primary GPT header; run create or recover",
- device_name);
- return;
- }
-
- tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
- if (tpg == NULL) {
- warnx("%s: error: no secondary GPT header; run recover",
- device_name);
- return;
- }
+ if ((hdr = gpt_hdr(gpt)) == NULL)
+ return -1;
- tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
- lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
- if (tbl == NULL || lbt == NULL) {
- warnx("%s: error: run recover -- trust me", device_name);
- return;
- }
-
- hdr = gpt->map_data;
if (entry > le32toh(hdr->hdr_entries)) {
- warnx("%s: error: index %u out of range (%u max)", device_name,
+ gpt_warnx(gpt, "Index %u out of range (%u max)",
entry, le32toh(hdr->hdr_entries));
- return;
+ return -1;
}
i = entry - 1;
- ent = (void*)((char*)tbl->map_data + i *
- le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_primary(gpt, i);
if (gpt_uuid_is_nil(ent->ent_type)) {
- warnx("%s: error: entry at index %u is unused",
- device_name, entry);
- return;
+ gpt_warnx(gpt, "Entry at index %u is unused", entry);
+ return -1;
}
ent->ent_attr &= ~attributes;
- hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, gpt);
- gpt_write(fd, tbl);
+ if (gpt_write_primary(gpt) == -1)
+ return -1;
- hdr = tpg->map_data;
- ent = (void*)((char*)lbt->map_data + i * le32toh(hdr->hdr_entsz));
+ ent = gpt_ent_backup(gpt, i);
ent->ent_attr &= ~attributes;
- hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
- le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
- hdr->hdr_crc_self = 0;
- hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
-
- gpt_write(fd, lbt);
- gpt_write(fd, tpg);
-
- printf("Partition %d attributes updated\n", entry);
+ if (gpt_write_backup(gpt) == -1)
+ return -1;
+ gpt_msg(gpt, "Partition %d attributes updated", entry);
+ return 0;
}
int
-cmd_unset(int argc, char *argv[])
+cmd_unset(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
while ((ch = getopt(argc, argv, "a:i:")) != -1) {
switch(ch) {
@@ -153,35 +119,25 @@ cmd_unset(int argc, char *argv[])
else if (strcmp(optarg, "bootfailed") == 0)
attributes |= GPT_ENT_ATTR_BOOTFAILED;
else
- usage_unset();
+ return usage_unset();
break;
case 'i':
if (entry > 0)
- usage_unset();
+ return usage_unset();
entry = strtoul(optarg, &p, 10);
if (*p != 0 || entry < 1)
- usage_unset();
+ return usage_unset();
break;
default:
- usage_unset();
+ return usage_unset();
}
}
- if (argc == optind)
- usage_unset();
+ if (argc != optind)
+ return usage_unset();
if (entry == 0 || attributes == 0)
- usage_unset();
-
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- unset(fd);
+ return usage_unset();
- gpt_close(fd);
- }
-
- return 0;
+ return unset(gpt);
}
Index: src/sbin/gpt/show.c
diff -u src/sbin/gpt/show.c:1.23 src/sbin/gpt/show.c:1.24
--- src/sbin/gpt/show.c:1.23 Sun Nov 29 09:12:56 2015
+++ src/sbin/gpt/show.c Tue Dec 1 04:05:33 2015
@@ -33,7 +33,7 @@
__FBSDID("$FreeBSD: src/sbin/gpt/show.c,v 1.14 2006/06/22 22:22:32 marcel Exp $");
#endif
#ifdef __RCSID
-__RCSID("$NetBSD: show.c,v 1.23 2015/11/29 14:12:56 christos Exp $");
+__RCSID("$NetBSD: show.c,v 1.24 2015/12/01 09:05:33 christos Exp $");
#endif
#include <sys/types.h>
@@ -47,40 +47,41 @@ __RCSID("$NetBSD: show.c,v 1.23 2015/11/
#include "map.h"
#include "gpt.h"
+#include "gpt_private.h"
static int show_label = 0;
static int show_uuid = 0;
static int show_guid = 0;
static unsigned int entry = 0;
-const char showmsg[] = "show [-glu] [-i index] device ...";
+const char showmsg[] = "show [-glu] [-i index] device";
-__dead static void
+static int
usage_show(void)
{
fprintf(stderr,
"usage: %s %s\n", getprogname(), showmsg);
- exit(1);
+ return -1;
}
-static void
-show(void)
+static int
+show(gpt_t gpt)
{
off_t start;
- map_t *m, *p;
+ map_t m, p;
struct mbr *mbr;
struct gpt_ent *ent;
unsigned int i;
- printf(" %*s", lbawidth, "start");
- printf(" %*s", lbawidth, "size");
+ printf(" %*s", gpt->lbawidth, "start");
+ printf(" %*s", gpt->lbawidth, "size");
printf(" index contents\n");
- m = map_first();
+ m = map_first(gpt);
while (m != NULL) {
- printf(" %*llu", lbawidth, (long long)m->map_start);
- printf(" %*llu", lbawidth, (long long)m->map_size);
+ printf(" %*llu", gpt->lbawidth, (long long)m->map_start);
+ printf(" %*llu", gpt->lbawidth, (long long)m->map_size);
putchar(' ');
putchar(' ');
if (m->map_index > 0)
@@ -155,31 +156,31 @@ show(void)
putchar('\n');
m = m->map_next;
}
+ return 0;
}
-static void
-show_one(void)
+static int
+show_one(gpt_t gpt)
{
- map_t *m;
+ map_t m;
struct gpt_ent *ent;
char s1[128], s2[128];
#ifdef HN_AUTOSCALE
char human_num[5];
#endif
- for (m = map_first(); m != NULL; m = m->map_next)
+ for (m = map_first(gpt); m != NULL; m = m->map_next)
if (entry == m->map_index)
break;
if (m == NULL) {
- warnx("%s: error: could not find index %d",
- device_name, entry);
- return;
+ gpt_warnx(gpt, "Could not find index %d", entry);
+ return -1;
}
ent = m->map_data;
printf("Details for index %d:\n", entry);
#ifdef HN_AUTOSCALE
- if (humanize_number(human_num, 5, (int64_t)(m->map_start * secsz),
+ if (humanize_number(human_num, 5, (int64_t)(m->map_start * gpt->secsz),
"", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
human_num[0] = '\0';
if (human_num[0] != '\0')
@@ -189,7 +190,7 @@ show_one(void)
#endif
printf("Start: %llu\n", (long long)m->map_start);
#ifdef HN_AUTOSCALE
- if (humanize_number(human_num, 5, (int64_t)(m->map_size * secsz),
+ if (humanize_number(human_num, 5, (int64_t)(m->map_size * gpt->secsz),
"", HN_AUTOSCALE, HN_NOSPACE|HN_B) < 0)
human_num[0] = '\0';
if (human_num[0] != '\0')
@@ -226,13 +227,14 @@ show_one(void)
if (ent->ent_attr & GPT_ENT_ATTR_BOOTFAILED)
printf(" partition that was marked bootonce but failed to boot\n");
}
+ return 0;
}
int
-cmd_show(int argc, char *argv[])
+cmd_show(gpt_t gpt, int argc, char *argv[])
{
char *p;
- int ch, fd;
+ int ch;
while ((ch = getopt(argc, argv, "gi:lu")) != -1) {
switch(ch) {
@@ -241,10 +243,10 @@ cmd_show(int argc, char *argv[])
break;
case 'i':
if (entry > 0)
- usage_show();
+ return usage_show();
entry = strtoul(optarg, &p, 10);
if (*p != 0 || entry < 1)
- usage_show();
+ return usage_show();
break;
case 'l':
show_label = 1;
@@ -253,25 +255,12 @@ cmd_show(int argc, char *argv[])
show_uuid = 1;
break;
default:
- usage_show();
+ return usage_show();
}
}
- if (argc == optind)
- usage_show();
+ if (argc != optind)
+ return usage_show();
- while (optind < argc) {
- fd = gpt_open(argv[optind++], 0);
- if (fd == -1)
- continue;
-
- if (entry > 0)
- show_one();
- else
- show();
-
- gpt_close(fd);
- }
-
- return (0);
+ return entry > 0 ? show_one(gpt) : show(gpt);
}
Added files:
Index: src/sbin/gpt/gpt_private.h
diff -u /dev/null src/sbin/gpt/gpt_private.h:1.1
--- /dev/null Tue Dec 1 04:05:33 2015
+++ src/sbin/gpt/gpt_private.h Tue Dec 1 04:05:33 2015
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+struct gpt {
+ char device_name[MAXPATHLEN];
+ int fd;
+ int flags;
+ int verbose;
+ int lbawidth;
+ struct map *mediamap;
+ struct map *tbl, *lbt, *gpt, *tpg;
+ u_int secsz;
+ off_t mediasz;
+ struct stat sb;
+};