[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