sysupdate: split out url config parser into new file

These are located at two distinct places, and are very similar, let's
put them in a common place.

This is preparation for reusing them later.
This commit is contained in:
Lennart Poettering
2026-07-03 16:09:49 +02:00
parent 55127751cc
commit 138829b784
5 changed files with 134 additions and 96 deletions
+1
View File
@@ -3,6 +3,7 @@
systemd_sysupdate_sources = files(
'sysupdate-cache.c',
'sysupdate-cleanup.c',
'sysupdate-config.c',
'sysupdate-feature.c',
'sysupdate-instance.c',
'sysupdate-partition.c',
+92
View File
@@ -0,0 +1,92 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "log.h"
#include "specifier.h"
#include "string-util.h"
#include "strv.h"
#include "sysupdate-config.h"
#include "web-util.h"
int config_parse_url_specifiers(
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) {
const char *root = userdata;
char **s = ASSERT_PTR(data);
int r;
assert(rvalue);
if (isempty(rvalue)) {
*s = mfree(*s);
return 0;
}
_cleanup_free_ char *resolved = NULL;
r = specifier_printf(rvalue, NAME_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);
return 0;
}
if (!http_url_is_valid(resolved)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s= URL is not valid, ignoring: %s", lvalue, rvalue);
return 0;
}
return free_and_replace(*s, resolved);
}
int config_parse_url_specifiers_many(
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) {
const char *root = userdata;
char ***s = ASSERT_PTR(data);
int r;
assert(rvalue);
if (isempty(rvalue)) {
*s = strv_free(*s);
return 0;
}
_cleanup_free_ char *resolved = NULL;
r = specifier_printf(rvalue, NAME_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);
return 0;
}
if (!http_url_is_valid(resolved)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s= URL is not valid, ignoring: %s", lvalue, rvalue);
return 0;
}
if (strv_consume(s, TAKE_PTR(resolved)) < 0)
return log_oom();
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser-forward.h"
CONFIG_PARSER_PROTOTYPE(config_parse_url_specifiers);
CONFIG_PARSER_PROTOTYPE(config_parse_url_specifiers_many);
+1 -41
View File
@@ -4,10 +4,9 @@
#include "conf-parser.h"
#include "hash-funcs.h"
#include "path-util.h"
#include "specifier.h"
#include "string-util.h"
#include "sysupdate-config.h"
#include "sysupdate-feature.h"
#include "web-util.h"
static Feature *feature_free(Feature *f) {
if (!f)
@@ -42,45 +41,6 @@ DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(feature_hash_ops,
char, string_hash_func, string_compare_func,
Feature, feature_unref);
static int config_parse_url_specifiers(
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) {
char **s = ASSERT_PTR(data);
const char *root = ASSERT_PTR(userdata);
_cleanup_free_ char *resolved = NULL;
int r;
assert(rvalue);
if (isempty(rvalue)) {
*s = mfree(*s);
return 0;
}
r = specifier_printf(rvalue, NAME_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);
return 0;
}
if (!http_url_is_valid(resolved)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s= URL is not valid, ignoring: %s", lvalue, rvalue);
return 0;
}
return free_and_replace(*s, resolved);
}
int feature_read_definition(Feature *f, const char *root, const char *path, const char *const *dirs) {
assert(f);
+33 -55
View File
@@ -36,6 +36,7 @@
#include "sync-util.h"
#include "sysupdate.h"
#include "sysupdate-cleanup.h"
#include "sysupdate-config.h"
#include "sysupdate-feature.h"
#include "sysupdate-instance.h"
#include "sysupdate-pattern.h"
@@ -182,7 +183,7 @@ static int config_parse_min_version(
return free_and_replace(*version, resolved);
}
static int config_parse_url_specifiers(
static int config_parse_transfer_url_specifiers_many(
const char *unit,
const char *filename,
unsigned line,
@@ -193,36 +194,13 @@ static int config_parse_url_specifiers(
const char *rvalue,
void *data,
void *userdata) {
char ***s = ASSERT_PTR(data);
Transfer *t = ASSERT_PTR(userdata);
_cleanup_free_ char *resolved = NULL;
int r;
assert(rvalue);
/* Here we expect userdata to point to our Transfer object, but config_parse_url_specifiers() wants
* the root dir there, hence fix this up */
if (isempty(rvalue)) {
*s = strv_free(*s);
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,
"Failed to expand specifiers in %s=, ignoring: %s", lvalue, rvalue);
return 0;
}
if (!http_url_is_valid(resolved)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s= URL is not valid, ignoring: %s", lvalue, rvalue);
return 0;
}
r = strv_push(s, TAKE_PTR(resolved));
if (r < 0)
return log_oom();
return 0;
return config_parse_url_specifiers_many(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, t->context->root);
}
static int config_parse_current_symlink(
@@ -510,33 +488,33 @@ int transfer_read_definition(Transfer *t, const char *path, const char **dirs, H
assert(t);
ConfigTableItem table[] = {
{ "Transfer", "MinVersion", config_parse_min_version, 0, &t->min_version },
{ "Transfer", "ProtectVersion", config_parse_protect_version, 0, &t->protected_versions },
{ "Transfer", "Verify", config_parse_bool, 0, &t->verify },
{ "Transfer", "ChangeLog", config_parse_url_specifiers, 0, &t->changelog },
{ "Transfer", "AppStream", config_parse_url_specifiers, 0, &t->appstream },
{ "Transfer", "Features", config_parse_strv, 0, &t->features },
{ "Transfer", "RequisiteFeatures", config_parse_strv, 0, &t->requisite_features },
{ "Source", "Type", config_parse_resource_type, 0, &t->source.type },
{ "Source", "Path", config_parse_resource_path, 0, &t->source },
{ "Source", "PathRelativeTo", config_parse_resource_path_relto, 0, &t->source.path_relative_to },
{ "Source", "MatchPattern", config_parse_resource_pattern, 0, &t->source.patterns },
{ "Target", "Type", config_parse_resource_type, 0, &t->target.type },
{ "Target", "Path", config_parse_resource_path, 0, &t->target },
{ "Target", "PathRelativeTo", config_parse_resource_path_relto, 0, &t->target.path_relative_to },
{ "Target", "MatchPattern", config_parse_resource_pattern, 0, &t->target.patterns },
{ "Target", "MatchPartitionType", config_parse_resource_ptype, 0, &t->target },
{ "Target", "PartitionUUID", config_parse_partition_uuid, 0, t },
{ "Target", "PartitionFlags", config_parse_partition_flags, 0, t },
{ "Target", "PartitionNoAuto", config_parse_tristate, 0, &t->no_auto },
{ "Target", "PartitionGrowFileSystem", config_parse_tristate, 0, &t->growfs },
{ "Target", "ReadOnly", config_parse_tristate, 0, &t->read_only },
{ "Target", "Mode", config_parse_mode, 0, &t->mode },
{ "Target", "TriesLeft", config_parse_uint64, 0, &t->tries_left },
{ "Target", "TriesDone", config_parse_uint64, 0, &t->tries_done },
{ "Target", "InstancesMax", config_parse_instances_max, 0, &t->instances_max },
{ "Target", "RemoveTemporary", config_parse_bool, 0, &t->remove_temporary },
{ "Target", "CurrentSymlink", config_parse_current_symlink, 0, &t->current_symlink },
{ "Transfer", "MinVersion", config_parse_min_version, 0, &t->min_version },
{ "Transfer", "ProtectVersion", config_parse_protect_version, 0, &t->protected_versions },
{ "Transfer", "Verify", config_parse_bool, 0, &t->verify },
{ "Transfer", "ChangeLog", config_parse_transfer_url_specifiers_many, 0, &t->changelog },
{ "Transfer", "AppStream", config_parse_transfer_url_specifiers_many, 0, &t->appstream },
{ "Transfer", "Features", config_parse_strv, 0, &t->features },
{ "Transfer", "RequisiteFeatures", config_parse_strv, 0, &t->requisite_features },
{ "Source", "Type", config_parse_resource_type, 0, &t->source.type },
{ "Source", "Path", config_parse_resource_path, 0, &t->source },
{ "Source", "PathRelativeTo", config_parse_resource_path_relto, 0, &t->source.path_relative_to },
{ "Source", "MatchPattern", config_parse_resource_pattern, 0, &t->source.patterns },
{ "Target", "Type", config_parse_resource_type, 0, &t->target.type },
{ "Target", "Path", config_parse_resource_path, 0, &t->target },
{ "Target", "PathRelativeTo", config_parse_resource_path_relto, 0, &t->target.path_relative_to },
{ "Target", "MatchPattern", config_parse_resource_pattern, 0, &t->target.patterns },
{ "Target", "MatchPartitionType", config_parse_resource_ptype, 0, &t->target },
{ "Target", "PartitionUUID", config_parse_partition_uuid, 0, t },
{ "Target", "PartitionFlags", config_parse_partition_flags, 0, t },
{ "Target", "PartitionNoAuto", config_parse_tristate, 0, &t->no_auto },
{ "Target", "PartitionGrowFileSystem", config_parse_tristate, 0, &t->growfs },
{ "Target", "ReadOnly", config_parse_tristate, 0, &t->read_only },
{ "Target", "Mode", config_parse_mode, 0, &t->mode },
{ "Target", "TriesLeft", config_parse_uint64, 0, &t->tries_left },
{ "Target", "TriesDone", config_parse_uint64, 0, &t->tries_done },
{ "Target", "InstancesMax", config_parse_instances_max, 0, &t->instances_max },
{ "Target", "RemoveTemporary", config_parse_bool, 0, &t->remove_temporary },
{ "Target", "CurrentSymlink", config_parse_current_symlink, 0, &t->current_symlink },
{}
};