From 22e932f4d15f59ae773370a41a1c01ec93f8915a Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 13 Oct 2022 21:26:16 +0200 Subject: [PATCH 1/4] gpt: Expose GptPartitionType and get rid of SECONDARY/OTHER Instead of exposing just the partition type UUID, let's expose the GptPartitionType struct, which has a lot more information available in a much more accessible way. Also, let's get rid of SECONDARY/OTHER in PartitionDesignator. These were only there to support preferred architectures in dissect-image.c, but we can easily handle that by comparing architectures when we decide whether to override a partition. This is done in a new function compare_arch(). --- src/id128/id128.c | 5 +- src/partition/repart.c | 82 +++++----- src/shared/dissect-image.c | 211 +++++++----------------- src/shared/gpt.c | 241 +++++++--------------------- src/shared/gpt.h | 31 +--- src/sysupdate/sysupdate-partition.c | 18 ++- src/sysupdate/sysupdate-resource.c | 2 +- src/sysupdate/sysupdate-resource.h | 5 +- src/sysupdate/sysupdate-transfer.c | 16 +- src/test/test-gpt.c | 14 +- 10 files changed, 200 insertions(+), 425 deletions(-) diff --git a/src/id128/id128.c b/src/id128/id128.c index af88e315bbc..53a24348d5c 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -123,10 +123,13 @@ static int verb_show(int argc, char **argv, void *userdata) { if (have_uuid) id = gpt_partition_type_uuid_to_string(uuid) ?: "XYZ"; else { - r = gpt_partition_type_uuid_from_string(*p, &uuid); + GptPartitionType type; + + r = gpt_partition_type_from_string(*p, &type); if (r < 0) return log_error_errno(r, "Unknown identifier \"%s\".", *p); + uuid = type.uuid; id = *p; } diff --git a/src/partition/repart.c b/src/partition/repart.c index 4cdbeadf711..20f764ee1ca 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -164,7 +164,7 @@ struct Partition { char *definition_path; char **drop_in_files; - sd_id128_t type_uuid; + GptPartitionType type; sd_id128_t current_uuid, new_uuid; bool new_uuid_is_set; char *current_label, *new_label; @@ -1087,12 +1087,12 @@ static int config_parse_type( void *data, void *userdata) { - sd_id128_t *type_uuid = ASSERT_PTR(data); + GptPartitionType *type = ASSERT_PTR(data); int r; assert(rvalue); - r = gpt_partition_type_uuid_from_string(rvalue, type_uuid); + r = gpt_partition_type_from_string(rvalue, type); if (r < 0) return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse partition type: %s", rvalue); @@ -1478,7 +1478,7 @@ static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_verity, verity_mode, V 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", "Type", config_parse_type, 0, &p->type }, { "Partition", "Label", config_parse_label, 0, &p->new_label }, { "Partition", "UUID", config_parse_uuid, 0, p }, { "Partition", "Priority", config_parse_int32, 0, &p->priority }, @@ -1535,7 +1535,7 @@ static int partition_read_definition(Partition *p, const char *path, const char return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), "PaddingMinBytes= larger than PaddingMaxBytes=, refusing."); - if (sd_id128_is_null(p->type_uuid)) + if (sd_id128_is_null(p->type.uuid)) return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), "Type= not defined, refusing."); @@ -1599,13 +1599,13 @@ static int partition_read_definition(Partition *p, const char *path, const char verity_mode_to_string(p->verity)); /* Verity partitions are read only, let's imply the RO flag hence, unless explicitly configured otherwise. */ - if ((gpt_partition_type_is_root_verity(p->type_uuid) || - gpt_partition_type_is_usr_verity(p->type_uuid)) && + if ((p->type.designator == PARTITION_ROOT_VERITY || + p->type.designator == PARTITION_USR_VERITY) && p->read_only < 0) p->read_only = true; /* Default to "growfs" on, unless read-only */ - if (gpt_partition_type_knows_growfs(p->type_uuid) && + if (gpt_partition_type_knows_growfs(p->type) && p->read_only <= 0) p->growfs = true; @@ -2099,7 +2099,7 @@ static int context_load_partition_table( LIST_FOREACH(partitions, pp, context->partitions) { last = pp; - if (!sd_id128_equal(pp->type_uuid, ptid)) + if (!sd_id128_equal(pp->type.uuid, ptid)) continue; if (!pp->current_partition) { @@ -2136,7 +2136,7 @@ static int context_load_partition_table( return log_oom(); np->current_uuid = id; - np->type_uuid = ptid; + np->type = gpt_partition_type_from_uuid(ptid); np->current_size = sz; np->offset = start; np->partno = partno; @@ -2295,7 +2295,7 @@ static const char *partition_label(const Partition *p) { if (p->current_label) return p->current_label; - return gpt_partition_type_uuid_to_string(p->type_uuid); + return gpt_partition_type_uuid_to_string(p->type.uuid); } static int context_dump_partitions(Context *context, const char *node) { @@ -2369,7 +2369,7 @@ static int context_dump_partitions(Context *context, const char *node) { r = table_add_many( t, - TABLE_STRING, gpt_partition_type_uuid_to_string_harder(p->type_uuid, uuid_buffer), + 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, 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(), @@ -2503,7 +2503,7 @@ static int partition_hint(const Partition *p, const char *node, char **ret) { else if (!sd_id128_is_null(p->current_uuid)) id = p->current_uuid; else - id = p->type_uuid; + id = p->type.uuid; buf = strdup(SD_ID128_TO_UUID_STRING(id)); @@ -3463,7 +3463,7 @@ static int make_copy_files_denylist(Context *context, Set **ret) { assert(ret); LIST_FOREACH(partitions, p, context->partitions) { - const char *sources = gpt_partition_type_mountpoint_nulstr(p->type_uuid); + const char *sources = gpt_partition_type_mountpoint_nulstr(p->type); if (!sources) continue; @@ -3955,13 +3955,13 @@ static int partition_acquire_uuid(Context *context, Partition *p, sd_id128_t *re if (p == q) break; - if (!sd_id128_equal(p->type_uuid, q->type_uuid)) + if (!sd_id128_equal(p->type.uuid, q->type.uuid)) continue; k++; } - plaintext.type_uuid = p->type_uuid; + plaintext.type_uuid = p->type.uuid; plaintext.counter = htole64(k); hmac_sha256(context->seed.bytes, sizeof(context->seed.bytes), @@ -4002,7 +4002,7 @@ static int partition_acquire_label(Context *context, Partition *p, char **ret) { assert(p); assert(ret); - prefix = gpt_partition_type_uuid_to_string(p->type_uuid); + prefix = gpt_partition_type_uuid_to_string(p->type.uuid); if (!prefix) prefix = "linux"; @@ -4118,35 +4118,35 @@ static uint64_t partition_merge_flags(Partition *p) { f = p->gpt_flags; if (p->no_auto >= 0) { - if (gpt_partition_type_knows_no_auto(p->type_uuid)) + if (gpt_partition_type_knows_no_auto(p->type)) SET_FLAG(f, SD_GPT_FLAG_NO_AUTO, p->no_auto); else { char buffer[SD_ID128_UUID_STRING_MAX]; log_warning("Configured NoAuto=%s for partition type '%s' that doesn't support it, ignoring.", yes_no(p->no_auto), - gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer)); + gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer)); } } if (p->read_only >= 0) { - if (gpt_partition_type_knows_read_only(p->type_uuid)) + if (gpt_partition_type_knows_read_only(p->type)) SET_FLAG(f, SD_GPT_FLAG_READ_ONLY, p->read_only); else { char buffer[SD_ID128_UUID_STRING_MAX]; log_warning("Configured ReadOnly=%s for partition type '%s' that doesn't support it, ignoring.", yes_no(p->read_only), - gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer)); + gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer)); } } if (p->growfs >= 0) { - if (gpt_partition_type_knows_growfs(p->type_uuid)) + if (gpt_partition_type_knows_growfs(p->type)) SET_FLAG(f, SD_GPT_FLAG_GROWFS, p->growfs); else { char buffer[SD_ID128_UUID_STRING_MAX]; log_warning("Configured GrowFileSystem=%s for partition type '%s' that doesn't support it, ignoring.", yes_no(p->growfs), - gpt_partition_type_uuid_to_string_harder(p->type_uuid, buffer)); + gpt_partition_type_uuid_to_string_harder(p->type.uuid, buffer)); } } @@ -4225,7 +4225,7 @@ static int context_mangle_partitions(Context *context) { if (!t) return log_oom(); - r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type_uuid)); + r = fdisk_parttype_set_typestr(t, SD_ID128_TO_UUID_STRING(p->type.uuid)); if (r < 0) return log_error_errno(r, "Failed to initialize partition type: %m"); @@ -4284,8 +4284,8 @@ static int split_name_printf(Partition *p) { assert(p); const Specifier table[] = { - { 't', specifier_string, GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(p->type_uuid) }, - { 'T', specifier_id128, &p->type_uuid }, + { 't', specifier_string, GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(p->type.uuid) }, + { 'T', specifier_id128, &p->type.uuid }, { 'U', specifier_id128, &p->new_uuid }, { 'n', specifier_uint64, &p->partno }, @@ -4614,7 +4614,7 @@ static int context_can_factory_reset(Context *context) { static int resolve_copy_blocks_auto_candidate( dev_t partition_devno, - sd_id128_t partition_type_uuid, + GptPartitionType partition_type, dev_t restrict_devno, sd_id128_t *ret_uuid) { @@ -4706,10 +4706,10 @@ static int resolve_copy_blocks_auto_candidate( return false; } - if (!sd_id128_equal(pt_parsed, partition_type_uuid)) { + if (!sd_id128_equal(pt_parsed, partition_type.uuid)) { log_debug("Partition %u:%u has non-matching partition type " SD_ID128_FORMAT_STR " (needed: " SD_ID128_FORMAT_STR "), ignoring.", major(partition_devno), minor(partition_devno), - SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type_uuid)); + SD_ID128_FORMAT_VAL(pt_parsed), SD_ID128_FORMAT_VAL(partition_type.uuid)); return false; } @@ -4766,7 +4766,7 @@ static int find_backing_devno( } static int resolve_copy_blocks_auto( - sd_id128_t type_uuid, + GptPartitionType type, const char *root, dev_t restrict_devno, dev_t *ret_devno, @@ -4796,30 +4796,30 @@ static int resolve_copy_blocks_auto( * partitions in the host, using the appropriate directory as key and ensuring that the partition * type matches. */ - if (gpt_partition_type_is_root(type_uuid)) + if (type.designator == PARTITION_ROOT) try1 = "/"; - else if (gpt_partition_type_is_usr(type_uuid)) + else if (type.designator == PARTITION_USR) try1 = "/usr/"; - else if (gpt_partition_type_is_root_verity(type_uuid)) + else if (type.designator == PARTITION_ROOT_VERITY) try1 = "/"; - else if (gpt_partition_type_is_usr_verity(type_uuid)) + else if (type.designator == PARTITION_USR_VERITY) try1 = "/usr/"; - else if (sd_id128_equal(type_uuid, SD_GPT_ESP)) { + else if (type.designator == PARTITION_ESP) { try1 = "/efi/"; try2 = "/boot/"; - } else if (sd_id128_equal(type_uuid, SD_GPT_XBOOTLDR)) + } else if (type.designator == PARTITION_XBOOTLDR) try1 = "/boot/"; else return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Partition type " SD_ID128_FORMAT_STR " not supported from automatic source block device discovery.", - SD_ID128_FORMAT_VAL(type_uuid)); + SD_ID128_FORMAT_VAL(type.uuid)); r = find_backing_devno(try1, root, &devno); if (r == -ENOENT && try2) r = find_backing_devno(try2, root, &devno); if (r < 0) return log_error_errno(r, "Failed to resolve automatic CopyBlocks= path for partition type " SD_ID128_FORMAT_STR ", sorry: %m", - SD_ID128_FORMAT_VAL(type_uuid)); + SD_ID128_FORMAT_VAL(type.uuid)); xsprintf_sys_block_path(p, "/slaves", devno); d = opendir(p); @@ -4861,7 +4861,7 @@ static int resolve_copy_blocks_auto( continue; } - r = resolve_copy_blocks_auto_candidate(sl, type_uuid, restrict_devno, &u); + r = resolve_copy_blocks_auto_candidate(sl, type, restrict_devno, &u); if (r < 0) return r; if (r > 0) { @@ -4877,7 +4877,7 @@ static int resolve_copy_blocks_auto( } else if (errno != ENOENT) return log_error_errno(errno, "Failed open %s: %m", p); else { - r = resolve_copy_blocks_auto_candidate(devno, type_uuid, restrict_devno, &found_uuid); + r = resolve_copy_blocks_auto_candidate(devno, type, restrict_devno, &found_uuid); if (r < 0) return r; if (r > 0) @@ -4934,7 +4934,7 @@ static int context_open_copy_block_paths( } else if (p->copy_blocks_auto) { dev_t devno; - r = resolve_copy_blocks_auto(p->type_uuid, p->copy_blocks_root, restrict_devno, &devno, &uuid); + r = resolve_copy_blocks_auto(p->type, p->copy_blocks_root, restrict_devno, &devno, &uuid); if (r < 0) return r; diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 8418ed6dc37..d67bdd501bc 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -333,6 +333,27 @@ static int open_partition(const char *node, bool is_partition, const LoopDevice return TAKE_FD(fd); } +static int compare_arch(Architecture a, Architecture b) { + if (a == b) + return 0; + + if (a == native_architecture()) + return 1; + + if (b == native_architecture()) + return -1; + +#ifdef ARCHITECTURE_SECONDARY + if (a == ARCHITECTURE_SECONDARY) + return 1; + + if (b == ARCHITECTURE_SECONDARY) + return -1; +#endif + + return 0; +} + static int dissect_image( DissectedImage *m, int fd, @@ -606,10 +627,9 @@ static int dissect_image( } if (is_gpt) { - PartitionDesignator designator = _PARTITION_DESIGNATOR_INVALID; - Architecture architecture = _ARCHITECTURE_INVALID; const char *stype, *sid, *fstype = NULL, *label; sd_id128_t type_id, id; + GptPartitionType type; bool rw = true, growfs = false; sid = blkid_partition_get_uuid(pp); @@ -624,9 +644,11 @@ static int dissect_image( if (sd_id128_from_string(stype, &type_id) < 0) continue; + type = gpt_partition_type_from_uuid(type_id); + label = blkid_partition_get_name(pp); /* libblkid returns NULL here if empty */ - if (sd_id128_equal(type_id, SD_GPT_HOME)) { + if (type.designator == PARTITION_HOME) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -634,11 +656,10 @@ static int dissect_image( if (pflags & SD_GPT_FLAG_NO_AUTO) continue; - designator = PARTITION_HOME; rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); - } else if (sd_id128_equal(type_id, SD_GPT_SRV)) { + } else if (type.designator == PARTITION_SRV) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -646,11 +667,10 @@ static int dissect_image( if (pflags & SD_GPT_FLAG_NO_AUTO) continue; - designator = PARTITION_SRV; rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); - } else if (sd_id128_equal(type_id, SD_GPT_ESP)) { + } else if (type.designator == PARTITION_ESP) { /* Note that we don't check the SD_GPT_FLAG_NO_AUTO flag for the ESP, as it is * not defined there. We instead check the SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL, as @@ -660,10 +680,9 @@ static int dissect_image( if (pflags & SD_GPT_FLAG_NO_BLOCK_IO_PROTOCOL) continue; - designator = PARTITION_ESP; fstype = "vfat"; - } else if (sd_id128_equal(type_id, SD_GPT_XBOOTLDR)) { + } else if (type.designator == PARTITION_XBOOTLDR) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -671,11 +690,10 @@ static int dissect_image( if (pflags & SD_GPT_FLAG_NO_AUTO) continue; - designator = PARTITION_XBOOTLDR; rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); - } else if (gpt_partition_type_is_root(type_id)) { + } else if (type.designator == PARTITION_ROOT) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -687,12 +705,10 @@ static int dissect_image( if (!sd_id128_is_null(root_uuid) && !sd_id128_equal(root_uuid, id)) continue; - assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0); - designator = partition_root_of_arch(architecture); rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); - } else if (gpt_partition_type_is_root_verity(type_id)) { + } else if (type.designator == PARTITION_ROOT_VERITY) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); @@ -712,12 +728,10 @@ static int dissect_image( if (!sd_id128_is_null(root_verity_uuid) && !sd_id128_equal(root_verity_uuid, id)) continue; - assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0); - designator = partition_verity_of(partition_root_of_arch(architecture)); fstype = "DM_verity_hash"; rw = false; - } else if (gpt_partition_type_is_root_verity_sig(type_id)) { + } else if (type.designator == PARTITION_ROOT_VERITY_SIG) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); @@ -732,12 +746,10 @@ static int dissect_image( if (verity->designator >= 0 && verity->designator != PARTITION_ROOT) continue; - assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0); - designator = partition_verity_sig_of(partition_root_of_arch(architecture)); fstype = "verity_hash_signature"; rw = false; - } else if (gpt_partition_type_is_usr(type_id)) { + } else if (type.designator == PARTITION_USR) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -749,12 +761,10 @@ static int dissect_image( if (!sd_id128_is_null(usr_uuid) && !sd_id128_equal(usr_uuid, id)) continue; - assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0); - designator = partition_usr_of_arch(architecture); rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); - } else if (gpt_partition_type_is_usr_verity(type_id)) { + } else if (type.designator == PARTITION_USR_VERITY) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); @@ -773,12 +783,10 @@ static int dissect_image( if (!sd_id128_is_null(usr_verity_uuid) && !sd_id128_equal(usr_verity_uuid, id)) continue; - assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0); - designator = partition_verity_of(partition_usr_of_arch(architecture)); fstype = "DM_verity_hash"; rw = false; - } else if (gpt_partition_type_is_usr_verity_sig(type_id)) { + } else if (type.designator == PARTITION_USR_VERITY_SIG) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY); @@ -793,21 +801,17 @@ static int dissect_image( if (verity->designator >= 0 && verity->designator != PARTITION_USR) continue; - assert_se((architecture = gpt_partition_type_uuid_to_arch(type_id)) >= 0); - designator = partition_verity_sig_of(partition_usr_of_arch(architecture)); fstype = "verity_hash_signature"; rw = false; - } else if (sd_id128_equal(type_id, SD_GPT_SWAP)) { + } else if (type.designator == PARTITION_SWAP) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO); if (pflags & SD_GPT_FLAG_NO_AUTO) continue; - designator = PARTITION_SWAP; - - } else if (sd_id128_equal(type_id, SD_GPT_LINUX_GENERIC)) { + } else if (type.designator == PARTITION_LINUX_GENERIC) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -827,7 +831,7 @@ static int dissect_image( return -ENOMEM; } - } else if (sd_id128_equal(type_id, SD_GPT_TMP)) { + } else if (type.designator == PARTITION_TMP) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -835,11 +839,10 @@ static int dissect_image( if (pflags & SD_GPT_FLAG_NO_AUTO) continue; - designator = PARTITION_TMP; rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); - } else if (sd_id128_equal(type_id, SD_GPT_VAR)) { + } else if (type.designator == PARTITION_VAR) { check_partition_flags(node, pflags, SD_GPT_FLAG_NO_AUTO | SD_GPT_FLAG_READ_ONLY | SD_GPT_FLAG_GROWFS); @@ -868,27 +871,29 @@ static int dissect_image( } } - designator = PARTITION_VAR; rw = !(pflags & SD_GPT_FLAG_READ_ONLY); growfs = FLAGS_SET(pflags, SD_GPT_FLAG_GROWFS); } - if (designator != _PARTITION_DESIGNATOR_INVALID) { + if (type.designator != _PARTITION_DESIGNATOR_INVALID) { _cleanup_free_ char *t = NULL, *o = NULL, *l = NULL; _cleanup_close_ int mount_node_fd = -1; const char *options = NULL; - if (m->partitions[designator].found) { + if (m->partitions[type.designator].found) { /* For most partition types the first one we see wins. Except for the * rootfs and /usr, where we do a version compare of the label, and * let the newest version win. This permits a simple A/B versioning * scheme in OS images. */ - if (!partition_designator_is_versioned(designator) || - strverscmp_improved(m->partitions[designator].label, label) >= 0) + if (compare_arch(type.arch, m->partitions[type.designator].architecture) <= 0) continue; - dissected_partition_done(m->partitions + designator); + if (!partition_designator_is_versioned(type.designator) || + strverscmp_improved(m->partitions[type.designator].label, label) >= 0) + continue; + + dissected_partition_done(m->partitions + type.designator); } if (FLAGS_SET(flags, DISSECT_IMAGE_OPEN_PARTITION_DEVICES)) { @@ -909,19 +914,19 @@ static int dissect_image( return -ENOMEM; } - options = mount_options_from_designator(mount_options, designator); + options = mount_options_from_designator(mount_options, type.designator); if (options) { o = strdup(options); if (!o) return -ENOMEM; } - m->partitions[designator] = (DissectedPartition) { + m->partitions[type.designator] = (DissectedPartition) { .found = true, .partno = nr, .rw = rw, .growfs = growfs, - .architecture = architecture, + .architecture = type.arch, .node = TAKE_PTR(node), .fstype = TAKE_PTR(t), .label = TAKE_PTR(l), @@ -1001,121 +1006,21 @@ static int dissect_image( } } - if (m->partitions[PARTITION_ROOT].found) { - /* If we found the primary arch, then invalidate the secondary and other arch to avoid any - * ambiguities, since we never want to mount the secondary or other arch in this case. */ - m->partitions[PARTITION_ROOT_SECONDARY].found = false; - m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found = false; - m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG].found = false; - m->partitions[PARTITION_USR_SECONDARY].found = false; - m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false; - m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found = false; - - m->partitions[PARTITION_ROOT_OTHER].found = false; - m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false; - m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG].found = false; - m->partitions[PARTITION_USR_OTHER].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false; - - } else if (m->partitions[PARTITION_ROOT_VERITY].found || - m->partitions[PARTITION_ROOT_VERITY_SIG].found) - return -EADDRNOTAVAIL; /* Verity found but no matching rootfs? Something is off, refuse. */ - - else if (m->partitions[PARTITION_ROOT_SECONDARY].found) { - - /* No root partition found but there's one for the secondary architecture? Then upgrade - * secondary arch to first and invalidate the other arch. */ - - log_debug("No root partition found of the native architecture, falling back to a root " - "partition of the secondary architecture."); - - m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY]); - m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY]); - m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG]); - - m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]); - m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]); - m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]); - - m->partitions[PARTITION_ROOT_OTHER].found = false; - m->partitions[PARTITION_ROOT_OTHER_VERITY].found = false; - m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG].found = false; - m->partitions[PARTITION_USR_OTHER].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false; - - } else if (m->partitions[PARTITION_ROOT_SECONDARY_VERITY].found || - m->partitions[PARTITION_ROOT_SECONDARY_VERITY_SIG].found) - return -EADDRNOTAVAIL; /* as above */ - - else if (m->partitions[PARTITION_ROOT_OTHER].found) { - - /* No root or secondary partition found but there's one for another architecture? Then - * upgrade the other architecture to first. */ - - log_debug("No root partition found of the native architecture or the secondary architecture, " - "falling back to a root partition of a non-native architecture (%s).", - architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture)); - - m->partitions[PARTITION_ROOT] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER]); - m->partitions[PARTITION_ROOT_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY]); - m->partitions[PARTITION_ROOT_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_ROOT_OTHER_VERITY_SIG]); - - m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]); - m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]); - m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]); - } + if (!m->partitions[PARTITION_ROOT].found && + (m->partitions[PARTITION_ROOT_VERITY].found || + m->partitions[PARTITION_ROOT_VERITY_SIG].found)) + return -EADDRNOTAVAIL; /* Verity found but no matching rootfs? Something is off, refuse. */ /* Hmm, we found a signature partition but no Verity data? Something is off. */ if (m->partitions[PARTITION_ROOT_VERITY_SIG].found && !m->partitions[PARTITION_ROOT_VERITY].found) return -EADDRNOTAVAIL; - if (m->partitions[PARTITION_USR].found) { - /* Invalidate secondary and other arch /usr/ if we found the primary arch */ - m->partitions[PARTITION_USR_SECONDARY].found = false; - m->partitions[PARTITION_USR_SECONDARY_VERITY].found = false; - m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found = false; + if (!m->partitions[PARTITION_USR].found && + (m->partitions[PARTITION_USR_VERITY].found || + m->partitions[PARTITION_USR_VERITY_SIG].found)) + return -EADDRNOTAVAIL; /* as above */ - m->partitions[PARTITION_USR_OTHER].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false; - - } else if (m->partitions[PARTITION_USR_VERITY].found || - m->partitions[PARTITION_USR_VERITY_SIG].found) - return -EADDRNOTAVAIL; /* as above */ - - else if (m->partitions[PARTITION_USR_SECONDARY].found) { - - log_debug("No usr partition found of the native architecture, falling back to a usr " - "partition of the secondary architecture."); - - /* Upgrade secondary arch to primary */ - m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY]); - m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY]); - m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG]); - - m->partitions[PARTITION_USR_OTHER].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY].found = false; - m->partitions[PARTITION_USR_OTHER_VERITY_SIG].found = false; - - } else if (m->partitions[PARTITION_USR_SECONDARY_VERITY].found || - m->partitions[PARTITION_USR_SECONDARY_VERITY_SIG].found) - return -EADDRNOTAVAIL; /* as above */ - - else if (m->partitions[PARTITION_USR_OTHER].found) { - - log_debug("No usr partition found of the native architecture or the secondary architecture, " - "falling back to a usr partition of a non-native architecture (%s).", - architecture_to_string(m->partitions[PARTITION_ROOT_OTHER].architecture)); - - /* Upgrade other arch to primary */ - m->partitions[PARTITION_USR] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER]); - m->partitions[PARTITION_USR_VERITY] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY]); - m->partitions[PARTITION_USR_VERITY_SIG] = TAKE_PARTITION(m->partitions[PARTITION_USR_OTHER_VERITY_SIG]); - } - - /* Hmm, we found a signature partition but no Verity data? Something is off. */ + /* as above */ if (m->partitions[PARTITION_USR_VERITY_SIG].found && !m->partitions[PARTITION_USR_VERITY].found) return -EADDRNOTAVAIL; diff --git a/src/shared/gpt.c b/src/shared/gpt.c index af969ff9d57..ce73d7f7819 100644 --- a/src/shared/gpt.c +++ b/src/shared/gpt.c @@ -23,23 +23,11 @@ bool partition_designator_is_versioned(PartitionDesignator d) { return IN_SET(d, PARTITION_ROOT, - PARTITION_ROOT_SECONDARY, - PARTITION_ROOT_OTHER, PARTITION_USR, - PARTITION_USR_SECONDARY, - PARTITION_USR_OTHER, PARTITION_ROOT_VERITY, - PARTITION_ROOT_SECONDARY_VERITY, - PARTITION_ROOT_OTHER_VERITY, PARTITION_USR_VERITY, - PARTITION_USR_SECONDARY_VERITY, - PARTITION_USR_OTHER_VERITY, PARTITION_ROOT_VERITY_SIG, - PARTITION_ROOT_SECONDARY_VERITY_SIG, - PARTITION_ROOT_OTHER_VERITY_SIG, - PARTITION_USR_VERITY_SIG, - PARTITION_USR_SECONDARY_VERITY_SIG, - PARTITION_USR_OTHER_VERITY_SIG); + PARTITION_USR_VERITY_SIG); } PartitionDesignator partition_verity_of(PartitionDesignator p) { @@ -48,21 +36,9 @@ PartitionDesignator partition_verity_of(PartitionDesignator p) { case PARTITION_ROOT: return PARTITION_ROOT_VERITY; - case PARTITION_ROOT_SECONDARY: - return PARTITION_ROOT_SECONDARY_VERITY; - - case PARTITION_ROOT_OTHER: - return PARTITION_ROOT_OTHER_VERITY; - case PARTITION_USR: return PARTITION_USR_VERITY; - case PARTITION_USR_SECONDARY: - return PARTITION_USR_SECONDARY_VERITY; - - case PARTITION_USR_OTHER: - return PARTITION_USR_OTHER_VERITY; - default: return _PARTITION_DESIGNATOR_INVALID; } @@ -74,82 +50,27 @@ PartitionDesignator partition_verity_sig_of(PartitionDesignator p) { case PARTITION_ROOT: return PARTITION_ROOT_VERITY_SIG; - case PARTITION_ROOT_SECONDARY: - return PARTITION_ROOT_SECONDARY_VERITY_SIG; - - case PARTITION_ROOT_OTHER: - return PARTITION_ROOT_OTHER_VERITY_SIG; - case PARTITION_USR: return PARTITION_USR_VERITY_SIG; - case PARTITION_USR_SECONDARY: - return PARTITION_USR_SECONDARY_VERITY_SIG; - - case PARTITION_USR_OTHER: - return PARTITION_USR_OTHER_VERITY_SIG; - default: return _PARTITION_DESIGNATOR_INVALID; } } -PartitionDesignator partition_root_of_arch(Architecture arch) { - switch (arch) { - - case native_architecture(): - return PARTITION_ROOT; - -#ifdef ARCHITECTURE_SECONDARY - case ARCHITECTURE_SECONDARY: - return PARTITION_ROOT_SECONDARY; -#endif - - default: - return PARTITION_ROOT_OTHER; - } -} - -PartitionDesignator partition_usr_of_arch(Architecture arch) { - switch (arch) { - - case native_architecture(): - return PARTITION_USR; - -#ifdef ARCHITECTURE_SECONDARY - case ARCHITECTURE_SECONDARY: - return PARTITION_USR_SECONDARY; -#endif - - default: - return PARTITION_USR_OTHER; - } -} static const char *const partition_designator_table[] = { [PARTITION_ROOT] = "root", - [PARTITION_ROOT_SECONDARY] = "root-secondary", - [PARTITION_ROOT_OTHER] = "root-other", [PARTITION_USR] = "usr", - [PARTITION_USR_SECONDARY] = "usr-secondary", - [PARTITION_USR_OTHER] = "usr-other", [PARTITION_HOME] = "home", [PARTITION_SRV] = "srv", [PARTITION_ESP] = "esp", [PARTITION_XBOOTLDR] = "xbootldr", [PARTITION_SWAP] = "swap", [PARTITION_ROOT_VERITY] = "root-verity", - [PARTITION_ROOT_SECONDARY_VERITY] = "root-secondary-verity", - [PARTITION_ROOT_OTHER_VERITY] = "root-other-verity", [PARTITION_USR_VERITY] = "usr-verity", - [PARTITION_USR_SECONDARY_VERITY] = "usr-secondary-verity", - [PARTITION_USR_OTHER_VERITY] = "usr-other-verity", [PARTITION_ROOT_VERITY_SIG] = "root-verity-sig", - [PARTITION_ROOT_SECONDARY_VERITY_SIG] = "root-secondary-verity-sig", - [PARTITION_ROOT_OTHER_VERITY_SIG] = "root-other-verity-sig", [PARTITION_USR_VERITY_SIG] = "usr-verity-sig", - [PARTITION_USR_SECONDARY_VERITY_SIG] = "usr-secondary-verity-sig", - [PARTITION_USR_OTHER_VERITY_SIG] = "usr-other-verity-sig", [PARTITION_TMP] = "tmp", [PARTITION_VAR] = "var", [PARTITION_USER_HOME] = "user-home", @@ -160,11 +81,7 @@ DEFINE_STRING_TABLE_LOOKUP(partition_designator, PartitionDesignator); static const char *const partition_mountpoint_table[] = { [PARTITION_ROOT] = "/\0", - [PARTITION_ROOT_SECONDARY] = "/\0", - [PARTITION_ROOT_OTHER] = "/\0", [PARTITION_USR] = "/usr\0", - [PARTITION_USR_SECONDARY] = "/usr\0", - [PARTITION_USR_OTHER] = "/usr\0", [PARTITION_HOME] = "/home\0", [PARTITION_SRV] = "/srv\0", [PARTITION_ESP] = "/efi\0/boot\0", @@ -176,12 +93,12 @@ static const char *const partition_mountpoint_table[] = { DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(partition_mountpoint, PartitionDesignator); #define _GPT_ARCH_SEXTET(arch, name) \ - { SD_GPT_ROOT_##arch, "root-" name, ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER }, \ - { SD_GPT_ROOT_##arch##_VERITY, "root-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER_VERITY }, \ - { SD_GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_OTHER_VERITY_SIG }, \ - { SD_GPT_USR_##arch, "usr-" name, ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER }, \ - { SD_GPT_USR_##arch##_VERITY, "usr-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER_VERITY }, \ - { SD_GPT_USR_##arch##_VERITY_SIG, "usr-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_USR_OTHER_VERITY_SIG } + { SD_GPT_ROOT_##arch, "root-" name, ARCHITECTURE_##arch, .designator = PARTITION_ROOT }, \ + { SD_GPT_ROOT_##arch##_VERITY, "root-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_VERITY }, \ + { SD_GPT_ROOT_##arch##_VERITY_SIG, "root-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_ROOT_VERITY_SIG }, \ + { SD_GPT_USR_##arch, "usr-" name, ARCHITECTURE_##arch, .designator = PARTITION_USR }, \ + { SD_GPT_USR_##arch##_VERITY, "usr-" name "-verity", ARCHITECTURE_##arch, .designator = PARTITION_USR_VERITY }, \ + { SD_GPT_USR_##arch##_VERITY_SIG, "usr-" name "-verity-sig", ARCHITECTURE_##arch, .designator = PARTITION_USR_VERITY_SIG } const GptPartitionType gpt_partition_type_table[] = { _GPT_ARCH_SEXTET(ALPHA, "alpha"), @@ -212,12 +129,12 @@ const GptPartitionType gpt_partition_type_table[] = { { SD_GPT_USR_NATIVE_VERITY_SIG, "usr-verity-sig", native_architecture(), .designator = PARTITION_USR_VERITY_SIG }, #endif #ifdef SD_GPT_ROOT_SECONDARY - { SD_GPT_ROOT_NATIVE, "root-secondary", native_architecture(), .designator = PARTITION_ROOT_SECONDARY }, - { SD_GPT_ROOT_NATIVE_VERITY, "root-secondary-verity", native_architecture(), .designator = PARTITION_ROOT_SECONDARY_VERITY }, - { SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-secondary-verity-sig", native_architecture(), .designator = PARTITION_ROOT_SECONDARY_VERITY_SIG }, - { SD_GPT_USR_NATIVE, "usr-secondary", native_architecture(), .designator = PARTITION_USR_SECONDARY }, - { SD_GPT_USR_NATIVE_VERITY, "usr-secondary-verity", native_architecture(), .designator = PARTITION_USR_SECONDARY_VERITY }, - { SD_GPT_USR_NATIVE_VERITY_SIG, "usr-secondary-verity-sig", native_architecture(), .designator = PARTITION_USR_SECONDARY_VERITY_SIG }, + { SD_GPT_ROOT_NATIVE, "root-secondary", native_architecture(), .designator = PARTITION_ROOT }, + { SD_GPT_ROOT_NATIVE_VERITY, "root-secondary-verity", native_architecture(), .designator = PARTITION_ROOT_VERITY }, + { SD_GPT_ROOT_NATIVE_VERITY_SIG, "root-secondary-verity-sig", native_architecture(), .designator = PARTITION_ROOT_VERITY_SIG }, + { SD_GPT_USR_NATIVE, "usr-secondary", native_architecture(), .designator = PARTITION_USR }, + { SD_GPT_USR_NATIVE_VERITY, "usr-secondary-verity", native_architecture(), .designator = PARTITION_USR_VERITY }, + { SD_GPT_USR_NATIVE_VERITY_SIG, "usr-secondary-verity-sig", native_architecture(), .designator = PARTITION_USR_VERITY_SIG }, #endif { SD_GPT_ESP, "esp", _ARCHITECTURE_INVALID, .designator = PARTITION_ESP }, @@ -266,17 +183,27 @@ const char *gpt_partition_type_uuid_to_string_harder( return sd_id128_to_uuid_string(id, buffer); } -int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret) { +int gpt_partition_type_from_string(const char *s, GptPartitionType *ret) { + sd_id128_t id; + int r; + assert(s); for (size_t i = 0; i < ELEMENTSOF(gpt_partition_type_table) - 1; i++) if (streq(s, gpt_partition_type_table[i].name)) { if (ret) - *ret = gpt_partition_type_table[i].uuid; + *ret = gpt_partition_type_table[i]; return 0; } - return sd_id128_from_string(s, ret); + r = sd_id128_from_string(s, &id); + if (r < 0) + return r; + + if (ret) + *ret = gpt_partition_type_from_uuid(id); + + return 0; } Architecture gpt_partition_type_uuid_to_arch(sd_id128_t id) { @@ -299,7 +226,7 @@ int gpt_partition_label_valid(const char *s) { return char16_strlen(recoded) <= GPT_LABEL_MAX; } -static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) { +GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) { const GptPartitionType *pt; pt = gpt_partition_type_find_by_uuid(id); @@ -313,91 +240,45 @@ static GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id) { }; } -bool gpt_partition_type_is_root(sd_id128_t id) { - return IN_SET(gpt_partition_type_from_uuid(id).designator, +const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type) { + return partition_mountpoint_to_string(type.designator); +} + +bool gpt_partition_type_knows_read_only(GptPartitionType type) { + return IN_SET(type.designator, PARTITION_ROOT, - PARTITION_ROOT_SECONDARY, - PARTITION_ROOT_OTHER); -} - -bool gpt_partition_type_is_root_verity(sd_id128_t id) { - return IN_SET(gpt_partition_type_from_uuid(id).designator, - PARTITION_ROOT_VERITY, - PARTITION_ROOT_SECONDARY_VERITY, - PARTITION_ROOT_OTHER_VERITY); -} - -bool gpt_partition_type_is_root_verity_sig(sd_id128_t id) { - return IN_SET(gpt_partition_type_from_uuid(id).designator, - PARTITION_ROOT_VERITY_SIG, - PARTITION_ROOT_SECONDARY_VERITY_SIG, - PARTITION_ROOT_OTHER_VERITY_SIG); -} - -bool gpt_partition_type_is_usr(sd_id128_t id) { - return IN_SET(gpt_partition_type_from_uuid(id).designator, PARTITION_USR, - PARTITION_USR_SECONDARY, - PARTITION_USR_OTHER); -} - -bool gpt_partition_type_is_usr_verity(sd_id128_t id) { - return IN_SET(gpt_partition_type_from_uuid(id).designator, + /* pretty much implied, but let's set the bit to make things really clear */ + PARTITION_ROOT_VERITY, PARTITION_USR_VERITY, - PARTITION_USR_SECONDARY_VERITY, - PARTITION_USR_OTHER_VERITY); + PARTITION_HOME, + PARTITION_SRV, + PARTITION_VAR, + PARTITION_TMP, + PARTITION_XBOOTLDR); } -bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id) { - return IN_SET(gpt_partition_type_from_uuid(id).designator, - PARTITION_USR_VERITY_SIG, - PARTITION_USR_SECONDARY_VERITY_SIG, - PARTITION_USR_OTHER_VERITY_SIG); +bool gpt_partition_type_knows_growfs(GptPartitionType type) { + return IN_SET(type.designator, + PARTITION_ROOT, + PARTITION_USR, + PARTITION_HOME, + PARTITION_SRV, + PARTITION_VAR, + PARTITION_TMP, + PARTITION_XBOOTLDR); } -const char *gpt_partition_type_mountpoint_nulstr(sd_id128_t id) { - PartitionDesignator d = gpt_partition_type_from_uuid(id).designator; - if (d < 0) - return NULL; - - return partition_mountpoint_to_string(d); -} - -bool gpt_partition_type_knows_read_only(sd_id128_t id) { - return gpt_partition_type_is_root(id) || - gpt_partition_type_is_usr(id) || - /* pretty much implied, but let's set the bit to make things really clear */ - gpt_partition_type_is_root_verity(id) || - gpt_partition_type_is_usr_verity(id) || - IN_SET(gpt_partition_type_from_uuid(id).designator, - PARTITION_HOME, - PARTITION_SRV, - PARTITION_VAR, - PARTITION_TMP, - PARTITION_XBOOTLDR); -} - -bool gpt_partition_type_knows_growfs(sd_id128_t id) { - return gpt_partition_type_is_root(id) || - gpt_partition_type_is_usr(id) || - IN_SET(gpt_partition_type_from_uuid(id).designator, - PARTITION_HOME, - PARTITION_SRV, - PARTITION_VAR, - PARTITION_TMP, - PARTITION_XBOOTLDR); -} - -bool gpt_partition_type_knows_no_auto(sd_id128_t id) { - return gpt_partition_type_is_root(id) || - gpt_partition_type_is_root_verity(id) || - gpt_partition_type_is_usr(id) || - gpt_partition_type_is_usr_verity(id) || - IN_SET(gpt_partition_type_from_uuid(id).designator, - PARTITION_HOME, - PARTITION_SRV, - PARTITION_VAR, - PARTITION_TMP, - PARTITION_XBOOTLDR, - PARTITION_SWAP); +bool gpt_partition_type_knows_no_auto(GptPartitionType type) { + return IN_SET(type.designator, + PARTITION_ROOT, + PARTITION_ROOT_VERITY, + PARTITION_USR, + PARTITION_USR_VERITY, + PARTITION_HOME, + PARTITION_SRV, + PARTITION_VAR, + PARTITION_TMP, + PARTITION_XBOOTLDR, + PARTITION_SWAP); } diff --git a/src/shared/gpt.h b/src/shared/gpt.h index e0ab44a6427..967e20e0af5 100644 --- a/src/shared/gpt.h +++ b/src/shared/gpt.h @@ -12,28 +12,16 @@ typedef enum PartitionDesignator { PARTITION_ROOT, /* Primary architecture */ - PARTITION_ROOT_SECONDARY, /* Secondary architecture */ - PARTITION_ROOT_OTHER, /* Any architecture not covered by the primary or secondary architecture. */ PARTITION_USR, - PARTITION_USR_SECONDARY, - PARTITION_USR_OTHER, PARTITION_HOME, PARTITION_SRV, PARTITION_ESP, PARTITION_XBOOTLDR, PARTITION_SWAP, PARTITION_ROOT_VERITY, /* verity data for the PARTITION_ROOT partition */ - PARTITION_ROOT_SECONDARY_VERITY, /* verity data for the PARTITION_ROOT_SECONDARY partition */ - PARTITION_ROOT_OTHER_VERITY, PARTITION_USR_VERITY, - PARTITION_USR_SECONDARY_VERITY, - PARTITION_USR_OTHER_VERITY, PARTITION_ROOT_VERITY_SIG, /* PKCS#7 signature for root hash for the PARTITION_ROOT partition */ - PARTITION_ROOT_SECONDARY_VERITY_SIG, /* ditto for the PARTITION_ROOT_SECONDARY partition */ - PARTITION_ROOT_OTHER_VERITY_SIG, PARTITION_USR_VERITY_SIG, - PARTITION_USR_SECONDARY_VERITY_SIG, - PARTITION_USR_OTHER_VERITY_SIG, PARTITION_TMP, PARTITION_VAR, PARTITION_USER_HOME, @@ -46,8 +34,6 @@ bool partition_designator_is_versioned(PartitionDesignator d); PartitionDesignator partition_verity_of(PartitionDesignator p); PartitionDesignator partition_verity_sig_of(PartitionDesignator p); -PartitionDesignator partition_root_of_arch(Architecture arch); -PartitionDesignator partition_usr_of_arch(Architecture arch); const char* partition_designator_to_string(PartitionDesignator d) _const_; PartitionDesignator partition_designator_from_string(const char *name) _pure_; @@ -56,7 +42,6 @@ const char *gpt_partition_type_uuid_to_string(sd_id128_t id); const char *gpt_partition_type_uuid_to_string_harder( sd_id128_t id, char buffer[static SD_ID128_UUID_STRING_MAX]); -int gpt_partition_type_uuid_from_string(const char *s, sd_id128_t *ret); #define GPT_PARTITION_TYPE_UUID_TO_STRING_HARDER(id) \ gpt_partition_type_uuid_to_string_harder((id), (char[SD_ID128_UUID_STRING_MAX]) {}) @@ -74,15 +59,11 @@ extern const GptPartitionType gpt_partition_type_table[]; int gpt_partition_label_valid(const char *s); -bool gpt_partition_type_is_root(sd_id128_t id); -bool gpt_partition_type_is_root_verity(sd_id128_t id); -bool gpt_partition_type_is_root_verity_sig(sd_id128_t id); -bool gpt_partition_type_is_usr(sd_id128_t id); -bool gpt_partition_type_is_usr_verity(sd_id128_t id); -bool gpt_partition_type_is_usr_verity_sig(sd_id128_t id); +GptPartitionType gpt_partition_type_from_uuid(sd_id128_t id); +int gpt_partition_type_from_string(const char *s, GptPartitionType *ret); -const char *gpt_partition_type_mountpoint_nulstr(sd_id128_t id); +const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type); -bool gpt_partition_type_knows_read_only(sd_id128_t id); -bool gpt_partition_type_knows_growfs(sd_id128_t id); -bool gpt_partition_type_knows_no_auto(sd_id128_t id); +bool gpt_partition_type_knows_read_only(GptPartitionType type); +bool gpt_partition_type_knows_growfs(GptPartitionType type); +bool gpt_partition_type_knows_no_auto(GptPartitionType type); diff --git a/src/sysupdate/sysupdate-partition.c b/src/sysupdate/sysupdate-partition.c index fa46574fd6b..33d0e584ba0 100644 --- a/src/sysupdate/sysupdate-partition.c +++ b/src/sysupdate/sysupdate-partition.c @@ -111,6 +111,7 @@ int read_partition_info( struct fdisk_parttype *pt; uint64_t start, size, flags; sd_id128_t ptid, id; + GptPartitionType type; size_t partno; int r; @@ -178,6 +179,8 @@ int read_partition_info( if (!label_copy) return log_oom(); + type = gpt_partition_type_from_uuid(ptid); + *ret = (PartitionInfo) { .partno = partno, .start = start, @@ -187,9 +190,9 @@ int read_partition_info( .uuid = id, .label = TAKE_PTR(label_copy), .device = TAKE_PTR(device), - .no_auto = FLAGS_SET(flags, SD_GPT_FLAG_NO_AUTO) && gpt_partition_type_knows_no_auto(ptid), - .read_only = FLAGS_SET(flags, SD_GPT_FLAG_READ_ONLY) && gpt_partition_type_knows_read_only(ptid), - .growfs = FLAGS_SET(flags, SD_GPT_FLAG_GROWFS) && gpt_partition_type_knows_growfs(ptid), + .no_auto = FLAGS_SET(flags, SD_GPT_FLAG_NO_AUTO) && gpt_partition_type_knows_no_auto(type), + .read_only = FLAGS_SET(flags, SD_GPT_FLAG_READ_ONLY) && gpt_partition_type_knows_read_only(type), + .growfs = FLAGS_SET(flags, SD_GPT_FLAG_GROWFS) && gpt_partition_type_knows_growfs(type), }; return 1; /* found! */ @@ -269,6 +272,7 @@ int patch_partition( _cleanup_(fdisk_unref_partitionp) struct fdisk_partition *pa = NULL; _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL; bool tweak_no_auto, tweak_read_only, tweak_growfs; + GptPartitionType type; int r, fd; assert(device); @@ -313,16 +317,18 @@ int patch_partition( return log_error_errno(r, "Failed to update partition UUID: %m"); } + type = gpt_partition_type_from_uuid(info->type); + /* Tweak the read-only flag, but only if supported by the partition type */ tweak_no_auto = FLAGS_SET(change, PARTITION_NO_AUTO) && - gpt_partition_type_knows_no_auto(info->type); + gpt_partition_type_knows_no_auto(type); tweak_read_only = FLAGS_SET(change, PARTITION_READ_ONLY) && - gpt_partition_type_knows_read_only(info->type); + gpt_partition_type_knows_read_only(type); tweak_growfs = FLAGS_SET(change, PARTITION_GROWFS) && - gpt_partition_type_knows_growfs(info->type); + gpt_partition_type_knows_growfs(type); if (change & PARTITION_FLAGS) { uint64_t flags; diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c index 8104e9c82e9..bf521980e26 100644 --- a/src/sysupdate/sysupdate-resource.c +++ b/src/sysupdate/sysupdate-resource.c @@ -194,7 +194,7 @@ static int resource_load_from_blockdev(Resource *rr) { continue; /* Check if partition type matches */ - if (rr->partition_type_set && !sd_id128_equal(pinfo.type, rr->partition_type)) + if (rr->partition_type_set && !sd_id128_equal(pinfo.type, rr->partition_type.uuid)) continue; /* A label of "_empty" means "not used so far" for us */ diff --git a/src/sysupdate/sysupdate-resource.h b/src/sysupdate/sysupdate-resource.h index 86be0d33893..3209988c24f 100644 --- a/src/sysupdate/sysupdate-resource.h +++ b/src/sysupdate/sysupdate-resource.h @@ -5,8 +5,7 @@ #include #include -#include "sd-id128.h" - +#include "gpt.h" #include "hashmap.h" #include "macro.h" @@ -74,7 +73,7 @@ struct Resource { char *path; bool path_auto; /* automatically find root path (only available if target resource, not source resource) */ char **patterns; - sd_id128_t partition_type; + GptPartitionType partition_type; bool partition_type_set; /* All instances of this resource we found */ diff --git a/src/sysupdate/sysupdate-transfer.c b/src/sysupdate/sysupdate-transfer.c index d6705cd12ec..0c3d65a00dc 100644 --- a/src/sysupdate/sysupdate-transfer.c +++ b/src/sysupdate/sysupdate-transfer.c @@ -344,7 +344,7 @@ static int config_parse_resource_ptype( assert(rvalue); - r = gpt_partition_type_uuid_from_string(rvalue, &rr->partition_type); + r = gpt_partition_type_from_string(rvalue, &rr->partition_type); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed parse partition type, ignoring: %s", rvalue); @@ -654,18 +654,18 @@ int transfer_vacuum( if (t->target.n_empty + t->target.n_instances < 2) return log_error_errno(SYNTHETIC_ERRNO(ENOSPC), "Partition table has less than two partition slots of the right type " SD_ID128_UUID_FORMAT_STR " (%s), refusing.", - SD_ID128_FORMAT_VAL(t->target.partition_type), - gpt_partition_type_uuid_to_string(t->target.partition_type)); + SD_ID128_FORMAT_VAL(t->target.partition_type.uuid), + gpt_partition_type_uuid_to_string(t->target.partition_type.uuid)); if (space > t->target.n_empty + t->target.n_instances) return log_error_errno(SYNTHETIC_ERRNO(ENOSPC), "Partition table does not have enough partition slots of right type " SD_ID128_UUID_FORMAT_STR " (%s) for operation.", - SD_ID128_FORMAT_VAL(t->target.partition_type), - gpt_partition_type_uuid_to_string(t->target.partition_type)); + SD_ID128_FORMAT_VAL(t->target.partition_type.uuid), + gpt_partition_type_uuid_to_string(t->target.partition_type.uuid)); if (space == t->target.n_empty + t->target.n_instances) return log_error_errno(SYNTHETIC_ERRNO(ENOSPC), "Asked to empty all partition table slots of the right type " SD_ID128_UUID_FORMAT_STR " (%s), can't allow that. One instance must always remain.", - SD_ID128_FORMAT_VAL(t->target.partition_type), - gpt_partition_type_uuid_to_string(t->target.partition_type)); + SD_ID128_FORMAT_VAL(t->target.partition_type.uuid), + gpt_partition_type_uuid_to_string(t->target.partition_type.uuid)); rm = LESS_BY(space, t->target.n_empty); remain = LESS_BY(t->target.n_instances, rm); @@ -858,7 +858,7 @@ int transfer_acquire_instance(Transfer *t, Instance *i) { r = find_suitable_partition( t->target.path, i->metadata.size, - t->target.partition_type_set ? &t->target.partition_type : NULL, + t->target.partition_type_set ? &t->target.partition_type.uuid : NULL, &t->partition_info); if (r < 0) return r; diff --git a/src/test/test-gpt.c b/src/test/test-gpt.c index 8c313c66cc8..377b79f1556 100644 --- a/src/test/test-gpt.c +++ b/src/test/test-gpt.c @@ -19,13 +19,13 @@ TEST(gpt_types_against_architectures) { for (Architecture a = 0; a < _ARCHITECTURE_MAX; a++) FOREACH_STRING(suffix, "", "-verity", "-verity-sig") { _cleanup_free_ char *joined = NULL; - sd_id128_t id; + GptPartitionType type; joined = strjoin(prefix, architecture_to_string(a), suffix); if (!joined) return (void) log_oom(); - r = gpt_partition_type_uuid_from_string(joined, &id); + r = gpt_partition_type_from_string(joined, &type); if (r < 0) { printf("%s %s\n", RED_CROSS_MARK(), joined); continue; @@ -34,15 +34,15 @@ TEST(gpt_types_against_architectures) { printf("%s %s\n", GREEN_CHECK_MARK(), joined); if (streq(prefix, "root-") && streq(suffix, "")) - assert_se(gpt_partition_type_is_root(id)); + assert_se(type.designator == PARTITION_ROOT); if (streq(prefix, "root-") && streq(suffix, "-verity")) - assert_se(gpt_partition_type_is_root_verity(id)); + assert_se(type.designator == PARTITION_ROOT_VERITY); if (streq(prefix, "usr-") && streq(suffix, "")) - assert_se(gpt_partition_type_is_usr(id)); + assert_se(type.designator == PARTITION_USR); if (streq(prefix, "usr-") && streq(suffix, "-verity")) - assert_se(gpt_partition_type_is_usr_verity(id)); + assert_se(type.designator == PARTITION_USR_VERITY); - assert_se(gpt_partition_type_uuid_to_arch(id) == a); + assert_se(type.arch == a); } } From 00428745e3d1e42fe4481fc8a5c50d6316d4282a Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 14 Oct 2022 12:40:28 +0200 Subject: [PATCH 2/4] repart: Use first unused partition number for new partitions If we skip some partition types in a first run of systemd-repart, we don't want their partition numbers to be different than usual, so let's change the allocation of partition numbers to account for that. --- src/partition/repart.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/partition/repart.c b/src/partition/repart.c index 20f764ee1ca..c2051de6596 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -1025,21 +1025,30 @@ static int context_grow_partitions(Context *context) { return 0; } -static void context_place_partitions(Context *context) { +static uint64_t find_first_unused_partno(Context *context) { uint64_t partno = 0; assert(context); - /* Determine next partition number to assign */ - LIST_FOREACH(partitions, p, context->partitions) { - if (!PARTITION_EXISTS(p)) - continue; + for (bool changed = true; changed;) { + changed = false; - assert(p->partno != UINT64_MAX); - if (p->partno >= partno) - partno = p->partno + 1; + LIST_FOREACH(partitions, p, context->partitions) { + if (p->partno != UINT64_MAX && p->partno == partno) { + partno++; + changed = true; + break; + } + } } + return partno; +} + +static void context_place_partitions(Context *context) { + + assert(context); + for (size_t i = 0; i < context->n_free_areas; i++) { FreeArea *a = context->free_areas[i]; _unused_ uint64_t left; @@ -1062,7 +1071,7 @@ static void context_place_partitions(Context *context) { continue; p->offset = start; - p->partno = partno++; + p->partno = find_first_unused_partno(context); assert(left >= p->new_size); start += p->new_size; From 81d1098bc1f6b607c57798932c4117a118d84929 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 14 Oct 2022 12:06:55 +0200 Subject: [PATCH 3/4] repart: Add --include/--exclude-partitions Let's allow filtering the partitions to operate on by partition type UUID. This is necessary when building bootable images with a verity protected root/usr partition as we can only build the UKI image when we have the verity roothash which means we cannot populate the EFI partition yet when we run repart initially to determine the verity roothash. --- man/systemd-repart.xml | 17 +++++++ src/partition/repart.c | 106 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) diff --git a/man/systemd-repart.xml b/man/systemd-repart.xml index 3585cbf1076..6559fceedb4 100644 --- a/man/systemd-repart.xml +++ b/man/systemd-repart.xml @@ -363,6 +363,23 @@ if is enabled. + + PARTITION + PARTITION + + These options specify which partition types systemd-repart should + operate on. If is used, all partitions that aren't specified + are excluded. If is used, all partitions that are specified + are excluded. Both options take a comma separated list of GPT partition type UUIDs or identifiers + (see Type= in + repart.d5). All + partitions that are excluded using these options are still taken into account when calculating the + sizes and offsets of other partitions, but aren't actually written to the disk image. The net effect + of this option is that if you run systemd-repart again without these options, the + missing partitions will be added as if they had not been excluded the first time + systemd-repart was executed. + + diff --git a/src/partition/repart.c b/src/partition/repart.c index c2051de6596..f4c37087662 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -103,6 +103,14 @@ static enum { EMPTY_CREATE, /* create disk as loopback file, create a partition table always */ } arg_empty = EMPTY_REFUSE; +typedef enum { + FILTER_PARTITIONS_NONE, + FILTER_PARTITIONS_EXCLUDE, + FILTER_PARTITIONS_INCLUDE, + _FILTER_PARTITIONS_MAX, + _FILTER_PARTITIONS_INVALID = -EINVAL, +} FilterPartitionsType; + static bool arg_dry_run = true; static const char *arg_node = NULL; static char *arg_root = NULL; @@ -128,6 +136,9 @@ static uint32_t arg_tpm2_pcr_mask = UINT32_MAX; static char *arg_tpm2_public_key = NULL; static uint32_t arg_tpm2_public_key_pcr_mask = UINT32_MAX; static bool arg_split = false; +static sd_id128_t *arg_filter_partitions = NULL; +static size_t arg_filter_partitions_size = 0; +static FilterPartitionsType arg_filter_partitions_type = FILTER_PARTITIONS_NONE; STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); @@ -137,6 +148,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_private_key, EVP_PKEY_freep); STATIC_DESTRUCTOR_REGISTER(arg_certificate, X509_freep); STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep); STATIC_DESTRUCTOR_REGISTER(arg_tpm2_public_key, freep); +STATIC_DESTRUCTOR_REGISTER(arg_filter_partitions, freep); typedef struct Partition Partition; typedef struct FreeArea FreeArea; @@ -372,6 +384,19 @@ static void partition_foreignize(Partition *p) { p->verity = VERITY_OFF; } +static bool partition_skip(const Partition *p) { + assert(p); + + if (arg_filter_partitions_type == FILTER_PARTITIONS_NONE) + return false; + + for (size_t i = 0; i < arg_filter_partitions_size; i++) + if (sd_id128_equal(p->type.uuid, arg_filter_partitions[i])) + return arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE; + + return arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE; +} + static Partition* partition_unlink_and_free(Context *context, Partition *p) { if (!p) return NULL; @@ -2930,6 +2955,9 @@ static int context_wipe_and_discard(Context *context, bool from_scratch) { if (!p->allocated_to_area) continue; + if (partition_skip(p)) + continue; + r = context_wipe_partition(context, p); if (r < 0) return r; @@ -3187,6 +3215,9 @@ static int context_copy_blocks(Context *context) { if (PARTITION_EXISTS(p)) /* Never copy over existing partitions */ continue; + if (partition_skip(p)) + continue; + assert(p->new_size != UINT64_MAX); assert(p->copy_blocks_size != UINT64_MAX); assert(p->new_size >= p->copy_blocks_size); @@ -3537,6 +3568,9 @@ static int context_mkfs(Context *context) { if (p->copy_blocks_fd >= 0) continue; + if (partition_skip(p)) + continue; + assert(p->offset != UINT64_MAX); assert(p->new_size != UINT64_MAX); @@ -3708,6 +3742,9 @@ static int context_verity_hash(Context *context) { if (p->verity != VERITY_HASH) continue; + if (partition_skip(p)) + continue; + assert_se(dp = p->siblings[VERITY_DATA]); assert(!dp->dropped); @@ -3870,6 +3907,9 @@ static int context_verity_sig(Context *context) { if (p->verity != VERITY_SIG) continue; + if (partition_skip(p)) + continue; + assert_se(hp = p->siblings[VERITY_HASH]); assert(!hp->dropped); @@ -4171,6 +4211,9 @@ static int context_mangle_partitions(Context *context) { if (p->dropped) continue; + if (partition_skip(p)) + continue; + assert(p->new_size != UINT64_MAX); assert(p->offset != UINT64_MAX); assert(p->partno != UINT64_MAX); @@ -4411,6 +4454,9 @@ static int context_split(Context *context) { if (!p->split_name_resolved) continue; + if (partition_skip(p)) + continue; + fname = strjoin(base, ".", p->split_name_resolved, ext); if (!fname) return log_oom(); @@ -5180,6 +5226,32 @@ static int context_minimize(Context *context) { return 0; } +static int parse_filter_partitions(const char *p) { + int r; + + for (;;) { + _cleanup_free_ char *name = NULL; + GptPartitionType type; + + r = extract_first_word(&p, &name, ",", EXTRACT_CUNESCAPE|EXTRACT_DONT_COALESCE_SEPARATORS); + if (r == 0) + break; + if (r < 0) + return log_error_errno(r, "Failed to extract partition designator: %s", optarg); + + r = gpt_partition_type_from_string(name, &type); + if (r < 0) + return log_error_errno(r, "'%s' is not a valid partition designator", name); + + if (!GREEDY_REALLOC(arg_filter_partitions, arg_filter_partitions_size + 1)) + return log_oom(); + + arg_filter_partitions[arg_filter_partitions_size++] = type.uuid; + } + + return 0; +} + static int help(void) { _cleanup_free_ char *link = NULL; int r; @@ -5222,6 +5294,10 @@ static int help(void) { " --json=pretty|short|off\n" " Generate JSON output\n" " --split=BOOL Whether to generate split artifacts\n" + " --include-partitions=PARTITION1,PARTITION2,PARTITION3,…\n" + " Only operate on partitions of the specified types\n" + " --exclude-partitions=PARTITION1,PARTITION2,PARTITION3,…\n" + " Don't operate on partitions of the specified types\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -5257,6 +5333,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_TPM2_PUBLIC_KEY, ARG_TPM2_PUBLIC_KEY_PCRS, ARG_SPLIT, + ARG_INCLUDE_PARTITIONS, + ARG_EXCLUDE_PARTITIONS, }; static const struct option options[] = { @@ -5284,6 +5362,8 @@ static int parse_argv(int argc, char *argv[]) { { "tpm2-public-key", required_argument, NULL, ARG_TPM2_PUBLIC_KEY }, { "tpm2-public-key-pcrs", required_argument, NULL, ARG_TPM2_PUBLIC_KEY_PCRS }, { "split", required_argument, NULL, ARG_SPLIT }, + { "include-partitions", required_argument, NULL, ARG_INCLUDE_PARTITIONS }, + { "exclude-partitions", required_argument, NULL, ARG_EXCLUDE_PARTITIONS }, {} }; @@ -5538,6 +5618,32 @@ static int parse_argv(int argc, char *argv[]) { arg_split = r; break; + case ARG_INCLUDE_PARTITIONS: + if (arg_filter_partitions_type == FILTER_PARTITIONS_EXCLUDE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Combination of --include-partitions= and --exclude-partitions= is invalid."); + + r = parse_filter_partitions(optarg); + if (r < 0) + return r; + + arg_filter_partitions_type = FILTER_PARTITIONS_INCLUDE; + + break; + + case ARG_EXCLUDE_PARTITIONS: + if (arg_filter_partitions_type == FILTER_PARTITIONS_INCLUDE) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Combination of --include-partitions= and --exclude-partitions= is invalid."); + + r = parse_filter_partitions(optarg); + if (r < 0) + return r; + + arg_filter_partitions_type = FILTER_PARTITIONS_EXCLUDE; + + break; + case '?': return -EINVAL; From 56bb434e9b33d74bdd445ac0e7d263254ad93e5e Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Fri, 11 Nov 2022 14:26:45 +0100 Subject: [PATCH 4/4] repart: Add integration test for --include/--exclude-partitions --- test/units/testsuite-58.sh | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/units/testsuite-58.sh b/test/units/testsuite-58.sh index f726dd548bd..121fabc0afe 100755 --- a/test/units/testsuite-58.sh +++ b/test/units/testsuite-58.sh @@ -133,6 +133,40 @@ SizeMaxBytes=64M PaddingMinBytes=92M EOF + systemd-repart --definitions="$defs" \ + --dry-run=no \ + --seed="$seed" \ + --include-partitions=home,swap \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 2097118 +$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"" + + systemd-repart --definitions="$defs" \ + --dry-run=no \ + --seed="$seed" \ + --exclude-partitions=root \ + "$imgs/zzz" + + output=$(sfdisk -d "$imgs/zzz" | grep -v -e 'sector-size' -e '^$') + + assert_eq "$output" "label: gpt +label-id: 1D2CE291-7CCE-4F7D-BC83-FDB49AD74EBD +device: $imgs/zzz +unit: sectors +first-lba: 2048 +last-lba: 2097118 +$imgs/zzz1 : start= 2048, size= 591856, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915, uuid=4980595D-D74A-483A-AA9E-9903879A0EE5, name=\"home-first\", attrs=\"GUID:59\" +$imgs/zzz4 : start= 1777624, size= 131072, type=0657FD6D-A4AB-43C4-84E5-0933C84B4F4F, uuid=78C92DB8-3D2B-4823-B0DC-792B78F66F1E, name=\"swap\"" + systemd-repart --definitions="$defs" \ --dry-run=no \ --seed="$seed" \