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:
parent
4ec630bfba
commit
c1852f9d5f
@ -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" />
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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_;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user