From daceb2d6a76a66254168effcc2cd0d5f4fadf946 Mon Sep 17 00:00:00 2001 From: Arvin Schnell Date: Thu, 28 Jul 2022 09:20:09 +0000 Subject: parted: Add display of GPT UUIDs in JSON output This adds 2 new disk type features, one for the whole disk UUID and another for the per-partition UUID. It adds ped_disk_get_uuid and ped_partition_get_uuid functions to retrieve them. It adds them to the JSON output on GPT disklabeled disks as "uuid" in the disk and partitions sections of the JSON output. Signed-off-by: Brian C. Lane --- include/parted/disk.in.h | 13 ++++++++-- libparted/disk.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ libparted/labels/gpt.c | 40 +++++++++++++++++++++++++++++- parted/parted.c | 18 ++++++++++++++ tests/t0800-json-gpt.sh | 7 ++++-- tests/t0900-type-gpt.sh | 8 +++--- 6 files changed, 142 insertions(+), 8 deletions(-) diff --git a/include/parted/disk.in.h b/include/parted/disk.in.h index 715637d..f649bcc 100644 --- a/include/parted/disk.in.h +++ b/include/parted/disk.in.h @@ -98,10 +98,12 @@ enum _PedDiskTypeFeature { PED_DISK_TYPE_PARTITION_NAME=2, /**< supports partition names */ PED_DISK_TYPE_PARTITION_TYPE_ID=4, /**< supports partition type-ids */ PED_DISK_TYPE_PARTITION_TYPE_UUID=8, /**< supports partition type-uuids */ + PED_DISK_TYPE_DISK_UUID=16, /**< supports disk uuids */ + PED_DISK_TYPE_PARTITION_UUID=32, /**< supports partition uuids */ }; // NOTE: DO NOT define using enums -#define PED_DISK_TYPE_FIRST_FEATURE 1 // PED_DISK_TYPE_EXTENDED -#define PED_DISK_TYPE_LAST_FEATURE 8 // PED_DISK_TYPE_PARTITION_TYPE_UUID +#define PED_DISK_TYPE_FIRST_FEATURE 1 // PED_DISK_TYPE_EXTENDED +#define PED_DISK_TYPE_LAST_FEATURE 32 // PED_DISK_TYPE_PARTITION_UUID struct _PedDisk; struct _PedPartition; @@ -228,6 +230,7 @@ struct _PedDiskOps { int (*disk_is_flag_available) ( const PedDisk *disk, PedDiskFlag flag); + uint8_t* (*disk_get_uuid) (const PedDisk* disk); /** \todo add label guessing op here */ /* partition operations */ @@ -260,6 +263,8 @@ struct _PedDiskOps { int (*partition_set_type_uuid) (PedPartition* part, const uint8_t* uuid); uint8_t* (*partition_get_type_uuid) (const PedPartition* part); + uint8_t* (*partition_get_uuid) (const PedPartition* part); + int (*partition_align) (PedPartition* part, const PedConstraint* constraint); int (*partition_enumerate) (PedPartition* part); @@ -331,6 +336,8 @@ extern int ped_disk_set_flag(PedDisk *disk, PedDiskFlag flag, int state); extern int ped_disk_get_flag(const PedDisk *disk, PedDiskFlag flag); extern int ped_disk_is_flag_available(const PedDisk *disk, PedDiskFlag flag); +extern uint8_t* ped_disk_get_uuid (const PedDisk* disk); + extern const char *ped_disk_flag_get_name(PedDiskFlag flag); extern PedDiskFlag ped_disk_flag_get_by_name(const char *name); extern PedDiskFlag ped_disk_flag_next(PedDiskFlag flag) _GL_ATTRIBUTE_CONST; @@ -367,6 +374,8 @@ extern uint8_t ped_partition_get_type_id (const PedPartition* part); extern int ped_partition_set_type_uuid (PedPartition* part, const uint8_t* uuid); extern uint8_t* ped_partition_get_type_uuid (const PedPartition* part); +extern uint8_t* ped_partition_get_uuid (const PedPartition* part); + extern int ped_partition_is_busy (const PedPartition* part); extern char* ped_partition_get_path (const PedPartition* part); diff --git a/libparted/disk.c b/libparted/disk.c index a961d65..0ed3d91 100644 --- a/libparted/disk.c +++ b/libparted/disk.c @@ -886,6 +886,37 @@ ped_disk_flag_next(PedDiskFlag flag) return (flag + 1) % (PED_DISK_LAST_FLAG + 1); } +static int +_assert_disk_uuid_feature (const PedDiskType* disk_type) +{ + if (!ped_disk_type_check_feature ( + disk_type, PED_DISK_TYPE_DISK_UUID)) { + ped_exception_throw ( + PED_EXCEPTION_ERROR, + PED_EXCEPTION_CANCEL, + "%s disk labels do not support disk uuids.", + disk_type->name); + return 0; + } + return 1; +} + +/** + * Get the uuid of the disk \p disk. This will only work if the disk label + * supports it. + */ +uint8_t* +ped_disk_get_uuid (const PedDisk *disk) +{ + PED_ASSERT (disk != NULL); + + if (!_assert_disk_uuid_feature (disk->type)) + return NULL; + + PED_ASSERT (disk->type->ops->disk_get_uuid != NULL); + return disk->type->ops->disk_get_uuid (disk); +} + /** * \internal We turned a really nasty bureaucracy problem into an elegant maths * problem :-) Basically, there are some constraints to a partition's @@ -1488,6 +1519,21 @@ _assert_partition_type_uuid_feature (const PedDiskType* disk_type) return 1; } +static int +_assert_partition_uuid_feature (const PedDiskType* disk_type) +{ + if (!ped_disk_type_check_feature ( + disk_type, PED_DISK_TYPE_PARTITION_UUID)) { + ped_exception_throw ( + PED_EXCEPTION_ERROR, + PED_EXCEPTION_CANCEL, + "%s disk labels do not support partition uuids.", + disk_type->name); + return 0; + } + return 1; +} + /** * Sets the name of a partition. * @@ -1612,6 +1658,24 @@ ped_partition_get_type_uuid (const PedPartition *part) return part->disk->type->ops->partition_get_type_uuid (part); } +/** + * Get the uuid of the partition \p part. This will only work if the disk label + * supports it. + */ +uint8_t* +ped_partition_get_uuid (const PedPartition *part) +{ + PED_ASSERT (part != NULL); + PED_ASSERT (part->disk != NULL); + PED_ASSERT (ped_partition_is_active (part)); + + if (!_assert_partition_uuid_feature (part->disk->type)) + return NULL; + + PED_ASSERT (part->disk->type->ops->partition_get_uuid != NULL); + return part->disk->type->ops->partition_get_uuid (part); +} + /** @} */ /** diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c index 8e6a37d..1993863 100644 --- a/libparted/labels/gpt.c +++ b/libparted/labels/gpt.c @@ -1576,6 +1576,24 @@ gpt_disk_is_flag_available(const PedDisk *disk, PedDiskFlag flag) } } +static uint8_t* +gpt_disk_get_uuid (const PedDisk *disk) +{ + GPTDiskData *gpt_disk_data = disk->disk_specific; + + efi_guid_t uuid = gpt_disk_data->uuid; + + /* uuid is always LE, while uint8_t is always kind of BE */ + + uuid.time_low = PED_SWAP32(uuid.time_low); + uuid.time_mid = PED_SWAP16(uuid.time_mid); + uuid.time_hi_and_version = PED_SWAP16(uuid.time_hi_and_version); + + uint8_t *buf = ped_malloc(sizeof (uuid_t)); + memcpy(buf, &uuid, sizeof (uuid_t)); + return buf; +} + static int gpt_disk_get_flag (const PedDisk *disk, PedDiskFlag flag) { @@ -1764,6 +1782,23 @@ gpt_partition_get_type_uuid (const PedPartition *part) return buf; } +static uint8_t* +gpt_partition_get_uuid (const PedPartition *part) +{ + const GPTPartitionData *gpt_part_data = part->disk_specific; + + efi_guid_t uuid = gpt_part_data->uuid; + + /* uuid is always LE, while uint8_t is always kind of BE */ + + uuid.time_low = PED_SWAP32(uuid.time_low); + uuid.time_mid = PED_SWAP16(uuid.time_mid); + uuid.time_hi_and_version = PED_SWAP16(uuid.time_hi_and_version); + + uint8_t *buf = ped_malloc(sizeof (uuid_t)); + memcpy(buf, &uuid, sizeof (uuid_t)); + return buf; +} static int gpt_get_max_primary_partition_count (const PedDisk *disk) @@ -1864,9 +1899,11 @@ static PedDiskOps gpt_disk_ops = partition_get_type_id: NULL, partition_set_type_uuid: gpt_partition_set_type_uuid, partition_get_type_uuid: gpt_partition_get_type_uuid, + partition_get_uuid: gpt_partition_get_uuid, disk_set_flag: gpt_disk_set_flag, disk_get_flag: gpt_disk_get_flag, disk_is_flag_available: gpt_disk_is_flag_available, + disk_get_uuid: gpt_disk_get_uuid, PT_op_function_initializers (gpt) }; @@ -1876,7 +1913,8 @@ static PedDiskType gpt_disk_type = next: NULL, name: "gpt", ops: &gpt_disk_ops, - features: PED_DISK_TYPE_PARTITION_NAME | PED_DISK_TYPE_PARTITION_TYPE_UUID + features: PED_DISK_TYPE_PARTITION_NAME | PED_DISK_TYPE_PARTITION_TYPE_UUID | + PED_DISK_TYPE_DISK_UUID | PED_DISK_TYPE_PARTITION_UUID }; void diff --git a/parted/parted.c b/parted/parted.c index 36c39c7..84187b7 100644 --- a/parted/parted.c +++ b/parted/parted.c @@ -1215,6 +1215,14 @@ _print_disk_info (const PedDevice *dev, const PedDisk *diskp) ul_jsonwrt_value_u64 (&json, "physical-sector-size", dev->phys_sector_size); ul_jsonwrt_value_s (&json, "label", pt_name); if (diskp) { + bool has_disk_uuid = ped_disk_type_check_feature (diskp->type, PED_DISK_TYPE_DISK_UUID); + if (has_disk_uuid) { + uint8_t* uuid = ped_disk_get_uuid (diskp); + static char buf[UUID_STR_LEN]; + uuid_unparse_lower (uuid, buf); + ul_jsonwrt_value_s (&json, "uuid", buf); + free (uuid); + } ul_jsonwrt_value_u64 (&json, "max-partitions", ped_disk_get_max_primary_partition_count(diskp)); disk_print_flags_json (diskp); @@ -1360,6 +1368,8 @@ do_print (PedDevice** dev, PedDisk** diskp) PED_DISK_TYPE_PARTITION_TYPE_ID); bool has_type_uuid = ped_disk_type_check_feature ((*diskp)->type, PED_DISK_TYPE_PARTITION_TYPE_UUID); + bool has_part_uuid = ped_disk_type_check_feature ((*diskp)->type, + PED_DISK_TYPE_PARTITION_UUID); PedPartition* part; if (opt_output_mode == HUMAN) { @@ -1512,6 +1522,14 @@ do_print (PedDevice** dev, PedDisk** diskp) free (type_uuid); } + if (has_part_uuid) { + uint8_t* uuid = ped_partition_get_uuid (part); + static char buf[UUID_STR_LEN]; + uuid_unparse_lower (uuid, buf); + ul_jsonwrt_value_s (&json, "uuid", buf); + free (uuid); + } + if (has_name) { name = ped_partition_get_name (part); if (strcmp (name, "") != 0) diff --git a/tests/t0800-json-gpt.sh b/tests/t0800-json-gpt.sh index 354c0bd..f6a3fb9 100755 --- a/tests/t0800-json-gpt.sh +++ b/tests/t0800-json-gpt.sh @@ -32,8 +32,8 @@ parted --script "$dev" mkpart "test1" ext4 10% 20% > out 2>&1 || fail=1 parted --script "$dev" mkpart "test2" xfs 20% 60% > out 2>&1 || fail=1 parted --script "$dev" set 2 raid on > out 2>&1 || fail=1 -# print with json format -parted --script --json "$dev" unit s print free > out 2>&1 || fail=1 +# print with json format, replace non-deterministic uuids +parted --script --json "$dev" unit s print free | sed -E 's/"uuid": "[0-9a-f-]{36}"/"uuid": ""/' > out 2>&1 || fail=1 cat < exp || fail=1 { @@ -45,6 +45,7 @@ cat < exp || fail=1 "logical-sector-size": 512, "physical-sector-size": 512, "label": "gpt", + "uuid": "", "max-partitions": 128, "flags": [ "pmbr_boot" @@ -63,6 +64,7 @@ cat < exp || fail=1 "size": "10240s", "type": "primary", "type-uuid": "0fc63daf-8483-4772-8e79-3d69d8477de4", + "uuid": "", "name": "test1" },{ "number": 2, @@ -71,6 +73,7 @@ cat < exp || fail=1 "size": "40960s", "type": "primary", "type-uuid": "a19d880f-05fc-4d3b-a006-743f0f84911e", + "uuid": "", "name": "test2", "flags": [ "raid" diff --git a/tests/t0900-type-gpt.sh b/tests/t0900-type-gpt.sh index 2014820..03febba 100755 --- a/tests/t0900-type-gpt.sh +++ b/tests/t0900-type-gpt.sh @@ -32,8 +32,8 @@ parted --script "$dev" mkpart "''" "linux-swap" 10% 20% > out 2>&1 || fail=1 # set type-uuid parted --script "$dev" type 1 "deadfd6d-a4ab-43c4-84e5-0933c84b4f4f" || fail=1 -# print with json format -parted --script --json "$dev" unit s print > out 2>&1 || fail=1 +# print with json format, replace non-deterministic uuids +parted --script --json "$dev" unit s print | sed -E 's/"uuid": "[0-9a-f-]{36}"/"uuid": ""/' > out 2>&1 || fail=1 cat < exp || fail=1 { @@ -45,6 +45,7 @@ cat < exp || fail=1 "logical-sector-size": 512, "physical-sector-size": 512, "label": "gpt", + "uuid": "", "max-partitions": 128, "partitions": [ { @@ -53,7 +54,8 @@ cat < exp || fail=1 "end": "20479s", "size": "10240s", "type": "primary", - "type-uuid": "deadfd6d-a4ab-43c4-84e5-0933c84b4f4f" + "type-uuid": "deadfd6d-a4ab-43c4-84e5-0933c84b4f4f", + "uuid": "" } ] } -- cgit v1.2.1