From bbb4a8ab26feb9c8ac24ed6414778a3ddb65c60c Mon Sep 17 00:00:00 2001 From: christos Date: Tue, 1 Dec 2015 19:25:24 +0000 Subject: [PATCH] refactor more duplicated code. --- sbin/gpt/add.c | 63 ++----- sbin/gpt/create.c | 120 ++----------- sbin/gpt/gpt.c | 408 ++++++++++++++++++++++++++++++++++++++++-- sbin/gpt/gpt.h | 33 +++- sbin/gpt/label.c | 128 +++---------- sbin/gpt/migrate.c | 101 +---------- sbin/gpt/remove.c | 120 ++----------- sbin/gpt/resize.c | 58 +----- sbin/gpt/resizedisk.c | 33 +--- sbin/gpt/set.c | 68 +------ sbin/gpt/type.c | 125 ++----------- sbin/gpt/unset.c | 66 +------ 12 files changed, 515 insertions(+), 808 deletions(-) diff --git a/sbin/gpt/add.c b/sbin/gpt/add.c index 22329f2f52f7..fc18f6e08b80 100644 --- a/sbin/gpt/add.c +++ b/sbin/gpt/add.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: add.c,v 1.32 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: add.c,v 1.33 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -79,6 +79,7 @@ add(gpt_t gpt) struct gpt_ent *ent, e; unsigned int i; off_t alignsecs; + char buf[128]; if ((hdr = gpt_hdr(gpt)) == NULL) return -1; @@ -141,29 +142,20 @@ add(gpt_t gpt) memcpy(ent, &e, sizeof(e)); gpt_write_backup(gpt); - gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64 "\n", i + 1, - type, map->map_start, map->map_size); + gpt_uuid_snprintf(buf, sizeof(buf), "%d", type); + gpt_msg(gpt, "Partition %d added: %s %" PRIu64 " %" PRIu64, i + 1, + buf, map->map_start, map->map_size); return 0; } static int cmd_add(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; int64_t human_num; - while ((ch = getopt(argc, argv, "a:b:i:l:s:t:")) != -1) { + while ((ch = getopt(argc, argv, GPT_AIS "bl:t:")) != -1) { switch(ch) { - case 'a': - if (alignment > 0) - return usage(); - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - alignment = human_num; - if (alignment < 1) - return usage(); - break; case 'b': if (block > 0) return usage(); @@ -173,45 +165,11 @@ cmd_add(gpt_t gpt, int argc, char *argv[]) if (block < 1) return usage(); break; - case 'i': - if (entry > 0) - usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) - return usage(); - break; case 'l': if (name != NULL) return usage(); name = (uint8_t *)strdup(optarg); break; - case 's': - if (sectors > 0 || size > 0) - return usage(); - sectors = strtoll(optarg, &p, 10); - if (sectors < 1) - return usage(); - if (*p == '\0') - break; - if (*p == 's' || *p == 'S') { - if (*(p + 1) == '\0') - break; - else - return usage(); - } - if (*p == 'b' || *p == 'B') { - if (*(p + 1) == '\0') { - size = sectors; - sectors = 0; - break; - } else - return usage(); - } - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - size = human_num; - sectors = 0; - break; case 't': if (!gpt_uuid_is_nil(type)) return usage(); @@ -219,11 +177,14 @@ cmd_add(gpt_t gpt, int argc, char *argv[]) return usage(); break; default: - return usage(); + if (gpt_add_ais(gpt, &alignment, &entry, &size, ch) + == -1) + return usage(); + break; } } - if (argc == optind) + if (argc != optind) return usage(); /* Create NetBSD FFS partitions by default. */ @@ -234,7 +195,7 @@ cmd_add(gpt_t gpt, int argc, char *argv[]) if (optind != argc) return usage(); - if ((sectors = gpt_check(gpt, alignment, size)) == -1) + if ((sectors = gpt_check_ais(gpt, alignment, entry, size)) == -1) return -1; return add(gpt); diff --git a/sbin/gpt/create.c b/sbin/gpt/create.c index ccd796f5b620..9471c670bbdc 100644 --- a/sbin/gpt/create.c +++ b/sbin/gpt/create.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/create.c,v 1.11 2005/08/31 01:47:19 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: create.c,v 1.15 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: create.c,v 1.16 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -74,21 +74,10 @@ struct gpt_cmd c_create = { static int create(gpt_t gpt) { - off_t blocks, last; + off_t last = gpt_last(gpt); map_t map; struct mbr *mbr; - struct gpt_hdr *hdr; - struct gpt_ent *ent; - unsigned int i; - void *p; - last = gpt->mediasz / gpt->secsz - 1LL; - - if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL || - map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) { - gpt_warnx(gpt, "Device already contains a GPT"); - return -1; - } map = map_find(gpt, MAP_TYPE_MBR); if (map != NULL) { if (!force) { @@ -117,110 +106,21 @@ create(gpt_t gpt) gpt_create_pmbr_part(mbr->mbr_part, last); map = map_add(gpt, 0LL, 1LL, MAP_TYPE_PMBR, mbr); - gpt_write(gpt, map); + if (gpt_write(gpt, map) == -1) { + gpt_warn(gpt, "Can't write PMBR"); + return -1; + } } - /* Get the amount of free space after the MBR */ - blocks = map_free(gpt, 1LL, 0LL); - if (blocks == 0LL) { - gpt_warnx(gpt, "No room for the GPT header"); + if (gpt_create(gpt, last, parts, primary_only) == -1) return -1; - } - - /* Don't create more than parts entries. */ - if ((uint64_t)(blocks - 1) * gpt->secsz > - parts * sizeof(struct gpt_ent)) { - blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz; - if ((parts * sizeof(struct gpt_ent)) % gpt->secsz) - blocks++; - blocks++; /* Don't forget the header itself */ - } - - /* Never cross the median of the device. */ - if ((blocks + 1LL) > ((last + 1LL) >> 1)) - blocks = ((last + 1LL) >> 1) - 1LL; - - /* - * Get the amount of free space at the end of the device and - * calculate the size for the GPT structures. - */ - map = map_last(gpt); - if (map->map_type != MAP_TYPE_UNUSED) { - gpt_warnx(gpt, "No room for the backup header"); - return -1; - } - - if (map->map_size < blocks) - blocks = map->map_size; - if (blocks == 1LL) { - gpt_warnx(gpt, "No room for the GPT table"); - return -1; - } - - if ((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. */ - 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->gpt->map_data; - memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)); - hdr->hdr_revision = htole32(GPT_HDR_REVISION); - hdr->hdr_size = htole32(GPT_HDR_SIZE); - hdr->hdr_lba_self = htole64(gpt->gpt->map_start); - hdr->hdr_lba_alt = htole64(last); - hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks); - hdr->hdr_lba_end = htole64(last - blocks - 1LL); - gpt_uuid_generate(hdr->hdr_guid); - hdr->hdr_lba_table = htole64(gpt->tbl->map_start); - hdr->hdr_entries = htole32((blocks * gpt->secsz) / - sizeof(struct gpt_ent)); - if (le32toh(hdr->hdr_entries) > parts) - hdr->hdr_entries = htole32(parts); - hdr->hdr_entsz = htole32(sizeof(struct gpt_ent)); - - ent = gpt->tbl->map_data; - for (i = 0; i < le32toh(hdr->hdr_entries); i++) { - gpt_uuid_generate(ent[i].ent_guid); - } if (gpt_write_primary(gpt) == -1) return -1; - /* - * Create backup GPT if the user didn't suppress it. - */ - if (!primary_only) { - // XXX: error checks - gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR, - calloc(1, gpt->secsz)); - gpt->lbt = map_add(gpt, last - blocks, blocks, - MAP_TYPE_SEC_GPT_TBL, gpt->tbl->map_data); - memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz); - hdr = gpt->tpg->map_data; - hdr->hdr_lba_self = htole64(gpt->tpg->map_start); - hdr->hdr_lba_alt = htole64(gpt->gpt->map_start); - hdr->hdr_lba_table = htole64(gpt->lbt->map_start); - if (gpt_write_backup(gpt) == -1) - return -1; - } + if (!primary_only && gpt_write_backup(gpt) == -1) + return -1; + return 0; } diff --git a/sbin/gpt/gpt.c b/sbin/gpt/gpt.c index a64e1dcd3075..297ee9cd6765 100644 --- a/sbin/gpt/gpt.c +++ b/sbin/gpt/gpt.c @@ -35,7 +35,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: gpt.c,v 1.50 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: gpt.c,v 1.51 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -712,24 +712,7 @@ gpt_create_pmbr_part(struct mbr_part *part, off_t last) } } -off_t -gpt_check(gpt_t gpt, off_t alignment, off_t size) -{ - if (alignment % gpt->secsz != 0) { - gpt_warnx(gpt, "Alignment (%#jx) must be a multiple of " - "sector size (%#x)", (uintmax_t)alignment, gpt->secsz); - return -1; - } - if (size % gpt->secsz != 0) { - gpt_warnx(gpt, "Size (%#jx) must be a multiple of " - "sector size (%#x)", (uintmax_t)size, gpt->secsz); - return -1; - } - if (size > 0) - return size / gpt->secsz; - return 0; -} struct gpt_ent * gpt_ent(map_t map, map_t tbl, unsigned int i) { @@ -770,3 +753,392 @@ gpt_usage(const char *prefix, const struct gpt_cmd *cmd) } return -1; } + +off_t +gpt_last(gpt_t gpt) +{ + return gpt->mediasz / gpt->secsz - 1LL; +} + +int +gpt_create(gpt_t gpt, off_t last, u_int parts, int primary_only) +{ + off_t blocks; + map_t map; + struct gpt_hdr *hdr; + struct gpt_ent *ent; + unsigned int i; + void *p; + + if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL || + map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) { + gpt_warnx(gpt, "Device already contains a GPT"); + return -1; + } + + /* Get the amount of free space after the MBR */ + blocks = map_free(gpt, 1LL, 0LL); + if (blocks == 0LL) { + gpt_warnx(gpt, "No room for the GPT header"); + return -1; + } + + /* Don't create more than parts entries. */ + if ((uint64_t)(blocks - 1) * gpt->secsz > + parts * sizeof(struct gpt_ent)) { + blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz; + if ((parts * sizeof(struct gpt_ent)) % gpt->secsz) + blocks++; + blocks++; /* Don't forget the header itself */ + } + + /* Never cross the median of the device. */ + if ((blocks + 1LL) > ((last + 1LL) >> 1)) + blocks = ((last + 1LL) >> 1) - 1LL; + + /* + * Get the amount of free space at the end of the device and + * calculate the size for the GPT structures. + */ + map = map_last(gpt); + if (map->map_type != MAP_TYPE_UNUSED) { + gpt_warnx(gpt, "No room for the backup header"); + return -1; + } + + if (map->map_size < blocks) + blocks = map->map_size; + if (blocks == 1LL) { + gpt_warnx(gpt, "No room for the GPT table"); + return -1; + } + + blocks--; /* Number of blocks in the GPT table. */ + + if ((p = calloc(1, gpt->secsz)) == NULL) { + gpt_warnx(gpt, "Can't allocate the primary GPT"); + return -1; + } + if ((gpt->gpt = map_add(gpt, 1LL, 1LL, + MAP_TYPE_PRI_GPT_HDR, p)) == NULL) { + free(p); + gpt_warnx(gpt, "Can't add the primary GPT"); + return -1; + } + + if ((p = calloc(blocks, gpt->secsz)) == NULL) { + gpt_warnx(gpt, "Can't allocate the primary GPT table"); + return -1; + } + if ((gpt->tbl = map_add(gpt, 2LL, blocks, + MAP_TYPE_PRI_GPT_TBL, p)) == NULL) { + free(p); + gpt_warnx(gpt, "Can't add the primary GPT table"); + return -1; + } + + hdr = gpt->gpt->map_data; + memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)); + + /* + * XXX struct gpt_hdr is not a multiple of 8 bytes in size and thus + * contains padding we must not include in the size. + */ + hdr->hdr_revision = htole32(GPT_HDR_REVISION); + hdr->hdr_size = htole32(GPT_HDR_SIZE); + hdr->hdr_lba_self = htole64(gpt->gpt->map_start); + hdr->hdr_lba_alt = htole64(last); + hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks); + hdr->hdr_lba_end = htole64(last - blocks - 1LL); + gpt_uuid_generate(hdr->hdr_guid); + hdr->hdr_lba_table = htole64(gpt->tbl->map_start); + hdr->hdr_entries = htole32((blocks * gpt->secsz) / + sizeof(struct gpt_ent)); + if (le32toh(hdr->hdr_entries) > parts) + hdr->hdr_entries = htole32(parts); + hdr->hdr_entsz = htole32(sizeof(struct gpt_ent)); + + ent = gpt->tbl->map_data; + for (i = 0; i < le32toh(hdr->hdr_entries); i++) { + gpt_uuid_generate(ent[i].ent_guid); + } + + /* + * Create backup GPT if the user didn't suppress it. + */ + if (primary_only) + return last; + + if ((p = calloc(1, gpt->secsz)) == NULL) { + gpt_warnx(gpt, "Can't allocate the secondary GPT"); + return -1; + } + + if ((gpt->tpg = map_add(gpt, last, 1LL, + MAP_TYPE_SEC_GPT_HDR, p)) == NULL) { + gpt_warnx(gpt, "Can't add the secondary GPT"); + return -1; + } + + if ((gpt->lbt = map_add(gpt, last - blocks, blocks, + MAP_TYPE_SEC_GPT_TBL, gpt->tbl->map_data)) == NULL) { + gpt_warnx(gpt, "Can't add the secondary GPT table"); + return -1; + } + + memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz); + + hdr = gpt->tpg->map_data; + hdr->hdr_lba_self = htole64(gpt->tpg->map_start); + hdr->hdr_lba_alt = htole64(gpt->gpt->map_start); + hdr->hdr_lba_table = htole64(gpt->lbt->map_start); + return last; +} + +int +gpt_add_find(gpt_t gpt, struct gpt_find *find, int ch) +{ + int64_t human_num; + char *p; + + switch (ch) { + case 'a': + if (find->all > 0) + return -1; + find->all = 1; + break; + case 'b': + if (find->block > 0) + return -1; + if (dehumanize_number(optarg, &human_num) < 0) + return -1; + find->block = human_num; + if (find->block < 1) + return -1; + break; + case 'i': + if (find->entry > 0) + return -1; + find->entry = strtoul(optarg, &p, 10); + if (*p != 0 || find->entry < 1) + return -1; + break; + case 'L': + if (find->label != NULL) + return -1; + find->label = (uint8_t *)strdup(optarg); + break; + case 's': + if (find->size > 0) + return -1; + find->size = strtoll(optarg, &p, 10); + if (*p != 0 || find->size < 1) + return -1; + break; + case 't': + if (!gpt_uuid_is_nil(find->type)) + return -1; + if (gpt_uuid_parse(optarg, find->type) != 0) + return -1; + break; + default: + return -1; + } + return 0; +} + +int +gpt_change_ent(gpt_t gpt, const struct gpt_find *find, + void (*cfn)(struct gpt_ent *, void *), void *v) +{ + map_t m; + struct gpt_hdr *hdr; + struct gpt_ent *ent; + unsigned int i; + + if (!find->all ^ + (find->block > 0 || find->entry > 0 || find->label != NULL + || find->size > 0 || !gpt_uuid_is_nil(find->type))) + return -1; + + if ((hdr = gpt_hdr(gpt)) == NULL) + return -1; + + /* Relabel all matching entries in the map. */ + for (m = map_first(gpt); m != NULL; m = m->map_next) { + if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1) + continue; + if (find->entry > 0 && find->entry != m->map_index) + continue; + if (find->block > 0 && find->block != m->map_start) + continue; + if (find->size > 0 && find->size != m->map_size) + continue; + + i = m->map_index - 1; + + ent = gpt_ent_primary(gpt, i); + if (find->label != NULL) + if (strcmp((char *)find->label, + (char *)utf16_to_utf8(ent->ent_name)) != 0) + continue; + + if (!gpt_uuid_is_nil(find->type) && + !gpt_uuid_equal(find->type, ent->ent_type)) + continue; + + /* Change the primary entry. */ + (*cfn)(ent, v); + + if (gpt_write_primary(gpt) == -1) + return -1; + + ent = gpt_ent_backup(gpt, i); + /* Change the secondary entry. */ + (*cfn)(ent, v); + + if (gpt_write_backup(gpt) == -1) + return -1; + + gpt_msg(gpt, "Partition %d %s", m->map_index, find->msg); + } + return 0; +} + +int +gpt_add_ais(gpt_t gpt, off_t *alignment, u_int *entry, off_t *size, int ch) +{ + int64_t human_num; + off_t sectors; + char *p; + + switch (ch) { + case 'a': + if (*alignment > 0) + return -1; + if (dehumanize_number(optarg, &human_num) < 0) + return -1; + *alignment = human_num; + if (*alignment < 1) + return -1; + return 0; + case 'i': + if (*entry > 0) + return -1; + *entry = strtoul(optarg, &p, 10); + if (*p != 0 || *entry < 1) + return -1; + return 0; + case 's': + if (*size > 0) + return -1; + sectors = strtoll(optarg, &p, 10); + if (sectors < 1) + return -1; + if (*p == '\0' || ((*p == 's' || *p == 'S') && p[1] == '\0')) { + *size = sectors * gpt->secsz; + return 0; + } + if ((*p == 'b' || *p == 'B') && p[1] == '\0') { + *size = sectors; + return 0; + } + if (dehumanize_number(optarg, &human_num) < 0) + return -1; + *size = human_num; + return 0; + default: + return -1; + } +} + +off_t +gpt_check_ais(gpt_t gpt, off_t alignment, u_int entry, off_t size) +{ + if (entry == 0) { + gpt_warnx(gpt, "Entry not specified"); + return -1; + } + if (alignment % gpt->secsz != 0) { + gpt_warnx(gpt, "Alignment (%#jx) must be a multiple of " + "sector size (%#x)", (uintmax_t)alignment, gpt->secsz); + return -1; + } + + if (size % gpt->secsz != 0) { + gpt_warnx(gpt, "Size (%#jx) must be a multiple of " + "sector size (%#x)", (uintmax_t)size, gpt->secsz); + return -1; + } + if (size > 0) + return size / gpt->secsz; + return 0; +} +int +gpt_attr_get(uint64_t *attributes) +{ + if (strcmp(optarg, "biosboot") == 0) + *attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE; + else if (strcmp(optarg, "bootme") == 0) + *attributes |= GPT_ENT_ATTR_BOOTME; + else if (strcmp(optarg, "bootonce") == 0) + *attributes |= GPT_ENT_ATTR_BOOTONCE; + else if (strcmp(optarg, "bootfailed") == 0) + *attributes |= GPT_ENT_ATTR_BOOTFAILED; + else + return -1; + return 0; +} +int +gpt_attr_update(gpt_t gpt, u_int entry, uint64_t set, uint64_t clr) +{ + struct gpt_hdr *hdr; + struct gpt_ent *ent; + unsigned int i; + + if (entry == 0 || (set == 0 && clr == 0)) + return -1; + + if ((hdr = gpt_hdr(gpt)) == NULL) + return -1; + + if (entry > le32toh(hdr->hdr_entries)) { + gpt_warnx(gpt, "Index %u out of range (%u max)", + entry, le32toh(hdr->hdr_entries)); + return -1; + } + + i = entry - 1; + ent = gpt_ent_primary(gpt, i); + if (gpt_uuid_is_nil(ent->ent_type)) { + gpt_warnx(gpt, "Entry at index %u is unused", entry); + return -1; + } + + ent->ent_attr &= ~clr; + ent->ent_attr |= set; + + if (gpt_write_primary(gpt) == -1) + return -1; + + ent = gpt_ent_backup(gpt, i); + ent->ent_attr &= ~clr; + ent->ent_attr |= set; + + if (gpt_write_backup(gpt) == -1) + return -1; + gpt_msg(gpt, "Partition %d attributes updated", entry); + return 0; +} + +int +gpt_entry_get(u_int *entry) +{ + char *p; + if (*entry > 0) + return -1; + *entry = strtoul(optarg, &p, 10); + if (*p != 0 || *entry < 1) + return -1; + return 0; +} diff --git a/sbin/gpt/gpt.h b/sbin/gpt/gpt.h index 5ebf4cfce23a..8697d53e0b81 100644 --- a/sbin/gpt/gpt.h +++ b/sbin/gpt/gpt.h @@ -75,7 +75,14 @@ uint32_t crc32(const void *, size_t); void gpt_close(gpt_t); int gpt_gpt(gpt_t, off_t, int); gpt_t gpt_open(const char *, int, int, off_t, u_int); +#define GPT_READONLY 1 +#define GPT_MODIFIED 2 +#define GPT_QUIET 4 +#define GPT_NOSYNC 8 + void* gpt_read(gpt_t, off_t, size_t); +off_t gpt_last(gpt_t); +int gpt_create(gpt_t, off_t, u_int, int); int gpt_write(gpt_t, map_t); int gpt_write_crc(gpt_t, map_t, map_t); int gpt_write_primary(gpt_t); @@ -85,7 +92,6 @@ void gpt_msg(gpt_t, const char *, ...) __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); @@ -94,9 +100,26 @@ int gpt_usage(const char *, const struct gpt_cmd *); uint8_t *utf16_to_utf8(uint16_t *); void utf8_to_utf16(const uint8_t *, uint16_t *, size_t); -#define GPT_READONLY 1 -#define GPT_MODIFIED 2 -#define GPT_QUIET 4 -#define GPT_NOSYNC 8 +#define GPT_FIND "ab:i:L:s:t:" + +struct gpt_find { + int all; + gpt_uuid_t type; + off_t block, size; + unsigned int entry; + uint8_t *name, *label; + const char *msg; +}; +int gpt_change_ent(gpt_t, const struct gpt_find *, + void (*)(struct gpt_ent *, void *), void *); +int gpt_add_find(gpt_t, struct gpt_find *, int); + +#define GPT_AIS "a:i:s:" +int gpt_add_ais(gpt_t, off_t *, u_int *, off_t *, int); +off_t gpt_check_ais(gpt_t, off_t, u_int, off_t); + +int gpt_attr_get(uint64_t *); +int gpt_attr_update(gpt_t, u_int, uint64_t, uint64_t); +int gpt_entry_get(u_int *); #endif /* _GPT_H_ */ diff --git a/sbin/gpt/label.c b/sbin/gpt/label.c index 16daaa004d0b..1e3d33ea9e59 100644 --- a/sbin/gpt/label.c +++ b/sbin/gpt/label.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/label.c,v 1.3 2006/10/04 18:20:25 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: label.c,v 1.21 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: label.c,v 1.22 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -50,12 +50,6 @@ __RCSID("$NetBSD: label.c,v 1.21 2015/12/01 16:32:19 christos Exp $"); #include "gpt_private.h" #include "gpt_uuid.h" -static int all; -static gpt_uuid_t type; -static off_t block, size; -static unsigned int entry; -static uint8_t *name, *xlabel; - static int cmd_label(gpt_t, int, char *[]); static const char *labelhelp[] = { @@ -72,65 +66,21 @@ struct gpt_cmd c_label = { #define usage() gpt_usage(NULL, &c_label) -static int -label(gpt_t gpt) +static void +change(struct gpt_ent *ent, void *v) { - map_t m; - struct gpt_hdr *hdr; - struct gpt_ent *ent; - unsigned int i; - - if ((hdr = gpt_hdr(gpt)) == NULL) - return -1; - - /* Relabel all matching entries in the map. */ - for (m = map_first(gpt); m != NULL; m = m->map_next) { - if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1) - continue; - if (entry > 0 && entry != m->map_index) - continue; - if (block > 0 && block != m->map_start) - continue; - if (size > 0 && size != m->map_size) - continue; - - i = m->map_index - 1; - - ent = gpt_ent_primary(gpt, i); - if (xlabel != NULL) - if (strcmp((char *)xlabel, - (char *)utf16_to_utf8(ent->ent_name)) != 0) - continue; - - if (!gpt_uuid_is_nil(type) && - !gpt_uuid_equal(type, ent->ent_type)) - continue; - - /* Label the primary entry. */ - utf8_to_utf16(name, ent->ent_name, 36); - - if (gpt_write_primary(gpt) == -1) - return -1; - - ent = gpt_ent_backup(gpt, i); - /* Label the secondary entry. */ - utf8_to_utf16(name, ent->ent_name, 36); - - if (gpt_write_backup(gpt) == -1) - return -1; - - gpt_msg(gpt, "Partition %d labeled %s", m->map_index, name); - } - return 0; + uint8_t *name = v; + utf8_to_utf16(name, ent->ent_name, 36); } -static void +static char * name_from_file(const char *fn) { FILE *f; char *p; size_t maxlen = 1024; size_t len; + char *name; if (strcmp(fn, "-") != 0) { f = fopen(fn, "r"); @@ -149,79 +99,41 @@ name_from_file(const char *fn) p = strchr((const char *)name, '\n'); if (p != NULL) *p = '\0'; + return name; } static int cmd_label(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; - int64_t human_num; + struct gpt_find find; + char *name = NULL; + + memset(&find, 0, sizeof(find)); + find.msg = "label changed"; /* Get the label options */ - while ((ch = getopt(argc, argv, "ab:f:i:L:l:s:t:")) != -1) { + while ((ch = getopt(argc, argv, GPT_FIND "f:l:")) != -1) { switch(ch) { - case 'a': - if (all > 0) - return usage(); - all = 1; - break; - case 'b': - if (block > 0) - return usage(); - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - block = human_num; - if (block < 1) - return usage(); - break; case 'f': if (name != NULL) return usage(); - name_from_file(optarg); - break; - case 'i': - if (entry > 0) - return usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) - return usage(); - break; - case 'L': - if (xlabel != NULL) - return usage(); - xlabel = (uint8_t *)strdup(optarg); + name = name_from_file(optarg); break; case 'l': if (name != NULL) return usage(); - name = (uint8_t *)strdup(optarg); - break; - case 's': - if (size > 0) - return usage(); - size = strtoll(optarg, &p, 10); - if (*p != 0 || size < 1) - return usage(); - break; - case 't': - if (!gpt_uuid_is_nil(type)) - return usage(); - if (gpt_uuid_parse(optarg, type) != 0) - return usage(); + name = strdup(optarg); break; default: - return usage(); + if (gpt_add_find(gpt, &find, ch) == -1) + return usage(); + break; } } - if (!all ^ - (block > 0 || entry > 0 || xlabel != NULL || size > 0 || - !gpt_uuid_is_nil(type))) - return usage(); - if (name == NULL || argc != optind) return usage(); - return label(gpt); + return gpt_change_ent(gpt, &find, change, name); } diff --git a/sbin/gpt/migrate.c b/sbin/gpt/migrate.c index c15c0f43b05a..cf651e83a456 100644 --- a/sbin/gpt/migrate.c +++ b/sbin/gpt/migrate.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/migrate.c,v 1.16 2005/09/01 02:42:52 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: migrate.c,v 1.24 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: migrate.c,v 1.25 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -262,16 +262,13 @@ migrate_netbsd_disklabel(gpt_t gpt, off_t start, struct gpt_ent *ent) static int migrate(gpt_t gpt) { - off_t blocks, last; + off_t last = gpt_last(gpt); map_t map; - struct gpt_hdr *hdr; struct gpt_ent *ent; struct mbr *mbr; uint32_t start, size; unsigned int i; - last = gpt->mediasz / gpt->secsz - 1LL; - map = map_find(gpt, MAP_TYPE_MBR); if (map == NULL || map->map_start != 0) { gpt_warnx(gpt, "No partitions to convert"); @@ -280,86 +277,10 @@ migrate(gpt_t gpt) mbr = map->map_data; - if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL || - map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) { - gpt_warnx(gpt, "Device already contains a GPT"); + if (gpt_create(gpt, last, parts, 0) == -1) return -1; - } - - /* Get the amount of free space after the MBR */ - blocks = map_free(gpt, 1LL, 0LL); - if (blocks == 0LL) { - gpt_warnx(gpt, "No room for the GPT header"); - return -1; - } - - /* Don't create more than parts entries. */ - if ((uint64_t)(blocks - 1) * gpt->secsz > - parts * sizeof(struct gpt_ent)) { - blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz; - if ((parts * sizeof(struct gpt_ent)) % gpt->secsz) - blocks++; - blocks++; /* Don't forget the header itself */ - } - - /* Never cross the median of the device. */ - if ((blocks + 1LL) > ((last + 1LL) >> 1)) - blocks = ((last + 1LL) >> 1) - 1LL; - - /* - * Get the amount of free space at the end of the device and - * calculate the size for the GPT structures. - */ - map = map_last(gpt); - if (map->map_type != MAP_TYPE_UNUSED) { - gpt_warnx(gpt, "No room for the backup header"); - return -1; - } - - if (map->map_size < blocks) - blocks = map->map_size; - if (blocks == 1LL) { - gpt_warnx(gpt, "No room for the GPT table"); - return -1; - } - - blocks--; /* Number of blocks in the GPT table. */ - gpt->gpt = map_add(gpt, 1LL, 1LL, MAP_TYPE_PRI_GPT_HDR, - calloc(1, gpt->secsz)); - gpt->tbl = map_add(gpt, 2LL, blocks, MAP_TYPE_PRI_GPT_TBL, - calloc(blocks, gpt->secsz)); - if (gpt->gpt == NULL || gpt->tbl == NULL) - return -1; - - gpt->lbt = map_add(gpt, last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL, - gpt->tbl->map_data); - gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR, - calloc(1, gpt->secsz)); - - hdr = gpt->gpt->map_data; - memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)); - hdr->hdr_revision = htole32(GPT_HDR_REVISION); - - /* - * XXX struct gpt_hdr is not a multiple of 8 bytes in size and thus - * contains padding we must not include in the size. - */ - hdr->hdr_size = htole32(GPT_HDR_SIZE); - hdr->hdr_lba_self = htole64(gpt->gpt->map_start); - hdr->hdr_lba_alt = htole64(gpt->tpg->map_start); - hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks); - hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1LL); - gpt_uuid_generate(hdr->hdr_guid); - hdr->hdr_lba_table = htole64(gpt->tbl->map_start); - hdr->hdr_entries = htole32((blocks * gpt->secsz) / sizeof(struct gpt_ent)); - if (le32toh(hdr->hdr_entries) > parts) - hdr->hdr_entries = htole32(parts); - hdr->hdr_entsz = htole32(sizeof(struct gpt_ent)); ent = gpt->tbl->map_data; - for (i = 0; i < le32toh(hdr->hdr_entries); i++) { - gpt_uuid_generate(ent[i].ent_guid); - } /* Mirror partitions. */ for (i = 0; i < 4; i++) { @@ -408,26 +329,18 @@ migrate(gpt_t gpt) if (gpt_write_primary(gpt) == -1) return -1; - /* - * Create backup GPT. - */ - memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz); - hdr = gpt->tpg->map_data; - hdr->hdr_lba_self = htole64(gpt->tpg->map_start); - hdr->hdr_lba_alt = htole64(gpt->gpt->map_start); - hdr->hdr_lba_table = htole64(gpt->lbt->map_start); - if (gpt_write_backup(gpt) == -1) return -1; - map = map_find(gpt, MAP_TYPE_MBR); - mbr = map->map_data; /* * Turn the MBR into a Protective MBR. */ memset(mbr->mbr_part, 0, sizeof(mbr->mbr_part)); gpt_create_pmbr_part(mbr->mbr_part, last); - gpt_write(gpt, map); + if (gpt_write(gpt, map) == -1) { + gpt_warn(gpt, "Cant write PMBR"); + return -1; + } return 0; } diff --git a/sbin/gpt/remove.c b/sbin/gpt/remove.c index 623a59f06f23..7eba8a490f49 100644 --- a/sbin/gpt/remove.c +++ b/sbin/gpt/remove.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: remove.c,v 1.19 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: remove.c,v 1.20 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -49,12 +49,6 @@ __RCSID("$NetBSD: remove.c,v 1.19 2015/12/01 16:32:19 christos Exp $"); #include "gpt.h" #include "gpt_private.h" -static int all; -static gpt_uuid_t type; -static off_t block, size; -static unsigned int entry; -static uint8_t *label; - static int cmd_remove(gpt_t, int, char *[]); static const char *removehelp[] = { @@ -71,119 +65,29 @@ struct gpt_cmd c_remove = { #define usage() gpt_usage(NULL, &c_remove) -static int -rem(gpt_t gpt) +static void +change(struct gpt_ent *ent, void *v) { - map_t m; - struct gpt_ent *ent; - unsigned int i; - - if (gpt_hdr(gpt) == NULL) - return -1; - - /* Remove all matching entries in the map. */ - for (m = map_first(gpt); m != NULL; m = m->map_next) { - if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1) - continue; - if (entry > 0 && entry != m->map_index) - continue; - if (block > 0 && block != m->map_start) - continue; - if (size > 0 && size != m->map_size) - continue; - - i = m->map_index - 1; - - ent = gpt_ent_primary(gpt, i); - - if (label != NULL) - if (strcmp((char *)label, - (char *)utf16_to_utf8(ent->ent_name)) != 0) - continue; - - if (!gpt_uuid_is_nil(type) && - !gpt_uuid_equal(type, ent->ent_type)) - continue; - - /* Remove the primary entry by clearing the partition type. */ - gpt_uuid_copy(ent->ent_type, gpt_uuid_nil); - - if (gpt_write_primary(gpt) == -1) - return -1; - - ent = gpt_ent_backup(gpt, i); - - /* Remove the secondary entry. */ - gpt_uuid_copy(ent->ent_type, gpt_uuid_nil); - - if (gpt_write_backup(gpt) == -1) - return -1; - gpt_msg(gpt, "partition %d removed", m->map_index); - } - return 0; + /* Remove the primary entry by clearing the partition type. */ + gpt_uuid_copy(ent->ent_type, gpt_uuid_nil); } static int cmd_remove(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; - int64_t human_num; + struct gpt_find find; + + memset(&find, 0, sizeof(find)); + find.msg = "removed"; /* Get the remove options */ - while ((ch = getopt(argc, argv, "ab:i:L:s:t:")) != -1) { - switch(ch) { - case 'a': - if (all > 0) - return usage(); - all = 1; - break; - case 'b': - if (block > 0) - return usage(); - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - block = human_num; - if (block < 1) - return usage(); - break; - case 'i': - if (entry > 0) - return usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) - return usage(); - break; - case 'L': - if (label != NULL) - return usage(); - label = (uint8_t *)strdup(optarg); - break; - case 's': - if (size > 0) - usage(); - size = strtoll(optarg, &p, 10); - if (*p != 0 || size < 1) - return usage(); - break; - case 't': - if (!gpt_uuid_is_nil(type)) - return usage(); - if (gpt_uuid_parse(optarg, type) != 0) - return usage(); - break; - default: + while ((ch = getopt(argc, argv, GPT_FIND)) != -1) + if (gpt_add_find(gpt, &find, ch) == -1) return usage(); - } - } - - if (!all ^ - (block > 0 || entry > 0 || label != NULL || size > 0 || - !gpt_uuid_is_nil(type))) - return usage(); if (argc != optind) return usage(); - return rem(gpt); + return gpt_change_ent(gpt, &find, change, NULL); } diff --git a/sbin/gpt/resize.c b/sbin/gpt/resize.c index db74b41d0c1c..97c7f4c20e0f 100644 --- a/sbin/gpt/resize.c +++ b/sbin/gpt/resize.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: resize.c,v 1.16 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: resize.c,v 1.17 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -139,67 +139,17 @@ resize(gpt_t gpt) static int cmd_resize(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; - int64_t human_num; - while ((ch = getopt(argc, argv, "a:i:s:")) != -1) { - switch(ch) { - case 'a': - if (alignment > 0) - return usage(); - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - alignment = human_num; - if (alignment < 1) - return usage(); - break; - case 'i': - if (entry > 0) - return usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) - return usage(); - break; - case 's': - if (sectors > 0 || size > 0) - return usage(); - sectors = strtoll(optarg, &p, 10); - if (sectors < 1) - return usage(); - if (*p == '\0') - break; - if (*p == 's' || *p == 'S') { - if (*(p + 1) == '\0') - break; - else - return usage(); - } - if (*p == 'b' || *p == 'B') { - if (*(p + 1) == '\0') { - size = sectors; - sectors = 0; - break; - } else - return usage(); - } - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - size = human_num; - sectors = 0; - break; - default: + while ((ch = getopt(argc, argv, GPT_AIS)) != -1) { + if (gpt_add_ais(gpt, &alignment, &entry, &size, ch) == -1) return usage(); - } } if (argc != optind) return usage(); - if (entry == 0) - return usage(); - - if ((sectors = gpt_check(gpt, alignment, size)) == -1) + if ((sectors = gpt_check_ais(gpt, alignment, entry, size)) == -1) return -1; return resize(gpt); diff --git a/sbin/gpt/resizedisk.c b/sbin/gpt/resizedisk.c index 1590d8393713..daf650e230bf 100644 --- a/sbin/gpt/resizedisk.c +++ b/sbin/gpt/resizedisk.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: resizedisk.c,v 1.9 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: resizedisk.c,v 1.10 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -223,38 +223,13 @@ resizedisk(gpt_t gpt) static int cmd_resizedisk(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; - int64_t human_num; while ((ch = getopt(argc, argv, "s:")) != -1) { switch(ch) { case 's': - if (sector > 0 || size > 0) - return usage(); - sector = strtoll(optarg, &p, 10); - if (sector < 1) - return usage(); - if (*p == '\0') - break; - if (*p == 's' || *p == 'S') { - if (*(p + 1) == '\0') - break; - else - return usage(); - } - if (*p == 'b' || *p == 'B') { - if (*(p + 1) == '\0') { - size = sector; - sector = 0; - break; - } else - return usage(); - } - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - size = human_num; - sector = 0; + if (gpt_add_ais(gpt, NULL, NULL, &size, ch) == -1) + return -1; break; default: return usage(); @@ -264,7 +239,7 @@ cmd_resizedisk(gpt_t gpt, int argc, char *argv[]) if (argc != optind) return usage(); - if ((sector = gpt_check(gpt, 0, size)) == -1) + if ((sector = gpt_check_ais(gpt, 0, ~0, size)) == -1) return -1; return resizedisk(gpt); diff --git a/sbin/gpt/set.c b/sbin/gpt/set.c index a10bdf7addb5..a24585d240ca 100644 --- a/sbin/gpt/set.c +++ b/sbin/gpt/set.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: set.c,v 1.8 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: set.c,v 1.9 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -49,9 +49,6 @@ __RCSID("$NetBSD: set.c,v 1.8 2015/12/01 16:32:19 christos Exp $"); #include "gpt.h" #include "gpt_private.h" -static unsigned int entry; -static uint64_t attributes; - static int cmd_set(gpt_t, int, char *[]); static const char *sethelp[] = { @@ -67,71 +64,21 @@ struct gpt_cmd c_set = { #define usage() gpt_usage(NULL, &c_set) -static int -set(gpt_t gpt) -{ - struct gpt_hdr *hdr; - struct gpt_ent *ent; - unsigned int i; - - - if ((hdr = gpt_hdr(gpt)) == NULL) - return -1; - - - if (entry > le32toh(hdr->hdr_entries)) { - gpt_warnx(gpt, "Index %u out of range (%u max)", - entry, le32toh(hdr->hdr_entries)); - return -1; - } - - i = entry - 1; - ent = gpt_ent_primary(gpt, i); - if (gpt_uuid_is_nil(ent->ent_type)) { - gpt_warnx(gpt, "Entry at index %u is unused", entry); - return -1; - } - - ent->ent_attr |= attributes; - - if (gpt_write_primary(gpt) == -1) - return -1; - - ent = gpt_ent_backup(gpt, i); - ent->ent_attr |= attributes; - - if (gpt_write_backup(gpt) == -1) - return -1; - - gpt_msg(gpt, "Partition %d attributes updated", entry); - return 0; -} - static int cmd_set(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; + unsigned int entry = 0; + uint64_t attributes = 0; while ((ch = getopt(argc, argv, "a:i:")) != -1) { switch(ch) { case 'a': - if (strcmp(optarg, "biosboot") == 0) - attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE; - else if (strcmp(optarg, "bootme") == 0) - attributes |= GPT_ENT_ATTR_BOOTME; - else if (strcmp(optarg, "bootonce") == 0) - attributes |= GPT_ENT_ATTR_BOOTONCE; - else if (strcmp(optarg, "bootfailed") == 0) - attributes |= GPT_ENT_ATTR_BOOTFAILED; - else + if (gpt_attr_get(&attributes) == -1) return usage(); break; case 'i': - if (entry > 0) - usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) + if (gpt_entry_get(&entry) == -1) return usage(); break; default: @@ -142,8 +89,5 @@ cmd_set(gpt_t gpt, int argc, char *argv[]) if (argc != optind) return usage(); - if (entry == 0 || attributes == 0) - return usage(); - - return set(gpt); + return gpt_attr_update(gpt, entry, attributes, 0); } diff --git a/sbin/gpt/type.c b/sbin/gpt/type.c index 85325f8b127c..72e72af3c9ec 100644 --- a/sbin/gpt/type.c +++ b/sbin/gpt/type.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: type.c,v 1.9 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: type.c,v 1.10 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -49,12 +49,6 @@ __RCSID("$NetBSD: type.c,v 1.9 2015/12/01 16:32:19 christos Exp $"); #include "gpt.h" #include "gpt_private.h" -static int all; -static gpt_uuid_t type, newtype; -static off_t block, size; -static unsigned int entry; -static uint8_t *label; - static int cmd_type(gpt_t, int, char *[]); static const char *typehelp[] = { @@ -71,108 +65,26 @@ struct gpt_cmd c_type = { #define usage() gpt_usage(NULL, &c_type) -static int -chtype(gpt_t gpt) +static void +change(struct gpt_ent *ent, void *v) { - map_t m; - struct gpt_ent *ent; - unsigned int i; - - if (gpt_hdr(gpt) == NULL) - return -1; - - /* Change type of all matching entries in the map. */ - for (m = map_first(gpt); m != NULL; m = m->map_next) { - if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1) - continue; - if (entry > 0 && entry != m->map_index) - continue; - if (block > 0 && block != m->map_start) - continue; - if (size > 0 && size != m->map_size) - continue; - - i = m->map_index - 1; - - ent = gpt_ent_primary(gpt, i); - - if (label != NULL) - if (strcmp((char *)label, - (char *)utf16_to_utf8(ent->ent_name)) != 0) - continue; - - if (!gpt_uuid_is_nil(type) && - !gpt_uuid_equal(type, ent->ent_type)) - continue; - - /* Change the primary entry. */ - gpt_uuid_copy(ent->ent_type, newtype); - - if (gpt_write_primary(gpt) == -1) - return -1; - - ent = gpt_ent_backup(gpt, i); - - /* Change the secondary entry. */ - gpt_uuid_copy(ent->ent_type, newtype); - - if (gpt_write_backup(gpt) == -1) - return -1; - - gpt_msg(gpt, "Partition %d type changed", m->map_index); - } - return 0; + gpt_uuid_t *newtype = v; + gpt_uuid_copy(ent->ent_type, *newtype); } static int cmd_type(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; - int64_t human_num; + gpt_uuid_t newtype; + struct gpt_find find; + + memset(&find, 0, sizeof(find)); + find.msg = "type changed"; /* Get the type options */ - while ((ch = getopt(argc, argv, "ab:i:L:s:t:T:")) != -1) { + while ((ch = getopt(argc, argv, GPT_FIND "T:")) != -1) { switch(ch) { - case 'a': - if (all > 0) - return usage(); - all = 1; - break; - case 'b': - if (block > 0) - return usage(); - if (dehumanize_number(optarg, &human_num) < 0) - return usage(); - block = human_num; - if (block < 1) - return usage(); - break; - case 'i': - if (entry > 0) - return usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) - return usage(); - break; - case 'L': - if (label != NULL) - return usage(); - label = (uint8_t *)strdup(optarg); - break; - case 's': - if (size > 0) - return usage(); - size = strtoll(optarg, &p, 10); - if (*p != 0 || size < 1) - return usage(); - break; - case 't': - if (!gpt_uuid_is_nil(type)) - return usage(); - if (gpt_uuid_parse(optarg, type) != 0) - return usage(); - break; case 'T': if (!gpt_uuid_is_nil(newtype)) return usage(); @@ -180,19 +92,14 @@ cmd_type(gpt_t gpt, int argc, char *argv[]) return usage(); break; default: - return usage(); + if (gpt_add_find(gpt, &find, ch) == -1) + return usage(); + break; } } - if (!all ^ - (block > 0 || entry > 0 || label != NULL || size > 0 || - !gpt_uuid_is_nil(type))) - return usage(); - if (gpt_uuid_is_nil(newtype)) + if (gpt_uuid_is_nil(newtype) || argc != optind) return usage(); - if (argc != optind) - return usage(); - - return chtype(gpt); + return gpt_change_ent(gpt, &find, change, &newtype); } diff --git a/sbin/gpt/unset.c b/sbin/gpt/unset.c index 062bf7bcb13b..775e66827235 100644 --- a/sbin/gpt/unset.c +++ b/sbin/gpt/unset.c @@ -33,7 +33,7 @@ __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $"); #endif #ifdef __RCSID -__RCSID("$NetBSD: unset.c,v 1.8 2015/12/01 16:32:19 christos Exp $"); +__RCSID("$NetBSD: unset.c,v 1.9 2015/12/01 19:25:24 christos Exp $"); #endif #include @@ -49,9 +49,6 @@ __RCSID("$NetBSD: unset.c,v 1.8 2015/12/01 16:32:19 christos Exp $"); #include "gpt.h" #include "gpt_private.h" -static unsigned int entry; -static uint64_t attributes; - static int cmd_unset(gpt_t, int, char *[]); static const char *unsethelp[] = { @@ -67,69 +64,21 @@ struct gpt_cmd c_unset = { #define usage() gpt_usage(NULL, &c_unset) -static int -unset(gpt_t gpt) -{ - struct gpt_hdr *hdr; - struct gpt_ent *ent; - unsigned int i; - - - if ((hdr = gpt_hdr(gpt)) == NULL) - return -1; - - if (entry > le32toh(hdr->hdr_entries)) { - gpt_warnx(gpt, "Index %u out of range (%u max)", - entry, le32toh(hdr->hdr_entries)); - return -1; - } - - i = entry - 1; - ent = gpt_ent_primary(gpt, i); - if (gpt_uuid_is_nil(ent->ent_type)) { - gpt_warnx(gpt, "Entry at index %u is unused", entry); - return -1; - } - - ent->ent_attr &= ~attributes; - - if (gpt_write_primary(gpt) == -1) - return -1; - - ent = gpt_ent_backup(gpt, i); - ent->ent_attr &= ~attributes; - - if (gpt_write_backup(gpt) == -1) - return -1; - gpt_msg(gpt, "Partition %d attributes updated", entry); - return 0; -} - static int cmd_unset(gpt_t gpt, int argc, char *argv[]) { - char *p; int ch; + unsigned int entry = 0; + uint64_t attributes = 0; while ((ch = getopt(argc, argv, "a:i:")) != -1) { switch(ch) { case 'a': - if (strcmp(optarg, "biosboot") == 0) - attributes |= GPT_ENT_ATTR_LEGACY_BIOS_BOOTABLE; - else if (strcmp(optarg, "bootme") == 0) - attributes |= GPT_ENT_ATTR_BOOTME; - else if (strcmp(optarg, "bootonce") == 0) - attributes |= GPT_ENT_ATTR_BOOTONCE; - else if (strcmp(optarg, "bootfailed") == 0) - attributes |= GPT_ENT_ATTR_BOOTFAILED; - else + if (gpt_attr_get(&attributes) == -1) return usage(); break; case 'i': - if (entry > 0) - return usage(); - entry = strtoul(optarg, &p, 10); - if (*p != 0 || entry < 1) + if (gpt_entry_get(&entry) == -1) return usage(); break; default: @@ -140,8 +89,5 @@ cmd_unset(gpt_t gpt, int argc, char *argv[]) if (argc != optind) return usage(); - if (entry == 0 || attributes == 0) - return usage(); - - return unset(gpt); + return gpt_attr_update(gpt, entry, 0, attributes); }