fdisk: add new functions for work with fdisk_parttype

- add flags to fdisk_parttype to store more information about the types
 - function for conversion from code to fdisk_parttype
 - function for conversion from string to fdisk_parttype
 - function for conversion from user input to fdisk_parttype
 - support for unknown complex types (e.g. unknown UUIDs)

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2012-09-25 10:23:36 +02:00
parent 7b575fcc3b
commit 559d921eda
7 changed files with 245 additions and 68 deletions

View File

@ -228,19 +228,6 @@ get_sysid(struct fdisk_context *cxt, int i) {
ptes[i].part_table->sys_ind);
}
char *partition_type(struct fdisk_context *cxt, unsigned char type)
{
int i;
struct fdisk_parttype *types = cxt->label->parttypes;
for (i=0; types[i].name; i++)
if (types[i].type == type)
return _(types[i].name);
return NULL;
}
void list_partition_types(struct fdisk_context *cxt)
{
struct fdisk_parttype *types;
@ -581,27 +568,34 @@ read_chars(char *mesg)
return *line_ptr;
}
int
read_hex(struct fdisk_context *cxt)
struct fdisk_parttype *read_partition_type(struct fdisk_context *cxt)
{
int hex;
if (!cxt || !cxt->label || !cxt->label->nparttypes)
return NULL;
while (1)
{
read_char(_("Hex code (type L to list codes): "));
if (tolower(*line_ptr) == 'l')
list_partition_types(cxt);
else if (isxdigit (*line_ptr))
{
hex = 0;
do
hex = hex << 4 | hex_val(*line_ptr++);
while (isxdigit(*line_ptr));
return hex;
}
}
do {
size_t sz;
if (cxt->label->parttypes[0].typestr)
read_chars(_("Partition type (type L to list all types): "));
else
read_chars(_("Hex code (type L to list all codes): "));
sz = strlen(line_ptr);
if (!sz || line_ptr[sz - 1] != '\n' || sz == 1)
continue;
line_ptr[sz - 1] = '\0';
if (tolower(*line_ptr) == 'l')
list_partition_types(cxt);
else
return fdisk_parse_parttype(cxt, line_ptr);
} while (1);
return NULL;
}
unsigned int
read_int_with_suffix(struct fdisk_context *cxt,
unsigned int low, unsigned int dflt, unsigned int high,
@ -862,8 +856,8 @@ static void delete_partition(struct fdisk_context *cxt, int partnum)
static void change_sysid(struct fdisk_context *cxt)
{
const char *temp;
int i, sys, origsys;
int i;
struct fdisk_parttype *t, *org_t;
struct partition *p;
i = get_existing_partition(cxt, 0, partitions);
@ -871,16 +865,18 @@ static void change_sysid(struct fdisk_context *cxt)
if (i == -1)
return;
p = ptes[i].part_table;
origsys = sys = get_sysid(cxt, i);
/* TODO: add get_partition_type(xt, partn) to API */
org_t = t = fdisk_get_parttype_from_code(cxt, get_sysid(cxt, i));
/* if changing types T to 0 is allowed, then
the reverse change must be allowed, too */
if (!sys && disklabel != SGI_LABEL && disklabel != SUN_LABEL && !get_nr_sects(p))
if (!t && disklabel != SGI_LABEL && disklabel != SUN_LABEL && !get_nr_sects(p))
printf(_("Partition %d does not exist yet!\n"), i + 1);
else while (1) {
sys = read_hex (cxt);
t = read_partition_type(cxt);
if (!sys && disklabel != SGI_LABEL && disklabel != SUN_LABEL) {
if (!t && disklabel != SGI_LABEL && disklabel != SUN_LABEL) {
printf(_("Type 0 means free space to many systems\n"
"(but not to Linux). Having partitions of\n"
"type 0 is probably unwise. You can delete\n"
@ -888,8 +884,11 @@ static void change_sysid(struct fdisk_context *cxt)
/* break; */
}
if (!t)
continue;
if (disklabel != SGI_LABEL && disklabel != SUN_LABEL) {
if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
if (IS_EXTENDED (t->type) != IS_EXTENDED (p->sys_ind)) {
printf(_("You cannot change a partition into"
" an extended one or vice versa\n"
"Delete it first.\n"));
@ -897,42 +896,51 @@ static void change_sysid(struct fdisk_context *cxt)
}
}
if (sys < 256) {
if (disklabel == SUN_LABEL && i == 2 && sys != SUN_TAG_BACKUP)
/* TODO: add set_partition_type(cxt, npart, type) API */
if (t->type < 256) {
if (disklabel == SUN_LABEL && i == 2 && t->type != SUN_TAG_BACKUP)
printf(_("Consider leaving partition 3 "
"as Whole disk (5),\n"
"as SunOS/Solaris expects it and "
"even Linux likes it.\n\n"));
if (disklabel == SGI_LABEL && ((i == 10 && sys != ENTIRE_DISK)
|| (i == 8 && sys != 0)))
if (disklabel == SGI_LABEL && ((i == 10 && t->type != ENTIRE_DISK)
|| (i == 8 && t->type != 0)))
printf(_("Consider leaving partition 9 "
"as volume header (0),\nand "
"partition 11 as entire volume (6), "
"as IRIX expects it.\n\n"));
if (sys == origsys)
break;
if (t == org_t)
goto nochange;
if (disklabel == SUN_LABEL) {
ptes[i].changed = sun_change_sysid(cxt, i, sys);
ptes[i].changed = sun_change_sysid(cxt, i, t->type);
} else
if (disklabel == SGI_LABEL) {
ptes[i].changed = sgi_change_sysid(cxt, i, sys);
ptes[i].changed = sgi_change_sysid(cxt, i, t->type);
} else {
p->sys_ind = sys;
p->sys_ind = t->type;
ptes[i].changed = 1;
}
temp = partition_type(cxt, sys) ? : _("Unknown");
if (ptes[i].changed)
printf (_("Changed system type of partition %d "
"to %x (%s)\n"), i + 1, sys, temp);
else
printf (_("System type of partition %d is unchanged: "
"%x (%s)\n"), i + 1, sys, temp);
if (is_dos_partition(origsys) ||
is_dos_partition(sys))
printf (_("Changed type of partition '%s' to '%s'\n"),
org_t ? org_t->name : _("Unknown"),
t ? t->name : _("Unknown"));
else {
nochange:
printf (_("Type of partition %d is unchanged: %s\n"),
i + 1,
org_t ? org_t->name : _("Unknown"));
}
if (is_dos_partition(t->type) || is_dos_partition(t->type))
dos_changed = 1;
break;
}
}
fdisk_free_parttype(t);
fdisk_free_parttype(org_t);
}
/* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
@ -1180,7 +1188,6 @@ fix_partition_table_order(void) {
static void
list_table(struct fdisk_context *cxt, int xtra) {
struct partition *p;
char *type;
int i, w;
if (disklabel == SUN_LABEL) {
@ -1225,6 +1232,8 @@ list_table(struct fdisk_context *cxt, int xtra) {
unsigned int psects = get_nr_sects(p);
unsigned int pblocks = psects;
unsigned int podd = 0;
struct fdisk_parttype *type =
fdisk_get_parttype_from_code(cxt, p->sys_ind);
if (cxt->sector_size < 1024) {
pblocks /= (1024 / cxt->sector_size);
@ -1242,8 +1251,7 @@ list_table(struct fdisk_context *cxt, int xtra) {
- (psects ? 1 : 0)),
/* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
/* type id */ p->sys_ind,
/* type name */ (type = partition_type(cxt, p->sys_ind)) ?
type : _("Unknown"));
/* type name */ type ? type->name : _("Unknown"));
check_consistency(cxt, p, i);
check_alignment(cxt, get_partition_start(pe), i);
}
@ -1344,7 +1352,10 @@ void print_partition_size(struct fdisk_context *cxt,
{
char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE,
(uint64_t)(stop - start + 1) * cxt->sector_size);
printf(_("Partition %d of type %s and of size %s is set\n"), num, partition_type(cxt, sysid), str);
struct fdisk_parttype *t = fdisk_get_parttype_from_code(cxt, sysid);
printf(_("Partition %d of type %s and of size %s is set\n"),
num, t ? t->name : _("Unknown"), str);
free(str);
}

View File

@ -104,10 +104,22 @@ typedef unsigned long long sector_t;
*/
struct fdisk_parttype {
unsigned int type; /* type as number or zero */
char *name; /* description */
const char *name; /* description */
char *typestr; /* type as string or NULL */
unsigned int flags; /* FDISK_PARTTYPE_* flags */
};
enum {
FDISK_PARTTYPE_UNKNOWN = (1 << 1),
FDISK_PARTTYPE_INVISIBLE = (1 << 2),
FDISK_PARTTYPE_ALLOCATED = (1 << 3)
};
#define fdisk_parttype_is_unknown(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_UNKNONW))
#define fdisk_parttype_is_invisible(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_INVISIBLE))
#define fdisk_parttype_is_allocated(_x) ((_x) && ((_x)->flags & FDISK_PARTTYPE_ALLOCATED))
/*
* Legacy CHS based geometry
*/
@ -148,6 +160,7 @@ struct fdisk_label {
/* array with partition types */
struct fdisk_parttype *parttypes;
size_t nparttypes; /* number of items in parttypes[] */
/* probe disk label */
int (*probe)(struct fdisk_context *cxt);
@ -189,6 +202,15 @@ extern int fdisk_write_disklabel(struct fdisk_context *cxt);
extern int fdisk_verify_disklabel(struct fdisk_context *cxt);
extern int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name);
extern size_t fdisk_get_nparttypes(struct fdisk_context *cxt);
extern struct fdisk_parttype *fdisk_get_parttype_from_code(struct fdisk_context *cxt,
unsigned int code);
extern struct fdisk_parttype *fdisk_get_parttype_from_string(struct fdisk_context *cxt,
const char *str);
extern struct fdisk_parttype *fdisk_parse_parttype(struct fdisk_context *cxt, const char *str);
extern void fdisk_free_parttype(struct fdisk_parttype *type);
/* prototypes for fdisk.c */
extern char *line_ptr;
extern int partitions;
@ -204,7 +226,7 @@ extern int get_partition(struct fdisk_context *cxt, int warn, int max);
extern void list_partition_types(struct fdisk_context *cxt);
extern int read_line (int *asked);
extern char read_char(char *mesg);
extern int read_hex(struct fdisk_context *cxt);
extern struct fdisk_parttype *read_partition_type(struct fdisk_context *cxt);
extern void reread_partition_table(struct fdisk_context *cxt, int leave);
extern struct partition *get_part_table(int);
extern unsigned int read_int(struct fdisk_context *cxt,

View File

@ -562,9 +562,15 @@ static void
xbsd_change_fstype (struct fdisk_context *cxt)
{
int i;
struct fdisk_parttype *t;
i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
xbsd_dlabel.d_partitions[i].p_fstype = read_hex (cxt);
t = read_partition_type(cxt);
if (t) {
xbsd_dlabel.d_partitions[i].p_fstype = t->type;
fdisk_free_parttype(t);
}
}
static int
@ -841,6 +847,7 @@ const struct fdisk_label bsd_label =
{
.name = "bsd",
.parttypes = xbsd_fstypes,
.nparttypes = ARRAY_SIZE(xbsd_fstypes),
.probe = osf_probe_label,
.write = xbsd_write_disklabel,

View File

@ -829,6 +829,8 @@ const struct fdisk_label dos_label =
{
.name = "dos",
.parttypes = dos_parttypes,
.nparttypes = ARRAY_SIZE(dos_parttypes),
.probe = dos_probe_label,
.write = dos_write_disklabel,
.verify = dos_verify_disklabel,

View File

@ -164,7 +164,6 @@ void
sgi_list_table(struct fdisk_context *cxt, int xtra) {
int i, w;
int kpi = 0; /* kernel partition ID */
char *type;
w = strlen(cxt->dev_path);
@ -195,6 +194,9 @@ sgi_list_table(struct fdisk_context *cxt, int xtra) {
if (sgi_get_num_sectors(cxt, i) || debug) {
uint32_t start = sgi_get_start_sector(cxt, i);
uint32_t len = sgi_get_num_sectors(cxt, i);
struct fdisk_parttype *t =
fdisk_get_parttype_from_code(cxt, sgi_get_sysid(cxt, i));
kpi++; /* only count nonempty partitions */
printf(
"%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
@ -205,9 +207,8 @@ sgi_list_table(struct fdisk_context *cxt, int xtra) {
/* start */ (long) scround(start),
/* end */ (long) scround(start+len)-1,
/* no odd flag on end */ (long) len,
/* type id */ sgi_get_sysid(cxt, i),
/* type name */ (type = partition_type(cxt, sgi_get_sysid(cxt, i)))
? type : _("Unknown"));
/* type id */ t ? t->type : sgi_get_sysid(cxt, i),
/* type name */ t ? t->name : _("Unknown"));
}
}
printf(_("----- Bootinfo -----\nBootfile: %s\n"
@ -899,6 +900,7 @@ const struct fdisk_label sgi_label =
{
.name = "sgi",
.parttypes = sgi_parttypes,
.nparttypes = ARRAY_SIZE(sgi_parttypes),
.probe = sgi_probe_label,
.write = sgi_write_disklabel,

View File

@ -538,7 +538,6 @@ int sun_change_sysid(struct fdisk_context *cxt, int i, uint16_t sys)
void sun_list_table(struct fdisk_context *cxt, int xtra)
{
int i, w;
char *type;
w = strlen(cxt->dev_path);
if (xtra)
@ -573,6 +572,8 @@ void sun_list_table(struct fdisk_context *cxt, int xtra)
if (part->num_sectors) {
uint32_t start = SSWAP32(part->start_cylinder) * cxt->geom.heads * cxt->geom.sectors;
uint32_t len = SSWAP32(part->num_sectors);
struct fdisk_parttype *t = fdisk_get_parttype_from_code(cxt, SSWAP16(tag->tag));
printf(
"%s %c%c %9lu %9lu %9lu%c %2x %s\n",
/* device */ partname(cxt->dev_path, i+1, w),
@ -582,8 +583,7 @@ void sun_list_table(struct fdisk_context *cxt, int xtra)
/* end */ (unsigned long) scround(start+len),
/* odd flag on end */ (unsigned long) len / 2, len & 1 ? '+' : ' ',
/* type id */ SSWAP16(tag->tag),
/* type name */ (type = partition_type(cxt, SSWAP16(tag->tag)))
? type : _("Unknown"));
/* type name */ t ? t->name : _("Unknown"));
}
}
}
@ -653,6 +653,7 @@ const struct fdisk_label sun_label =
{
.name = "sun",
.parttypes = sun_parttypes,
.nparttypes = ARRAY_SIZE(sun_parttypes),
.probe = sun_probe_label,
.write = sun_write_disklabel,

View File

@ -20,6 +20,7 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#ifdef HAVE_LIBBLKID
#include <blkid.h>
#endif
@ -521,3 +522,134 @@ void fdisk_free_context(struct fdisk_context *cxt)
free(cxt->firstsector);
free(cxt);
}
/*
* fdisk_get_nparttypes:
*
* Returns: number of partition types supported by the current label
*/
size_t fdisk_get_nparttypes(struct fdisk_context *cxt)
{
if (!cxt || !cxt->label)
return 0;
return cxt->label->nparttypes;
}
struct fdisk_parttype *fdisk_get_parttype_from_code(
struct fdisk_context *cxt,
unsigned int code)
{
size_t i;
if (!fdisk_get_nparttypes(cxt))
return NULL;
for (i = 0; i < cxt->label->nparttypes; i++)
if (cxt->label->parttypes[i].type == code)
return &cxt->label->parttypes[i];
return NULL;
}
struct fdisk_parttype *fdisk_get_parttype_from_string(
struct fdisk_context *cxt,
const char *str)
{
size_t i;
if (!fdisk_get_nparttypes(cxt))
return NULL;
for (i = 0; i < cxt->label->nparttypes; i++)
if (cxt->label->parttypes[i].typestr
&&strcasecmp(cxt->label->parttypes[i].typestr, str) == 0)
return &cxt->label->parttypes[i];
return NULL;
}
static struct fdisk_parttype *mk_unknown_partype(unsigned int type, const char *typestr)
{
struct fdisk_parttype *t;
t = calloc(1, sizeof(*t));
if (!t)
return NULL;
if (typestr) {
t->typestr = strdup(typestr);
if (!t->typestr) {
free(t);
return NULL;
}
}
t->name = _("unknown");
t->type = type;
t->flags |= FDISK_PARTTYPE_UNKNOWN | FDISK_PARTTYPE_ALLOCATED;
return t;
}
/*
* fdisk_parse_parttype
* @cxt: fdisk context
* @str: string
*
* Returns pointer to static table of the partition types, or newly allocated
* partition type if @unknown is not NULL and partition type in @str is
* unknown, or NULL in case of error.
*/
struct fdisk_parttype *fdisk_parse_parttype(
struct fdisk_context *cxt,
const char *str)
{
struct fdisk_parttype *types, *ret;
unsigned int code = 0;
char *typestr = NULL, *end = NULL;
if (!fdisk_get_nparttypes(cxt))
return NULL;
types = cxt->label->parttypes;
if (types[0].typestr == NULL && isxdigit(*str)) {
errno = 0;
code = strtol(str, &end, 16);
if (errno || *end != '\0')
return NULL;
ret = fdisk_get_parttype_from_code(cxt, code);
if (ret)
return ret;
} else {
int i;
/* maybe specified by type string (e.g. UUID) */
ret = fdisk_get_parttype_from_string(cxt, str);
if (ret)
return ret;
/* maybe specified by order number */
errno = 0;
i = strtol(str, &end, 0);
if (errno == 0 && *end == '\0' && i < (int) fdisk_get_nparttypes(cxt))
return &types[i];
}
return mk_unknown_partype(code, typestr);
}
/*
* fdisk_free_parttype:
*
* Free the @type.
*/
void fdisk_free_parttype(struct fdisk_parttype *t)
{
if (t && (t->flags & FDISK_PARTTYPE_ALLOCATED)) {
free(t->typestr);
free(t);
}
}