[parted-devel] [PATCH 1/1] show GPT UUIDs in JSON output
Arvin Schnell
aschnell at suse.com
Thu Jul 28 10:20:09 BST 2022
Include GPT UUIDs in JSON output.
---
include/parted/disk.in.h | 11 ++++++-
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, 141 insertions(+), 7 deletions(-)
diff --git a/include/parted/disk.in.h b/include/parted/disk.in.h
index 672c4ee..a99cd31 100644
--- a/include/parted/disk.in.h
+++ b/include/parted/disk.in.h
@@ -96,9 +96,11 @@ 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 */
};
#define PED_DISK_TYPE_FIRST_FEATURE PED_DISK_TYPE_EXTENDED
-#define PED_DISK_TYPE_LAST_FEATURE PED_DISK_TYPE_PARTITION_TYPE_UUID
+#define PED_DISK_TYPE_LAST_FEATURE PED_DISK_TYPE_PARTITION_UUID
struct _PedDisk;
struct _PedPartition;
@@ -225,6 +227,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 */
@@ -257,6 +260,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);
@@ -328,6 +333,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;
@@ -364,6 +371,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 0e9e060..70a5512 100644
--- a/libparted/labels/gpt.c
+++ b/libparted/labels/gpt.c
@@ -1538,6 +1538,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)
{
@@ -1723,6 +1741,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)
@@ -1823,9 +1858,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)
};
@@ -1835,7 +1872,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": "<uuid>"/' > out 2>&1 || fail=1
cat <<EOF > exp || fail=1
{
@@ -45,6 +45,7 @@ cat <<EOF > exp || fail=1
"logical-sector-size": 512,
"physical-sector-size": 512,
"label": "gpt",
+ "uuid": "<uuid>",
"max-partitions": 128,
"flags": [
"pmbr_boot"
@@ -63,6 +64,7 @@ cat <<EOF > exp || fail=1
"size": "10240s",
"type": "primary",
"type-uuid": "0fc63daf-8483-4772-8e79-3d69d8477de4",
+ "uuid": "<uuid>",
"name": "test1"
},{
"number": 2,
@@ -71,6 +73,7 @@ cat <<EOF > exp || fail=1
"size": "40960s",
"type": "primary",
"type-uuid": "a19d880f-05fc-4d3b-a006-743f0f84911e",
+ "uuid": "<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": "<uuid>"/' > out 2>&1 || fail=1
cat <<EOF > exp || fail=1
{
@@ -45,6 +45,7 @@ cat <<EOF > exp || fail=1
"logical-sector-size": 512,
"physical-sector-size": 512,
"label": "gpt",
+ "uuid": "<uuid>",
"max-partitions": 128,
"partitions": [
{
@@ -53,7 +54,8 @@ cat <<EOF > exp || fail=1
"end": "20479s",
"size": "10240s",
"type": "primary",
- "type-uuid": "deadfd6d-a4ab-43c4-84e5-0933c84b4f4f"
+ "type-uuid": "deadfd6d-a4ab-43c4-84e5-0933c84b4f4f",
+ "uuid": "<uuid>"
}
]
}
--
2.37.1
More information about the parted-devel
mailing list