]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
repart: Add support for setting a partition's UUID to zero
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 4 Sep 2022 16:53:25 +0000 (18:53 +0200)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 5 Sep 2022 14:19:41 +0000 (23:19 +0900)
This is useful when we need to fill in the UUID later, such as when
using verity partitions.

man/repart.d.xml
src/partition/repart.c
test/units/testsuite-58.sh

index d9ec521160ba7f3e39ddb1a3fbf5c50700e4169f..6a0a6b32b2e4705eb8d90915d566b2801a962b3d 100644 (file)
         <listitem><para>The UUID to assign to the partition if none is assigned yet. Note that this
         setting is not used for matching. It is also not used when a UUID is already set for an existing
         partition. It is thus only used when a partition is newly created or when an existing one had a
-        all-zero UUID set. If not specified a UUID derived from the partition type is automatically
-        used.</para></listitem>
+        all-zero UUID set. If set to <literal>null</literal>, the UUID is set to all zeroes. If not specified
+        a UUID derived from the partition type is automatically used.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 1d949696a4f9857a5e2bab67f0a2d61795455168..ea8468dc29b2a923c765979d8ae9c9bb480b02bb 100644 (file)
@@ -138,6 +138,7 @@ struct Partition {
 
         sd_id128_t type_uuid;
         sd_id128_t current_uuid, new_uuid;
+        bool new_uuid_is_set;
         char *current_label, *new_label;
 
         bool dropped;
@@ -1313,12 +1314,50 @@ static int config_parse_gpt_flags(
         return 0;
 }
 
+static int config_parse_uuid(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        Partition *partition = ASSERT_PTR(data);
+        int r;
+
+        if (isempty(rvalue)) {
+                partition->new_uuid = SD_ID128_NULL;
+                partition->new_uuid_is_set = false;
+                return 0;
+        }
+
+        if (streq(rvalue, "null")) {
+                partition->new_uuid = SD_ID128_NULL;
+                partition->new_uuid_is_set = true;
+                return 0;
+        }
+
+        r = sd_id128_from_string(rvalue, &partition->new_uuid);
+        if (r < 0) {
+                log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse 128bit ID/UUID, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        partition->new_uuid_is_set = true;
+
+        return 0;
+}
+
 static int partition_read_definition(Partition *p, const char *path, const char *const *conf_file_dirs) {
 
         ConfigTableItem table[] = {
                 { "Partition", "Type",            config_parse_type,        0, &p->type_uuid        },
                 { "Partition", "Label",           config_parse_label,       0, &p->new_label        },
-                { "Partition", "UUID",            config_parse_id128,       0, &p->new_uuid         },
+                { "Partition", "UUID",            config_parse_uuid,        0, p                    },
                 { "Partition", "Priority",        config_parse_int32,       0, &p->priority         },
                 { "Partition", "Weight",          config_parse_weight,      0, &p->weight           },
                 { "Partition", "PaddingWeight",   config_parse_weight,      0, &p->padding_weight   },
@@ -2066,7 +2105,7 @@ static int context_dump_partitions(Context *context, const char *node) {
                                 t,
                                 TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type_uuid, uuid_buffer),
                                 TABLE_STRING, empty_to_null(label) ?: "-", TABLE_SET_COLOR, empty_to_null(label) ? NULL : ansi_grey(),
-                                TABLE_UUID, sd_id128_is_null(p->new_uuid) ? p->current_uuid : p->new_uuid,
+                                TABLE_UUID, p->new_uuid_is_set ? p->new_uuid : p->current_uuid,
                                 TABLE_STRING, p->definition_path ? basename(p->definition_path) : "-", TABLE_SET_COLOR, p->definition_path ? NULL : ansi_grey(),
                                 TABLE_STRING, partname ?: "-", TABLE_SET_COLOR, partname ? NULL : ansi_highlight(),
                                 TABLE_UINT64, p->offset,
@@ -2184,7 +2223,7 @@ static int partition_hint(const Partition *p, const char *node, char **ret) {
                 goto done;
         }
 
-        if (!sd_id128_is_null(p->new_uuid))
+        if (p->new_uuid_is_set)
                 id = p->new_uuid;
         else if (!sd_id128_is_null(p->current_uuid))
                 id = p->current_uuid;
@@ -3249,11 +3288,13 @@ static int context_acquire_partition_uuids_and_labels(Context *context) {
 
                 if (!sd_id128_is_null(p->current_uuid))
                         p->new_uuid = p->current_uuid; /* Never change initialized UUIDs */
-                else if (sd_id128_is_null(p->new_uuid)) {
+                else if (!p->new_uuid_is_set) {
                         /* Not explicitly set by user! */
                         r = partition_acquire_uuid(context, p, &p->new_uuid);
                         if (r < 0)
                                 return r;
+
+                        p->new_uuid_is_set = true;
                 }
 
                 if (!isempty(p->current_label)) {
@@ -3369,8 +3410,6 @@ static int context_mangle_partitions(Context *context) {
                         }
 
                         if (!sd_id128_equal(p->new_uuid, p->current_uuid)) {
-                                assert(!sd_id128_is_null(p->new_uuid));
-
                                 r = fdisk_partition_set_uuid(p->current_partition, SD_ID128_TO_UUID_STRING(p->new_uuid));
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to set partition UUID: %m");
@@ -3402,7 +3441,6 @@ static int context_mangle_partitions(Context *context) {
                         assert(!p->new_partition);
                         assert(p->offset % context->sector_size == 0);
                         assert(p->new_size % context->sector_size == 0);
-                        assert(!sd_id128_is_null(p->new_uuid));
                         assert(p->new_label);
 
                         t = fdisk_new_parttype();
@@ -4042,8 +4080,10 @@ static int context_open_copy_block_paths(
                 free_and_replace(p->copy_blocks_path, opened);
 
                 /* When copying from an existing partition copy that partitions UUID if none is configured explicitly */
-                if (sd_id128_is_null(p->new_uuid) && !sd_id128_is_null(uuid))
+                if (!p->new_uuid_is_set && !sd_id128_is_null(uuid)) {
                         p->new_uuid = uuid;
+                        p->new_uuid_is_set = true;
+                }
         }
 
         return 0;
index 3c826b0829e499cf8113d6bff0e0d338c55534aa..fddcda3872ad775f09ccb6713f8fe903a0b767ce 100755 (executable)
@@ -570,6 +570,34 @@ EOF
     assert_in "$imgs/21817.img2 : start=      104448, size=      (100319| 98304)," "$output"
 }
 
+test_zero_uuid() {
+    local defs imgs output
+
+    defs="$(mktemp --directory "/tmp/test-repart.XXXXXXXXXX")"
+    imgs="$(mktemp --directory "/var/tmp/test-repart.XXXXXXXXXX")"
+    # shellcheck disable=SC2064
+    trap "rm -rf '$defs' '$imgs'" RETURN
+
+    # Test image with zero UUID.
+
+    cat >"$defs/root.conf" <<EOF
+[Partition]
+Type=root-${architecture}
+UUID=null
+EOF
+
+    systemd-repart --definitions="$defs" \
+                   --seed="$seed" \
+                   --dry-run=no \
+                   --empty=create \
+                   --size=auto \
+                   "$imgs/zero"
+
+    output=$(sfdisk --dump "$imgs/zero")
+
+    assert_in "$imgs/zero1 : start=        2048, size=       20480, type=${root_guid}, uuid=00000000-0000-0000-0000-000000000000" "$output"
+}
+
 test_sector() {
     local defs imgs output loop
     local start size ratio
@@ -635,6 +663,7 @@ test_multiple_definitions
 test_copy_blocks
 test_unaligned_partition
 test_issue_21817
+test_zero_uuid
 
 # Valid block sizes on the Linux block layer are >= 512 and <= PAGE_SIZE, and
 # must be powers of 2. Which leaves exactly four different ones to test on