o Add functionality to add a GPT partition,
o Use DCE compliant UUID functions and provide local implementations if they don't exist, o Move dumping of the map to show.c and print the partition type, o Some cleanups and rearrangements. The default GPT partition type is UFS. When no starting block or size are specified, the tool will create a partition in the first free space it find (or that fits, depending on the size).
This commit is contained in:
parent
eb0f0a174a
commit
5d5e1c2b12
@ -1,7 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= gpt
|
||||
SRCS= create.c destroy.c gpt.c map.c migrate.c recover.c show.c
|
||||
SRCS= add.c create.c destroy.c gpt.c map.c migrate.c recover.c show.c
|
||||
WARNS= 4
|
||||
NOMAN= not yet
|
||||
|
||||
|
192
sbin/gpt/add.c
Normal file
192
sbin/gpt/add.c
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Marcel Moolenaar
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/uuid.h>
|
||||
#include <sys/gpt.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "map.h"
|
||||
#include "gpt.h"
|
||||
|
||||
off_t block, size;
|
||||
uuid_t type;
|
||||
|
||||
static void
|
||||
usage_add(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,
|
||||
"usage: %s [-bst] device\n", getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
add(int fd)
|
||||
{
|
||||
map_t *gpt, *tpg;
|
||||
map_t *tbl, *lbt;
|
||||
map_t *map;
|
||||
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: device does not contain a GPT", device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
|
||||
if (tpg == NULL) {
|
||||
warnx("%s: error: no secundary table; 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;
|
||||
}
|
||||
|
||||
/* Create UFS partitions by default. */
|
||||
if (uuid_is_nil(&type, NULL)) {
|
||||
uuid_t ufs = GPT_ENT_TYPE_FREEBSD_UFS;
|
||||
type = ufs;
|
||||
}
|
||||
|
||||
map = map_alloc(block, size);
|
||||
if (map == NULL) {
|
||||
warnx("%s: error: no space available on device", device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find empty slot in GPT table. */
|
||||
hdr = gpt->map_data;
|
||||
for (i = 0; i < hdr->hdr_entries; i++) {
|
||||
ent = (void*)((char*)tbl->map_data + i * hdr->hdr_entsz);
|
||||
if (uuid_is_nil(&ent->ent_type, NULL))
|
||||
break;
|
||||
}
|
||||
if (i == hdr->hdr_entries) {
|
||||
warnx("%s: error: no available table entries", device_name);
|
||||
return;
|
||||
}
|
||||
|
||||
ent->ent_type = type;
|
||||
ent->ent_lba_start = map->map_start;
|
||||
ent->ent_lba_end = map->map_start + map->map_size - 1LL;
|
||||
|
||||
hdr->hdr_crc_table = crc32(tbl->map_data,
|
||||
hdr->hdr_entries * hdr->hdr_entsz);
|
||||
hdr->hdr_crc_self = 0;
|
||||
hdr->hdr_crc_self = crc32(hdr, hdr->hdr_size);
|
||||
|
||||
gpt_write(fd, gpt);
|
||||
gpt_write(fd, tbl);
|
||||
|
||||
hdr = tpg->map_data;
|
||||
ent = (void*)((char*)lbt->map_data + i * hdr->hdr_entsz);
|
||||
|
||||
ent->ent_type = type;
|
||||
ent->ent_lba_start = map->map_start;
|
||||
ent->ent_lba_end = map->map_start + map->map_size - 1LL;
|
||||
|
||||
hdr->hdr_crc_table = crc32(lbt->map_data,
|
||||
hdr->hdr_entries * hdr->hdr_entsz);
|
||||
hdr->hdr_crc_self = 0;
|
||||
hdr->hdr_crc_self = crc32(hdr, hdr->hdr_size);
|
||||
|
||||
gpt_write(fd, lbt);
|
||||
gpt_write(fd, tpg);
|
||||
}
|
||||
|
||||
int
|
||||
cmd_add(int argc, char *argv[])
|
||||
{
|
||||
char *p;
|
||||
int ch, fd;
|
||||
uint32_t status;
|
||||
|
||||
/* Get the migrate options */
|
||||
while ((ch = getopt(argc, argv, "b:s:t:")) != -1) {
|
||||
switch(ch) {
|
||||
case 'b':
|
||||
if (block > 0)
|
||||
usage_add();
|
||||
block = strtol(optarg, &p, 10);
|
||||
if (*p != 0 || block < 1)
|
||||
usage_add();
|
||||
break;
|
||||
case 's':
|
||||
if (size > 0)
|
||||
usage_add();
|
||||
size = strtol(optarg, &p, 10);
|
||||
if (*p != 0 || size < 1)
|
||||
usage_add();
|
||||
break;
|
||||
case 't':
|
||||
if (!uuid_is_nil(&type, NULL))
|
||||
usage_add();
|
||||
uuid_from_string(optarg, &type, &status);
|
||||
if (status != uuid_s_ok) {
|
||||
/* TODO: accept aliases. */
|
||||
usage_add();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage_add();
|
||||
}
|
||||
}
|
||||
|
||||
if (argc == optind)
|
||||
usage_add();
|
||||
|
||||
while (optind < argc) {
|
||||
fd = gpt_open(argv[optind++]);
|
||||
if (fd == -1) {
|
||||
warn("unable to open device '%s'", device_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
add(fd);
|
||||
|
||||
gpt_close(fd);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
@ -69,7 +69,7 @@ create(int fd)
|
||||
}
|
||||
|
||||
/* Get the amount of free space after the MBR */
|
||||
blocks = map_unused(1LL, 0LL);
|
||||
blocks = map_free(1LL, 0LL);
|
||||
if (blocks == 0LL) {
|
||||
warnx("%s: error: no room for the GPT header", device_name);
|
||||
return;
|
||||
@ -125,7 +125,7 @@ create(int fd)
|
||||
hdr->hdr_lba_alt = last;
|
||||
hdr->hdr_lba_start = tbl->map_start + blocks;
|
||||
hdr->hdr_lba_end = last - blocks - 1LL;
|
||||
uuidgen(&hdr->hdr_uuid, 1);
|
||||
uuid_create(&hdr->hdr_uuid, NULL);
|
||||
hdr->hdr_lba_table = tbl->map_start;
|
||||
hdr->hdr_entries = (blocks * secsz) / sizeof(struct gpt_ent);
|
||||
if (hdr->hdr_entries > parts)
|
||||
@ -134,7 +134,7 @@ create(int fd)
|
||||
|
||||
ent = tbl->map_data;
|
||||
for (i = 0; i < hdr->hdr_entries; i++)
|
||||
uuidgen(&ent[i].ent_uuid, 1);
|
||||
uuid_create(&ent[i].ent_uuid, NULL);
|
||||
|
||||
hdr->hdr_crc_table = crc32(ent, hdr->hdr_entries * hdr->hdr_entsz);
|
||||
hdr->hdr_crc_self = crc32(hdr, hdr->hdr_size);
|
||||
|
104
sbin/gpt/gpt.c
104
sbin/gpt/gpt.c
@ -127,18 +127,62 @@ unicode16(short *dst, const wchar_t *src, size_t len)
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
uuid_string(uuid_t *uuid)
|
||||
#ifdef NEED_UUID_FUNCTIONS
|
||||
void
|
||||
uuid_create(uuid_t *u, uint32_t *st __unused)
|
||||
{
|
||||
static char buf[48];
|
||||
uuidgen(u, 1);
|
||||
}
|
||||
|
||||
void
|
||||
uuid_from_string(const char *s, uuid_t *u, uint32_t *st)
|
||||
{
|
||||
int n;
|
||||
|
||||
*st = uuid_s_invalid_string_uuid;
|
||||
|
||||
if (strlen(s) != 36 || s[8] != '-')
|
||||
return;
|
||||
|
||||
n = sscanf(s,
|
||||
"%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
|
||||
&u->time_low, &u->time_mid, &u->time_hi_and_version,
|
||||
&u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0],
|
||||
&u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]);
|
||||
|
||||
if (n != 11)
|
||||
return;
|
||||
|
||||
n = u->clock_seq_hi_and_reserved;
|
||||
if ((n & 0x80) != 0x00 && /* variant 0? */
|
||||
(n & 0xc0) != 0x80 && /* variant 1? */
|
||||
(n & 0xe0) != 0xc0) /* variant 2? */
|
||||
*st = uuid_s_bad_version;
|
||||
else
|
||||
*st = uuid_s_ok;
|
||||
}
|
||||
|
||||
int32_t
|
||||
uuid_is_nil(uuid_t *u, uint32_t *st __unused)
|
||||
{
|
||||
uint32_t *p;
|
||||
|
||||
p = (uint32_t*)u;
|
||||
return ((p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
void
|
||||
uuid_to_string(uuid_t *u, char **s, uint32_t *st __unused)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
uuid->time_low, uuid->time_mid, uuid->time_hi_and_version,
|
||||
uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low,
|
||||
uuid->node[0], uuid->node[1], uuid->node[2], uuid->node[3],
|
||||
uuid->node[4], uuid->node[5]);
|
||||
return buf;
|
||||
u->time_low, u->time_mid, u->time_hi_and_version,
|
||||
u->clock_seq_hi_and_reserved, u->clock_seq_low, u->node[0],
|
||||
u->node[1], u->node[2], u->node[3], u->node[4], u->node[5]);
|
||||
*s = strdup(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
void*
|
||||
gpt_read(int fd, off_t lba, size_t count)
|
||||
@ -180,7 +224,7 @@ gpt_gpt(int fd, off_t lba)
|
||||
off_t size;
|
||||
struct gpt_ent *ent;
|
||||
struct gpt_hdr *hdr;
|
||||
char *p;
|
||||
char *p, *s;
|
||||
map_t *m;
|
||||
size_t blocks, tblsz;
|
||||
unsigned int i;
|
||||
@ -235,20 +279,19 @@ gpt_gpt(int fd, off_t lba)
|
||||
return (0);
|
||||
|
||||
for (i = 0; i < hdr->hdr_entries; i++) {
|
||||
uuid_t unused = GPT_ENT_TYPE_UNUSED;
|
||||
|
||||
ent = (void*)(p + i * hdr->hdr_entsz);
|
||||
if (!memcmp(&ent->ent_type, &unused, sizeof(uuid_t)))
|
||||
if (uuid_is_nil(&ent->ent_type, NULL))
|
||||
continue;
|
||||
|
||||
size = ent->ent_lba_end - ent->ent_lba_start + 1LL;
|
||||
|
||||
if (verbose > 2)
|
||||
if (verbose > 2) {
|
||||
uuid_to_string(&ent->ent_type, &s, NULL);
|
||||
warnx(
|
||||
"%s: GPT partition: type=%s, start=%llu, size=%llu",
|
||||
device_name, uuid_string(&ent->ent_type),
|
||||
"%s: GPT partition: type=%s, start=%llu, size=%llu", device_name, s,
|
||||
(long long)ent->ent_lba_start, (long long)size);
|
||||
m = map_add(ent->ent_lba_start, size, MAP_TYPE_GPT_PART, NULL);
|
||||
free(s);
|
||||
}
|
||||
m = map_add(ent->ent_lba_start, size, MAP_TYPE_GPT_PART, ent);
|
||||
if (m == NULL)
|
||||
return (-1);
|
||||
}
|
||||
@ -338,19 +381,18 @@ gpt_open(const char *dev)
|
||||
start = (start << 16) + mbr->mbr_part[i].part_start_lo;
|
||||
size = mbr->mbr_part[i].part_size_hi;
|
||||
size = (size << 16) + mbr->mbr_part[i].part_size_lo;
|
||||
if (start != 0 || size != 0) {
|
||||
if (verbose > 2)
|
||||
warnx(
|
||||
"%s: MBR partition: type=%d, start=%llu, size=%llu", device_name,
|
||||
mbr->mbr_part[i].part_typ,
|
||||
(long long)start, (long long)size);
|
||||
if (mbr->mbr_part[i].part_typ != 0xee) {
|
||||
m = map_add(start, size,
|
||||
MAP_TYPE_MBR_PART, NULL);
|
||||
if (m == NULL)
|
||||
goto close;
|
||||
}
|
||||
}
|
||||
if (start == 0 && size == 0)
|
||||
continue;
|
||||
if (verbose > 2)
|
||||
warnx("%s: MBR partition: type=%d, start=%llu, size=%llu",
|
||||
device_name, mbr->mbr_part[i].part_typ,
|
||||
(long long)start, (long long)size);
|
||||
if (mbr->mbr_part[i].part_typ == 0xee)
|
||||
continue;
|
||||
m = map_add(start, size, MAP_TYPE_MBR_PART,
|
||||
mbr->mbr_part + i);
|
||||
if (m == NULL)
|
||||
goto close;
|
||||
}
|
||||
} else {
|
||||
if (verbose)
|
||||
@ -384,7 +426,7 @@ static struct {
|
||||
int (*fptr)(int, char *[]);
|
||||
const char *name;
|
||||
} cmdsw[] = {
|
||||
{ NULL, "add" },
|
||||
{ cmd_add, "add" },
|
||||
{ cmd_create, "create" },
|
||||
{ NULL, "delete" },
|
||||
{ cmd_destroy, "destroy" },
|
||||
|
@ -29,26 +29,39 @@
|
||||
#ifndef _GPT_H_
|
||||
#define _GPT_H_
|
||||
|
||||
struct mbr_part {
|
||||
uint8_t part_flag; /* bootstrap flags */
|
||||
uint8_t part_shd; /* starting head */
|
||||
uint8_t part_ssect; /* starting sector */
|
||||
uint8_t part_scyl; /* starting cylinder */
|
||||
uint8_t part_typ; /* partition type */
|
||||
uint8_t part_ehd; /* end head */
|
||||
uint8_t part_esect; /* end sector */
|
||||
uint8_t part_ecyl; /* end cylinder */
|
||||
uint16_t part_start_lo; /* absolute starting ... */
|
||||
uint16_t part_start_hi; /* ... sector number */
|
||||
uint16_t part_size_lo; /* partition size ... */
|
||||
uint16_t part_size_hi; /* ... in sectors */
|
||||
};
|
||||
|
||||
struct mbr {
|
||||
uint16_t mbr_code[223];
|
||||
struct {
|
||||
uint8_t part_flag; /* bootstrap flags */
|
||||
uint8_t part_shd; /* starting head */
|
||||
uint8_t part_ssect; /* starting sector */
|
||||
uint8_t part_scyl; /* starting cylinder */
|
||||
uint8_t part_typ; /* partition type */
|
||||
uint8_t part_ehd; /* end head */
|
||||
uint8_t part_esect; /* end sector */
|
||||
uint8_t part_ecyl; /* end cylinder */
|
||||
uint16_t part_start_lo; /* absolute starting ... */
|
||||
uint16_t part_start_hi; /* ... sector number */
|
||||
uint16_t part_size_lo; /* partition size ... */
|
||||
uint16_t part_size_hi; /* ... in sectors */
|
||||
} mbr_part[4];
|
||||
struct mbr_part mbr_part[4];
|
||||
uint16_t mbr_sig;
|
||||
#define MBR_SIG 0xAA55
|
||||
};
|
||||
|
||||
#ifndef uuid_s_ok
|
||||
#define NEED_UUID_FUNCTIONS
|
||||
#define uuid_s_ok 0
|
||||
#define uuid_s_bad_version 1
|
||||
#define uuid_s_invalid_string_uuid 2
|
||||
void uuid_create(uuid_t *, uint32_t *);
|
||||
void uuid_from_string(const char *, uuid_t *, uint32_t *);
|
||||
int32_t uuid_is_nil(uuid_t *, uint32_t *);
|
||||
void uuid_to_string(uuid_t *, char **, uint32_t *);
|
||||
#endif
|
||||
|
||||
extern char device_name[];
|
||||
extern off_t mediasz;
|
||||
extern u_int parts;
|
||||
@ -62,6 +75,7 @@ void* gpt_read(int, off_t, size_t);
|
||||
int gpt_write(int, map_t *);
|
||||
void unicode16(short *, const wchar_t *, size_t);
|
||||
|
||||
int cmd_add(int, char *[]);
|
||||
int cmd_create(int, char *[]);
|
||||
int cmd_destroy(int, char *[]);
|
||||
int cmd_migrate(int, char *[]);
|
||||
|
@ -33,7 +33,8 @@
|
||||
|
||||
#include "map.h"
|
||||
|
||||
static int lbawidth;
|
||||
int lbawidth;
|
||||
|
||||
static map_t *mediamap;
|
||||
|
||||
static map_t *
|
||||
@ -132,6 +133,31 @@ map_add(off_t start, off_t size, int type, void *data)
|
||||
return (m);
|
||||
}
|
||||
|
||||
map_t *
|
||||
map_alloc(off_t start, off_t size)
|
||||
{
|
||||
off_t delta;
|
||||
map_t *m;
|
||||
|
||||
for (m = 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)
|
||||
return (NULL);
|
||||
delta = (start != 0) ? start - m->map_start : 0;
|
||||
if (size == 0 || m->map_size - delta >= size) {
|
||||
if (m->map_size - delta <= 0)
|
||||
continue;
|
||||
if (size == 0)
|
||||
size = m->map_size - delta;
|
||||
return (map_add(m->map_start + delta, size,
|
||||
MAP_TYPE_GPT_PART, NULL));
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
map_t *
|
||||
map_find(int type)
|
||||
{
|
||||
@ -161,7 +187,7 @@ map_last(void)
|
||||
}
|
||||
|
||||
off_t
|
||||
map_unused(off_t start, off_t size)
|
||||
map_free(off_t start, off_t size)
|
||||
{
|
||||
map_t *m;
|
||||
|
||||
@ -176,53 +202,6 @@ map_unused(off_t start, off_t size)
|
||||
return (m->map_size - (start - m->map_start));
|
||||
}
|
||||
|
||||
void
|
||||
map_dump(void)
|
||||
{
|
||||
off_t end;
|
||||
map_t *m;
|
||||
|
||||
printf(" %*s", lbawidth, "start");
|
||||
printf(" %*s", lbawidth, "end");
|
||||
printf(" %*s", lbawidth, "size");
|
||||
printf(" %s\n", "contents");
|
||||
|
||||
m = mediamap;
|
||||
while (m != NULL) {
|
||||
end = m->map_start + m->map_size - 1;
|
||||
printf(" %*llu", lbawidth, (long long)m->map_start);
|
||||
printf(" %*llu", lbawidth, (long long)end);
|
||||
printf(" %*llu", lbawidth, (long long)m->map_size);
|
||||
|
||||
putchar(' '); putchar(' ');
|
||||
switch (m->map_type) {
|
||||
case MAP_TYPE_MBR:
|
||||
printf("MBR");
|
||||
break;
|
||||
case MAP_TYPE_PRI_GPT_HDR:
|
||||
printf("Pri GPT header");
|
||||
break;
|
||||
case MAP_TYPE_SEC_GPT_HDR:
|
||||
printf("Sec GPT header");
|
||||
break;
|
||||
case MAP_TYPE_PRI_GPT_TBL:
|
||||
printf("Pri GPT table");
|
||||
break;
|
||||
case MAP_TYPE_SEC_GPT_TBL:
|
||||
printf("Sec GPT table");
|
||||
break;
|
||||
case MAP_TYPE_MBR_PART:
|
||||
printf("MBR partition");
|
||||
break;
|
||||
case MAP_TYPE_GPT_PART:
|
||||
printf("GPT partition");
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
m = m->map_next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
map_init(off_t size)
|
||||
{
|
||||
|
@ -46,14 +46,16 @@ typedef struct map {
|
||||
void *map_data;
|
||||
} map_t;
|
||||
|
||||
extern int lbawidth;
|
||||
|
||||
map_t *map_add(off_t, off_t, int, void*);
|
||||
map_t *map_alloc(off_t, off_t);
|
||||
map_t *map_find(int);
|
||||
map_t *map_first(void);
|
||||
map_t *map_last(void);
|
||||
|
||||
off_t map_unused(off_t, off_t);
|
||||
off_t map_free(off_t, off_t);
|
||||
|
||||
void map_dump(void);
|
||||
void map_init(off_t);
|
||||
|
||||
#endif /* _MAP_H_ */
|
||||
|
@ -135,7 +135,7 @@ migrate(int fd)
|
||||
}
|
||||
|
||||
/* Get the amount of free space after the MBR */
|
||||
blocks = map_unused(1LL, 0LL);
|
||||
blocks = map_free(1LL, 0LL);
|
||||
if (blocks == 0LL) {
|
||||
warnx("%s: error: no room for the GPT header", device_name);
|
||||
return;
|
||||
@ -193,7 +193,7 @@ migrate(int fd)
|
||||
hdr->hdr_lba_alt = tpg->map_start;
|
||||
hdr->hdr_lba_start = tbl->map_start + blocks;
|
||||
hdr->hdr_lba_end = lbt->map_start - 1LL;
|
||||
uuidgen(&hdr->hdr_uuid, 1);
|
||||
uuid_create(&hdr->hdr_uuid, NULL);
|
||||
hdr->hdr_lba_table = tbl->map_start;
|
||||
hdr->hdr_entries = (blocks * secsz) / sizeof(struct gpt_ent);
|
||||
if (hdr->hdr_entries > parts)
|
||||
@ -202,7 +202,7 @@ migrate(int fd)
|
||||
|
||||
ent = tbl->map_data;
|
||||
for (i = 0; i < hdr->hdr_entries; i++)
|
||||
uuidgen(&ent[i].ent_uuid, 1);
|
||||
uuid_create(&ent[i].ent_uuid, NULL);
|
||||
|
||||
/* Mirror partitions. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
@ -49,6 +49,62 @@ usage_show(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
show(int fd __unused)
|
||||
{
|
||||
off_t end;
|
||||
map_t *m;
|
||||
struct mbr_part *part;
|
||||
struct gpt_ent *ent;
|
||||
char *s;
|
||||
|
||||
printf(" %*s", lbawidth, "start");
|
||||
printf(" %*s", lbawidth, "end");
|
||||
printf(" %*s", lbawidth, "size");
|
||||
printf(" %s\n", "contents");
|
||||
|
||||
m = map_first();
|
||||
while (m != NULL) {
|
||||
end = m->map_start + m->map_size - 1;
|
||||
printf(" %*llu", lbawidth, (long long)m->map_start);
|
||||
printf(" %*llu", lbawidth, (long long)end);
|
||||
printf(" %*llu", lbawidth, (long long)m->map_size);
|
||||
|
||||
putchar(' '); putchar(' ');
|
||||
switch (m->map_type) {
|
||||
case MAP_TYPE_MBR:
|
||||
printf("MBR");
|
||||
break;
|
||||
case MAP_TYPE_PRI_GPT_HDR:
|
||||
printf("Pri GPT header");
|
||||
break;
|
||||
case MAP_TYPE_SEC_GPT_HDR:
|
||||
printf("Sec GPT header");
|
||||
break;
|
||||
case MAP_TYPE_PRI_GPT_TBL:
|
||||
printf("Pri GPT table");
|
||||
break;
|
||||
case MAP_TYPE_SEC_GPT_TBL:
|
||||
printf("Sec GPT table");
|
||||
break;
|
||||
case MAP_TYPE_MBR_PART:
|
||||
printf("MBR partition: ");
|
||||
part = m->map_data;
|
||||
printf("type=%d", part->part_typ);
|
||||
break;
|
||||
case MAP_TYPE_GPT_PART:
|
||||
printf("GPT partition: ");
|
||||
ent = m->map_data;
|
||||
uuid_to_string(&ent->ent_type, &s, NULL);
|
||||
printf("type=%s", s);
|
||||
free(s);
|
||||
break;
|
||||
}
|
||||
putchar('\n');
|
||||
m = m->map_next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cmd_show(int argc, char *argv[])
|
||||
{
|
||||
@ -71,7 +127,7 @@ cmd_show(int argc, char *argv[])
|
||||
continue;
|
||||
}
|
||||
|
||||
map_dump();
|
||||
show(fd);
|
||||
|
||||
gpt_close(fd);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user