diff --git a/src/sysupdate/sysupdate-config.c b/src/sysupdate/sysupdate-config.c index 45794b5a21..1b4a025228 100644 --- a/src/sysupdate/sysupdate-config.c +++ b/src/sysupdate/sysupdate-config.c @@ -34,7 +34,7 @@ int config_parse_url_specifiers( } _cleanup_free_ char *resolved = NULL; - r = specifier_printf(rvalue, NAME_MAX, system_and_tmp_specifier_table, root, NULL, &resolved); + r = specifier_printf(rvalue, SIZE_MAX, system_and_tmp_specifier_table, root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in %s=, ignoring: %s", lvalue, rvalue); @@ -90,7 +90,7 @@ int config_parse_url_specifiers_many( } _cleanup_free_ char *resolved = NULL; - r = specifier_printf(rvalue, NAME_MAX, system_and_tmp_specifier_table, root, NULL, &resolved); + r = specifier_printf(rvalue, SIZE_MAX, system_and_tmp_specifier_table, root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in %s=, ignoring: %s", lvalue, rvalue); diff --git a/src/sysupdate/sysupdate-transfer.c b/src/sysupdate/sysupdate-transfer.c index e80dcaf39a..226dbd93ae 100644 --- a/src/sysupdate/sysupdate-transfer.c +++ b/src/sysupdate/sysupdate-transfer.c @@ -134,6 +134,11 @@ static int config_parse_protect_version( assert(rvalue); + if (isempty(rvalue)) { + *protected_versions = strv_free(*protected_versions); + return 0; + } + r = specifier_printf(rvalue, NAME_MAX, system_and_tmp_specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, @@ -173,6 +178,11 @@ static int config_parse_min_version( assert(rvalue); + if (isempty(rvalue)) { + *version = mfree(*version); + return 0; + } + r = specifier_printf(rvalue, NAME_MAX, system_and_tmp_specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, @@ -228,7 +238,12 @@ static int config_parse_current_symlink( assert(rvalue); - r = specifier_printf(rvalue, NAME_MAX, system_and_tmp_specifier_table, t->context->root, NULL, &resolved); + if (isempty(rvalue)) { + *current_symlink = mfree(*current_symlink); + return 0; + } + + r = specifier_printf(rvalue, PATH_MAX-1, system_and_tmp_specifier_table, t->context->root, NULL, &resolved); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to expand specifiers in CurrentSymlink=, ignoring: %s", rvalue); @@ -415,6 +430,12 @@ static int config_parse_resource_ptype( assert(rvalue); + if (isempty(rvalue)) { + rr->partition_type = (GptPartitionType) {}; + rr->partition_type_set = false; + return 0; + } + r = gpt_partition_type_from_string(rvalue, &rr->partition_type); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, @@ -443,6 +464,12 @@ static int config_parse_partition_uuid( assert(rvalue); + if (isempty(rvalue)) { + t->partition_uuid = SD_ID128_NULL; + t->partition_uuid_set = false; + return 0; + } + r = sd_id128_from_string(rvalue, &t->partition_uuid); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, @@ -471,7 +498,13 @@ static int config_parse_partition_flags( assert(rvalue); - r = safe_atou64(rvalue, &t->partition_flags); + if (isempty(rvalue)) { + t->partition_flags = 0; + t->partition_flags_set = false; + return 0; + } + + r = safe_atoux64(rvalue, &t->partition_flags); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse partition flags, ignoring: %s", rvalue); @@ -608,6 +641,11 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), "Target Type= must be one of partition, regular-file, directory, subvolume."); + if (t->target.type == RESOURCE_PARTITION && !t->target.partition_type_set) { + t->target.partition_type = gpt_partition_type_from_uuid(SD_GPT_LINUX_GENERIC); + t->target.partition_type_set = true; + } + if ((IN_SET(t->source.type, RESOURCE_URL_FILE, RESOURCE_PARTITION, RESOURCE_REGULAR_FILE) && !IN_SET(t->target.type, RESOURCE_PARTITION, RESOURCE_REGULAR_FILE)) || (IN_SET(t->source.type, RESOURCE_URL_TAR, RESOURCE_TAR, RESOURCE_DIRECTORY, RESOURCE_SUBVOLUME) && @@ -730,7 +768,8 @@ static void transfer_remove_temporary(Transfer *t) { if (!IN_SET(t->target.type, RESOURCE_REGULAR_FILE, RESOURCE_DIRECTORY, RESOURCE_SUBVOLUME)) return; - /* Removes all temporary files/dirs from previous runs in the target directory, i.e. all those starting with '.#' */ + /* Removes all incomplete files/dirs from previous runs in the target directory. Clean both the + * current partial sysupdate prefix and the legacy '.#' prefix. */ d = opendir(t->target.path); if (!d) { @@ -752,7 +791,7 @@ static void transfer_remove_temporary(Transfer *t) { break; } - if (!startswith(de->d_name, ".#")) + if (!STARTSWITH_SET(de->d_name, ".#", ".sysupdate.partial.")) continue; r = rm_rf_child(dirfd(d), de->d_name, REMOVE_PHYSICAL|REMOVE_SUBVOLUME|REMOVE_CHMOD); @@ -1269,8 +1308,7 @@ int transfer_compute_temporary_paths(Transfer *t, Instance *i, InstanceMetadata if (!r) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Formatted pattern is not suitable as GPT partition label, refusing: %s", formatted_pattern); - if (!t->target.partition_type_set) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Partition type must be set for partition targets."); + assert(t->target.partition_type_set); /* Derive temporary partition type UUIDs for partial/pending states from the configured * partition type. This avoids the need for label prefixes. */