diff options
-rw-r--r-- | man/systemd-dissect.xml | 19 | ||||
-rw-r--r-- | src/dissect/dissect.c | 25 |
2 files changed, 44 insertions, 0 deletions
diff --git a/man/systemd-dissect.xml b/man/systemd-dissect.xml index 1d0532713d..06c57a22ec 100644 --- a/man/systemd-dissect.xml +++ b/man/systemd-dissect.xml @@ -386,6 +386,25 @@ </para></listitem> </varlistentry> + <varlistentry> + <term><option>--loop-ref=</option></term> + + <listitem><para>Configures the "reference" string the kernel shall report as backing file for the + loopback block device. While this is supposed to be a path or filename referencing the backing file, + this is not enforced and the kernel accepts arbitrary free-form strings, chosen by the user. Accepts + arbitrary strings up to a length of 63 characters. This sets the kernel's + <literal>.lo_file_name</literal> field for the block device. Note this is distinct from the + <filename>/sys/class/block/loopX/loop/backing_file</filename> attribute file that always reports a + path referring to the actual backing file. The latter is subject to mount namespace translation, the + former is not.</para> + + <para>This setting is particularly useful in combination with the <option>--attach</option> command, + as it allows later referencing the allocated loop device via <filename>/dev/loop/by-ref/…</filename> + symlinks. Example: first, set up the loopback device via <command>systemd-dissect attach + --loop-ref=quux foo.raw</command>, and then reference it in a command via the specified filename: + <command>cfdisk /dev/loop/by-ref/quux</command>.</para></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" /> diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 6f7b44f0aa..a688e6f32c 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -81,9 +81,11 @@ static bool arg_legend = true; static bool arg_rmdir = false; static bool arg_in_memory = false; static char **arg_argv = NULL; +static char *arg_loop_ref = NULL; STATIC_DESTRUCTOR_REGISTER(arg_verity_settings, verity_settings_done); STATIC_DESTRUCTOR_REGISTER(arg_argv, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_loop_ref, freep); static int help(void) { _cleanup_free_ char *link = NULL; @@ -123,6 +125,7 @@ static int help(void) { " not embedded in IMAGE\n" " --json=pretty|short|off\n" " Generate JSON output\n" + " --loop-ref=NAME Set reference string for loopback device\n" "\n%3$sCommands:%4$s\n" " -h --help Show this help\n" " --version Show package version\n" @@ -214,6 +217,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_DISCOVER, ARG_ATTACH, ARG_DETACH, + ARG_LOOP_REF, }; static const struct option options[] = { @@ -242,6 +246,7 @@ static int parse_argv(int argc, char *argv[]) { { "copy-to", no_argument, NULL, 'a' }, { "json", required_argument, NULL, ARG_JSON }, { "discover", no_argument, NULL, ARG_DISCOVER }, + { "loop-ref", required_argument, NULL, ARG_LOOP_REF }, {} }; @@ -435,6 +440,20 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_DISCOVER; break; + case ARG_LOOP_REF: + if (isempty(optarg)) { + arg_loop_ref = mfree(arg_loop_ref); + break; + } + + if (strlen(optarg) >= sizeof_field(struct loop_info64, lo_file_name)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Loop device ref string '%s' is too long.", optarg); + + r = free_and_strdup_warn(&arg_loop_ref, optarg); + if (r < 0) + return r; + break; + case '?': return -EINVAL; @@ -1671,6 +1690,12 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to set up loopback device for %s: %m", arg_image); + if (arg_loop_ref) { + r = loop_device_set_filename(d, arg_loop_ref); + if (r < 0) + log_warning_errno(r, "Failed to set loop reference string to '%s', ignoring: %m", arg_loop_ref); + } + r = dissect_loop_device_and_warn( d, &arg_verity_settings, |