From: Daan De Meyer Date: Sun, 8 Sep 2024 14:09:19 +0000 (+0200) Subject: sysupdate: Add --transfer-source= X-Git-Tag: v257-rc1~511 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c1852f9d5fad0fd7baf2ea88339c3eaa5a60290d;p=thirdparty%2Fsystemd.git sysupdate: Add --transfer-source= In mkosi, I want to add a sysupdate verb to wrap systemd-sysupdate. The definitions will be picked up from mkosi.sysupdate/ and passed to systemd-sysupdate. I want users to be able to write transfer definitions that are independent of the output directory used by mkosi. To make this possible, it should be possible to specify the directory that transfer sources should be looked up in on the sysupdate command line. Let's allow this via a new --transfer-source= option. Additionally, transfer sources that want to take advantage of this feature should specify PathRelativeTo=directory to indicate the configured Path= is interpreted relative to the tranfer source directory specified on the CLI. This allows for the following transfer definition to be put in mkosi.sysupdate: """ [Transfer] ProtectVersion=%A [Source] Type=regular-file Path=/ PathRelativeTo=directory MatchPattern=ParticleOS_@v.usr-%a.@u.raw [Target] Type=partition Path=auto MatchPattern=ParticleOS_@v MatchPartitionType=usr PartitionFlags=0 ReadOnly=1 """ --- diff --git a/man/systemd-sysupdate.xml b/man/systemd-sysupdate.xml index f57a17b79ac..f7f1521a5d4 100644 --- a/man/systemd-sysupdate.xml +++ b/man/systemd-sysupdate.xml @@ -305,6 +305,15 @@ + + + + Takes a path as its argument. When specified, all transfer sources configured with + PathRelativeTo=explicit will be interpreted relative to the specified path. + + + + diff --git a/man/sysupdate.d.xml b/man/sysupdate.d.xml index ef3b21d29d4..070d6307355 100644 --- a/man/sysupdate.d.xml +++ b/man/sysupdate.d.xml @@ -627,15 +627,26 @@ PathRelativeTo= - Specifies what partition Path= should be relative to. Takes one of - root, esp, xbootldr, or boot. - If unspecified, defaults to root. + Specifies what anchor point Path= should be relative to. Takes one + of root, esp, xbootldr, + boot or directory. If unspecified, defaults to + root. + + If set to root, esp, xbootldr, + the specified Path= will be resolved relative to the mount point of the + corresponding partition, as defined by the + Boot Loader + Specification. If set to boot, the specified Path= will be resolved relative to the mount point of the $BOOT partition (i.e. the ESP or XBOOTLDR), as defined by the Boot Loader Specification. + If set to explicit, the specified Path= will be + resolved relative to the directory specified with when invoking + systemd-sysupdate. + The values esp, xbootldr, and boot are only supported when Type= is set to regular-file or directory. diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c index 94308998971..2f7a0880924 100644 --- a/src/sysupdate/sysupdate-resource.c +++ b/src/sysupdate/sysupdate-resource.c @@ -555,6 +555,7 @@ Instance* resource_find_instance(Resource *rr, const char *version) { int resource_resolve_path( Resource *rr, const char *root, + const char *relative_to_directory, const char *node) { _cleanup_free_ char *p = NULL; @@ -648,7 +649,13 @@ int resource_resolve_path( _cleanup_free_ char *resolved = NULL, *relative_to = NULL; ChaseFlags chase_flags = CHASE_PREFIX_ROOT; - if (rr->path_relative_to == PATH_RELATIVE_TO_ROOT) { + if (rr->path_relative_to == PATH_RELATIVE_TO_EXPLICIT) { + assert(relative_to_directory); + + relative_to = strdup(relative_to_directory); + if (!relative_to) + return log_oom(); + } else if (rr->path_relative_to == PATH_RELATIVE_TO_ROOT) { relative_to = strdup(empty_to_root(root)); if (!relative_to) return log_oom(); @@ -715,6 +722,7 @@ static const char *path_relative_to_table[_PATH_RELATIVE_TO_MAX] = { [PATH_RELATIVE_TO_ESP] = "esp", [PATH_RELATIVE_TO_XBOOTLDR] = "xbootldr", [PATH_RELATIVE_TO_BOOT] = "boot", + [PATH_RELATIVE_TO_EXPLICIT] = "explicit", }; DEFINE_STRING_TABLE_LOOKUP(path_relative_to, PathRelativeTo); diff --git a/src/sysupdate/sysupdate-resource.h b/src/sysupdate/sysupdate-resource.h index 76795db0d80..1bcbe0f8e5d 100644 --- a/src/sysupdate/sysupdate-resource.h +++ b/src/sysupdate/sysupdate-resource.h @@ -73,6 +73,7 @@ typedef enum PathRelativeTo { PATH_RELATIVE_TO_ESP, PATH_RELATIVE_TO_XBOOTLDR, PATH_RELATIVE_TO_BOOT, /* Refers to $BOOT from the BLS. No direct counterpart in PartitionDesignator */ + PATH_RELATIVE_TO_EXPLICIT, _PATH_RELATIVE_TO_MAX, _PATH_RELATIVE_TO_INVALID = -EINVAL, } PathRelativeTo; @@ -102,7 +103,7 @@ int resource_load_instances(Resource *rr, bool verify, Hashmap **web_cache); Instance* resource_find_instance(Resource *rr, const char *version); -int resource_resolve_path(Resource *rr, const char *root, const char *node); +int resource_resolve_path(Resource *rr, const char *root, const char *relative_to_directory, const char *node); ResourceType resource_type_from_string(const char *s) _pure_; const char* resource_type_to_string(ResourceType t) _const_; diff --git a/src/sysupdate/sysupdate-transfer.c b/src/sysupdate/sysupdate-transfer.c index cbf3f77f5bf..508fd73355f 100644 --- a/src/sysupdate/sysupdate-transfer.c +++ b/src/sysupdate/sysupdate-transfer.c @@ -557,6 +557,14 @@ int transfer_read_definition(Transfer *t, const char *path) { return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), "Source specification lacks Path=."); + if (t->source.path_relative_to == PATH_RELATIVE_TO_EXPLICIT && !arg_transfer_source) + return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), + "PathRelativeTo=explicit requires --transfer-source= to be specified."); + + if (t->target.path_relative_to == PATH_RELATIVE_TO_EXPLICIT) + return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), + "PathRelativeTo=explicit can only be used in source specifications."); + if (t->source.path) { if (RESOURCE_IS_FILESYSTEM(t->source.type) || t->source.type == RESOURCE_PARTITION) if (!path_is_absolute(t->source.path) || !path_is_normalized(t->source.path)) @@ -618,11 +626,11 @@ int transfer_resolve_paths( assert(t); - r = resource_resolve_path(&t->source, root, node); + r = resource_resolve_path(&t->source, root, arg_transfer_source, node); if (r < 0) return r; - r = resource_resolve_path(&t->target, root, node); + r = resource_resolve_path(&t->target, root, /*relative_to_directory=*/ NULL, node); if (r < 0) return r; diff --git a/src/sysupdate/sysupdate.c b/src/sysupdate/sysupdate.c index 04fd003299e..a80599c7969 100644 --- a/src/sysupdate/sysupdate.c +++ b/src/sysupdate/sysupdate.c @@ -48,12 +48,14 @@ static char *arg_component = NULL; static int arg_verify = -1; static ImagePolicy *arg_image_policy = NULL; static bool arg_offline = false; +char *arg_transfer_source = NULL; STATIC_DESTRUCTOR_REGISTER(arg_definitions, freep); STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); STATIC_DESTRUCTOR_REGISTER(arg_component, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); +STATIC_DESTRUCTOR_REGISTER(arg_transfer_source, freep); typedef struct Context { Transfer **transfers; @@ -1436,6 +1438,8 @@ static int verb_help(int argc, char **argv, void *userdata) { " --no-legend Do not show the headers and footers\n" " --json=pretty|short|off\n" " Generate JSON output\n" + " --transfer-source=PATH\n" + " Specify the directory to transfer sources from\n" "\nSee the %2$s for details.\n", program_invocation_short_name, link, @@ -1462,6 +1466,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_REBOOT, ARG_VERIFY, ARG_OFFLINE, + ARG_TRANSFER_SOURCE, }; static const struct option options[] = { @@ -1480,6 +1485,7 @@ static int parse_argv(int argc, char *argv[]) { { "component", required_argument, NULL, 'C' }, { "verify", required_argument, NULL, ARG_VERIFY }, { "offline", no_argument, NULL, ARG_OFFLINE }, + { "transfer-source", required_argument, NULL, ARG_TRANSFER_SOURCE }, {} }; @@ -1587,6 +1593,13 @@ static int parse_argv(int argc, char *argv[]) { arg_offline = true; break; + case ARG_TRANSFER_SOURCE: + r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_transfer_source); + if (r < 0) + return r; + + break; + case '?': return -EINVAL; diff --git a/src/sysupdate/sysupdate.h b/src/sysupdate/sysupdate.h index 011b351375f..572b4305c72 100644 --- a/src/sysupdate/sysupdate.h +++ b/src/sysupdate/sysupdate.h @@ -10,3 +10,4 @@ typedef struct Context Context; extern bool arg_sync; extern uint64_t arg_instances_max; extern char *arg_root; +extern char *arg_transfer_source;