PR/44218 - David Young -- add "type" subcommand to change a partition type

This commit is contained in:
jnemeth 2014-09-28 08:14:51 +00:00
parent 7249f0e282
commit 88085c2f28
5 changed files with 254 additions and 6 deletions

View File

@ -1,10 +1,10 @@
# $NetBSD: Makefile,v 1.9 2014/09/23 07:47:54 jnemeth Exp $
# $NetBSD: Makefile,v 1.10 2014/09/28 08:14:51 jnemeth Exp $
# $FreeBSD: src/sbin/gpt/Makefile,v 1.7 2005/09/01 02:49:20 marcel Exp $
PROG= gpt
SRCS= add.c backup.c biosboot.c create.c destroy.c gpt.c label.c map.c \
migrate.c recover.c remove.c resize.c resizedisk.c restore.c \
set.c show.c unset.c
set.c show.c type.c unset.c
MAN= gpt.8
LDADD+= -lprop -lutil

View File

@ -1,4 +1,4 @@
.\" $NetBSD: gpt.8,v 1.30 2014/09/23 07:47:54 jnemeth Exp $
.\" $NetBSD: gpt.8,v 1.31 2014/09/28 08:14:51 jnemeth Exp $
.\"
.\" Copyright (c) 2002 Marcel Moolenaar
.\" All rights reserved.
@ -26,7 +26,7 @@
.\"
.\" $FreeBSD: src/sbin/gpt/gpt.8,v 1.17 2006/06/22 22:22:32 marcel Exp $
.\"
.Dd September 23, 2014
.Dd September 28, 2014
.Dt GPT 8
.Os
.Sh NAME
@ -457,6 +457,18 @@ The order of precedence for the options are:
.Fl l ,
.Fl g ,
.Fl u .
.\" ==== type ====
.It Nm Ic type Oo Fl a Oc Fl T Ar newtype Ar device ...
.It Nm Ic type Oo Fl b Ar blocknr Oc Oo Fl i Ar index Oc \
Oo Fl s Ar sectors Oc Oo Fl t Ar type Oc Fl T Ar newtype Ar device ...
The
.Ic type
command allows the user to change the type of any and all partitions
that match the selection.
It uses the same selection options as the
.Ic label
command.
See above for a description of these options.
.\" ==== unset ====
.It Nm Ic unset Fl a Ar attribute Fl i Ar index Ar device ...
The

View File

@ -31,7 +31,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.29 2014/09/23 07:47:54 jnemeth Exp $");
__RCSID("$NetBSD: gpt.c,v 1.30 2014/09/28 08:14:51 jnemeth Exp $");
#endif
#include <sys/param.h>
@ -732,6 +732,7 @@ static struct {
{ cmd_restore, "restore" },
{ cmd_set, "set" },
{ cmd_show, "show" },
{ cmd_type, "type" },
{ cmd_unset, "unset" },
{ NULL, "verify" },
{ NULL, NULL }
@ -744,7 +745,8 @@ usage(void)
extern const char createmsg[], destroymsg[], labelmsg1[], labelmsg2[];
extern const char labelmsg3[], migratemsg[], recovermsg[], removemsg1[];
extern const char removemsg2[], resizemsg[], resizediskmsg[];
extern const char restoremsg[], setmsg[], showmsg[], unsetmsg[];
extern const char restoremsg[], setmsg[], showmsg[], typemsg1[];
extern const char typemsg2[], typemsg3[], unsetmsg[];
fprintf(stderr,
"usage: %s %s\n"
@ -765,6 +767,9 @@ usage(void)
" %s %s\n"
" %s %s\n"
" %s %s\n"
" %s %s\n"
" %s %s\n"
" %*s %s\n"
" %s %s\n",
getprogname(), addmsg1,
getprogname(), addmsg2,
@ -784,6 +789,9 @@ usage(void)
getprogname(), restoremsg,
getprogname(), setmsg,
getprogname(), showmsg,
getprogname(), typemsg1,
getprogname(), typemsg2,
(int)strlen(getprogname()), "", typemsg3,
getprogname(), unsetmsg);
exit(1);
}

View File

@ -94,6 +94,7 @@ 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 *[]);
#endif /* _GPT_H_ */

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

@ -0,0 +1,227 @@
/*-
* Copyright (c) 2004 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifdef __FBSDID
__FBSDID("$FreeBSD: src/sbin/gpt/remove.c,v 1.10 2006/10/04 18:20:25 marcel Exp $");
#endif
#ifdef __RCSID
__RCSID("$NetBSD: type.c,v 1.1 2014/09/28 08:14:51 jnemeth Exp $");
#endif
#include <sys/types.h>
#include <err.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "map.h"
#include "gpt.h"
static int all;
static uuid_t type, newtype;
static off_t block, size;
static unsigned int entry;
const char typemsg1[] = "type -a -T newtype device ...";
const char typemsg2[] = "type [-b blocknr] [-i index] [-s sectors] [-t type]";
const char typemsg3[] = " -T newtype device ...";
__dead static void
usage_type(void)
{
fprintf(stderr,
"usage: %s %s\n"
" %s %s\n"
" %*s %s\n", getprogname(), typemsg1,
getprogname(), typemsg2, (int)strlen(getprogname()), "", typemsg3);
exit(1);
}
static void
chtype(int fd)
{
uuid_t uuid;
map_t *gpt, *tpg;
map_t *tbl, *lbt;
map_t *m;
struct gpt_hdr *hdr;
struct gpt_ent *ent;
unsigned int i;
gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
if (gpt == NULL) {
warnx("%s: error: no primary GPT header; run create or recover",
device_name);
return;
}
tpg = map_find(MAP_TYPE_SEC_GPT_HDR);
if (tpg == NULL) {
warnx("%s: error: no secondary GPT header; run recover",
device_name);
return;
}
tbl = map_find(MAP_TYPE_PRI_GPT_TBL);
lbt = map_find(MAP_TYPE_SEC_GPT_TBL);
if (tbl == NULL || lbt == NULL) {
warnx("%s: error: run recover -- trust me", device_name);
return;
}
/* Change type of all matching entries in the map. */
for (m = map_first(); m != NULL; m = m->map_next) {
if (m->map_type != MAP_TYPE_GPT_PART || m->map_index < 1)
continue;
if (entry > 0 && entry != m->map_index)
continue;
if (block > 0 && block != m->map_start)
continue;
if (size > 0 && size != m->map_size)
continue;
i = m->map_index - 1;
hdr = gpt->map_data;
ent = (void*)((char*)tbl->map_data + i *
le32toh(hdr->hdr_entsz));
le_uuid_dec(ent->ent_type, &uuid);
if (!uuid_is_nil(&type, NULL) &&
!uuid_equal(&type, &uuid, NULL))
continue;
/* Change the primary entry. */
le_uuid_enc(ent->ent_type, &newtype);
hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
hdr->hdr_crc_self = 0;
hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
gpt_write(fd, gpt);
gpt_write(fd, tbl);
hdr = tpg->map_data;
ent = (void*)((char*)lbt->map_data + i *
le32toh(hdr->hdr_entsz));
/* Change the secondary entry. */
le_uuid_enc(ent->ent_type, &newtype);
hdr->hdr_crc_table = htole32(crc32(lbt->map_data,
le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
hdr->hdr_crc_self = 0;
hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));
gpt_write(fd, lbt);
gpt_write(fd, tpg);
printf("partition %d type changed\n", m->map_index);
}
}
int
cmd_type(int argc, char *argv[])
{
char *p;
int ch, fd;
int64_t human_num;
/* Get the type options */
while ((ch = getopt(argc, argv, "ab:i:s:t:T:")) != -1) {
switch(ch) {
case 'a':
if (all > 0)
usage_type();
all = 1;
break;
case 'b':
if (block > 0)
usage_type();
if (dehumanize_number(optarg, &human_num) < 0)
usage_type();
block = human_num;
if (block < 1)
usage_type();
break;
case 'i':
if (entry > 0)
usage_type();
entry = strtoul(optarg, &p, 10);
if (*p != 0 || entry < 1)
usage_type();
break;
case 's':
if (size > 0)
usage_type();
size = strtoll(optarg, &p, 10);
if (*p != 0 || size < 1)
usage_type();
break;
case 't':
if (!uuid_is_nil(&type, NULL))
usage_type();
if (parse_uuid(optarg, &type) != 0)
usage_type();
break;
case 'T':
if (!uuid_is_nil(&newtype, NULL))
usage_type();
if (parse_uuid(optarg, &newtype) != 0)
usage_type();
break;
default:
usage_type();
}
}
if (!all ^
(block > 0 || entry > 0 || size > 0 || !uuid_is_nil(&type, NULL)))
usage_type();
if (uuid_is_nil(&newtype, NULL))
usage_type();
if (argc == optind)
usage_type();
while (optind < argc) {
fd = gpt_open(argv[optind++]);
if (fd == -1) {
warn("unable to open device '%s'", device_name);
continue;
}
chtype(fd);
gpt_close(fd);
}
return (0);
}