]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysupdate: split out url config parser into new file 42871/head
authorLennart Poettering <lennart@amutable.com>
Thu, 18 Jun 2026 15:58:09 +0000 (17:58 +0200)
committerLennart Poettering <lennart@amutable.com>
Fri, 3 Jul 2026 14:09:49 +0000 (16:09 +0200)
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.

src/sysupdate/meson.build
src/sysupdate/sysupdate-config.c [new file with mode: 0644]
src/sysupdate/sysupdate-config.h [new file with mode: 0644]
src/sysupdate/sysupdate-feature.c
src/sysupdate/sysupdate-transfer.c

index b6f94366065681979962bbfb1c78cfc59e1e824f..ec873269047e89802c381e2253d6d9f37fceab05 100644 (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',
diff --git a/src/sysupdate/sysupdate-config.c b/src/sysupdate/sysupdate-config.c
new file mode 100644 (file)
index 0000000..7f553a9
--- /dev/null
@@ -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;
+}
diff --git a/src/sysupdate/sysupdate-config.h b/src/sysupdate/sysupdate-config.h
new file mode 100644 (file)
index 0000000..bd972d5
--- /dev/null
@@ -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);
index 45a913f7c16a39aa99d7b5c70968ce2a64e00d40..49c2e77988b93ba8b6a74fdf3ea029862efcafee 100644 (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);
 
index 08396d61b1c0c5520a7dcff08af831a1add2c004..2a29448836aa7bfe2119c22429a278b0526d6e54 100644 (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);
-
-        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;
-        }
+        Transfer *t = ASSERT_PTR(userdata);
 
-        r = strv_push(s, TAKE_PTR(resolved));
-        if (r < 0)
-                return log_oom();
+        /* Here we expect userdata to point to our Transfer object, but config_parse_url_specifiers() wants
+         * the root dir there, hence fix this up */
 
-        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         },
                 {}
         };