diff options
author | Karel Zak | 2013-10-16 15:28:32 +0200 |
---|---|---|
committer | Karel Zak | 2013-10-23 10:46:10 +0200 |
commit | c83f772efde4f476d313d640ca9640fb52733fd0 (patch) | |
tree | fa37f7e5c114e81e823619612625718c77932f29 | |
parent | libfdisk: (dos) be more verbose when change bootable flag (diff) | |
download | kernel-qcow2-util-linux-c83f772efde4f476d313d640ca9640fb52733fd0.tar.gz kernel-qcow2-util-linux-c83f772efde4f476d313d640ca9640fb52733fd0.tar.xz kernel-qcow2-util-linux-c83f772efde4f476d313d640ca9640fb52733fd0.zip |
libfdisk: support extended attributes modification
* GPT attributes defined by standard (e.g. legacy boot etc.)
* attributes (bits 48-63) reserved for GUID specific attributes (used for example
by MS Windows)
Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r-- | libfdisk/src/gpt.c | 123 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h | 7 |
2 files changed, 130 insertions, 0 deletions
diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c index ec58c0098..6e7b74d9f 100644 --- a/libfdisk/src/gpt.c +++ b/libfdisk/src/gpt.c @@ -75,6 +75,9 @@ struct gpt_attr { uint64_t guid_secific:16; } __attribute__ ((packed)); + + + /* The GPT Partition entry array contains an array of GPT entries. */ struct gpt_entry { struct gpt_guid type; /* purpose and type of the partition */ @@ -1168,6 +1171,36 @@ static char *encode_to_utf8(unsigned char *src, size_t count) return dest; } +/* convert GUID Specific attributes to string, result is a list of the enabled + * bits (e.g. "60,62,63" for enabled bits 60, 62 and 63). + * + * Returns newly allocated string or NULL in case of error. + * + * see struct gpt_attr definition for more details. + */ +static char *guid_attrs_to_string(struct gpt_attr *attr, char **res) +{ + char *bits = (char *) attr, *end; + size_t i, count = 0, len; + + end = *res = calloc(1, 16 * 3 + 6); /* three bytes for one bit + \0 */ + if (!*res) + return NULL; + + for (i = 48; i < 64; i++) { + if (!isset(bits, i)) + continue; + count++; + if (count > 1) + len = snprintf(end, 4, ",%zu", i); + else + len = snprintf(end, 8, "GUID:%zu", i); + end += len; + } + + return *res; +} + /* * List label partitions. * This function must currently exist to comply with standard fdisk @@ -1215,6 +1248,7 @@ static int gpt_list_disklabel(struct fdisk_context *cxt) if (fdisk_context_display_details(cxt)) { tt_define_column(tb, _("UUID"), 36, 0); tt_define_column(tb, _("Name"), 0.2, trunc); + tt_define_column(tb, _("Attributes"), 0, 0); } for (i = 0; i < le32_to_cpu(h->npartition_entries); i++) { @@ -1258,6 +1292,7 @@ static int gpt_list_disklabel(struct fdisk_context *cxt) /* expert menu column(s) */ if (fdisk_context_display_details(cxt)) { + char *buf = NULL; char *name = encode_to_utf8( (unsigned char *)e->name, sizeof(e->name)); @@ -1266,6 +1301,13 @@ static int gpt_list_disklabel(struct fdisk_context *cxt) tt_line_set_data(ln, 5, strdup(u_str)); if (name) tt_line_set_data(ln, 6, name); + if (asprintf(&p, "%s%s%s%s", + e->attr.required_to_function ? "Required " : "", + e->attr.legacy_bios_bootable ? "LegacyBoot " : "", + e->attr.no_blockio_protocol ? "NoBlockIO " : "", + guid_attrs_to_string(&e->attr, &buf)) > 0) + tt_line_set_data(ln, 7, p); + free(buf); } fdisk_warn_alignment(cxt, start, i); @@ -2061,6 +2103,86 @@ int fdisk_gpt_partition_set_name(struct fdisk_context *cxt, size_t i) return 0; } +static int gpt_toggle_partition_flag( + struct fdisk_context *cxt, + size_t i, + unsigned long flag) +{ + struct fdisk_gpt_label *gpt; + struct gpt_entry *e; + + assert(cxt); + assert(cxt->label); + assert(fdisk_is_disklabel(cxt, GPT)); + + DBG(LABEL, dbgprint("GPT entry attribute change requested partno=%zu", i)); + + gpt = self_label(cxt); + + if ((uint32_t) i >= le32_to_cpu(gpt->pheader->npartition_entries)) + return -EINVAL; + + e = &gpt->ents[i]; + + switch (flag) { + case GPT_FLAG_REQUIRED: + e->attr.required_to_function = !e->attr.required_to_function; + fdisk_label_set_changed(cxt->label, 1); + fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, + e->attr.required_to_function ? + _("The RequiredPartiton flag on partition %zu is enabled now.") : + _("The RequiredPartiton flag on partition %zu is disabled now."), + i + 1); + break; + case GPT_FLAG_NOBLOCK: + e->attr.no_blockio_protocol = !e->attr.no_blockio_protocol; + fdisk_label_set_changed(cxt->label, 1); + fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, + e->attr.no_blockio_protocol ? + _("The NoBlockIOProtocol flag on partition %zu is enabled now.") : + _("The NoBlockIOProtocol flag on partition %zu is disabled now."), + i + 1); + break; + case GPT_FLAG_LEGACYBOOT: + e->attr.legacy_bios_bootable = !e->attr.legacy_bios_bootable; + fdisk_label_set_changed(cxt->label, 1); + fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, + e->attr.legacy_bios_bootable ? + _("The LegacyBIOSBootable flag on partition %zu is enabled now.") : + _("The LegacyBIOSBootable flag on partition %zu is disabled now."), + i + 1); + break; + case GPT_FLAG_GUIDSPECIFIC: + { + char *attrs = (char *) &e->attr; + uint64_t bit = 0; + int rc = fdisk_ask_number(cxt, 48, 48, 63, + _("Enter GUID specific bit"), + &bit); + if (rc) + return rc; + if (!isset(attrs, bit)) + setbit(attrs, bit); + else + clrbit(attrs, bit); + + fdisk_label_set_changed(cxt->label, 1); + fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, + isset(attrs, bit) ? + _("The GUID specific bit %ju on partition %zu is enabled now.") : + _("The GUID specific bit %ju on partition %zu is disabled now."), + bit, i + 1); + break; + } + default: + return 1; + } + + gpt_recompute_crc(gpt->pheader, gpt->ents); + gpt_recompute_crc(gpt->bheader, gpt->ents); + + return 0; +} /* * Deinitialize fdisk-specific variables @@ -2096,6 +2218,7 @@ static const struct fdisk_label_operations gpt_operations = .part_delete = gpt_delete_partition, .part_get_type = gpt_get_partition_type, .part_set_type = gpt_set_partition_type, + .part_toggle_flag = gpt_toggle_partition_flag, .part_get_status = gpt_get_partition_status, diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h index 835691be4..77892d271 100644 --- a/libfdisk/src/libfdisk.h +++ b/libfdisk/src/libfdisk.h @@ -190,6 +190,13 @@ extern int fdisk_sgi_set_bootfile(struct fdisk_context *cxt); extern int fdisk_sgi_create_info(struct fdisk_context *cxt); /* gpt */ +enum { + GPT_FLAG_REQUIRED = 1, + GPT_FLAG_NOBLOCK, + GPT_FLAG_LEGACYBOOT, + GPT_FLAG_GUIDSPECIFIC +}; + extern int fdisk_gpt_partition_set_uuid(struct fdisk_context *cxt, size_t i); extern int fdisk_gpt_partition_set_name(struct fdisk_context *cxt, size_t i); |