1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

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
"""
This commit is contained in:
Daan De Meyer 2024-09-08 16:09:19 +02:00
parent 4ec630bfba
commit c1852f9d5f
7 changed files with 58 additions and 7 deletions

View File

@ -305,6 +305,15 @@
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--transfer-source=</option></term>
<listitem><para>Takes a path as its argument. When specified, all transfer sources configured with
<varname>PathRelativeTo=explicit</varname> will be interpreted relative to the specified path.</para>
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="no-pager" />
<xi:include href="standard-options.xml" xpointer="no-legend" />
<xi:include href="standard-options.xml" xpointer="json" />

View File

@ -627,15 +627,26 @@
<varlistentry>
<term><varname>PathRelativeTo=</varname></term>
<listitem><para>Specifies what partition <varname>Path=</varname> should be relative to. Takes one of
<constant>root</constant>, <constant>esp</constant>, <constant>xbootldr</constant>, or <constant>boot</constant>.
If unspecified, defaults to <constant>root</constant>.</para>
<listitem><para>Specifies what anchor point <varname>Path=</varname> should be relative to. Takes one
of <constant>root</constant>, <constant>esp</constant>, <constant>xbootldr</constant>,
<constant>boot</constant> or <constant>directory</constant>. If unspecified, defaults to
<constant>root</constant>.</para>
<para>If set to <constant>root</constant>, <constant>esp</constant>, <constant>xbootldr</constant>,
the specified <varname>Path=</varname> will be resolved relative to the mount point of the
corresponding partition, as defined by the
<ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot Loader
Specification</ulink>.</para>
<para>If set to <constant>boot</constant>, the specified <varname>Path=</varname> will be resolved
relative to the mount point of the $BOOT partition (i.e. the ESP or XBOOTLDR), as defined by the
<ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot Loader
Specification</ulink>.</para>
<para>If set to <constant>explicit</constant>, the specified <varname>Path=</varname> will be
resolved relative to the directory specified with <option>--transfer-source=</option> when invoking
<command>systemd-sysupdate</command>.</para>
<para>The values <constant>esp</constant>, <constant>xbootldr</constant>, and
<constant>boot</constant> are only supported when <varname>Type=</varname> is set to
<constant>regular-file</constant> or <constant>directory</constant>.</para>

View File

@ -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);

View File

@ -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_;

View File

@ -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;

View File

@ -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;

View File

@ -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;