Merge pull request #26695 from poettering/dissect-mount-helper
make "systemd-dissect --mount" available as /sbin/mount.ddi
This commit is contained in:
@@ -902,7 +902,7 @@ manpages = [
|
||||
['systemd-debug-generator', '8', [], ''],
|
||||
['systemd-delta', '1', [], ''],
|
||||
['systemd-detect-virt', '1', [], ''],
|
||||
['systemd-dissect', '1', [], 'HAVE_BLKID'],
|
||||
['systemd-dissect', '1', ['mount.ddi'], 'HAVE_BLKID'],
|
||||
['systemd-environment-d-generator',
|
||||
'8',
|
||||
['30-systemd-environment-d-generator'],
|
||||
|
||||
+47
-2
@@ -18,6 +18,7 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd-dissect</refname>
|
||||
<refname>mount.ddi</refname>
|
||||
<refpurpose>Dissect Discoverable Disk Images (DDIs)</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
@@ -99,6 +100,14 @@
|
||||
what it operates with when mounting the image. To display the complete list of partitions use a tool such
|
||||
as <citerefentry
|
||||
project='man-pages'><refentrytitle>fdisk</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>The <command>systemd-dissect</command> command may be invoked as <command>mount.ddi</command> in
|
||||
which case it implements the <citerefentry
|
||||
project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> "external
|
||||
helper" interface. This ensures disk images compatible with <command>systemd-dissect</command> can be
|
||||
mounted directly by <command>mount</command> and <citerefentry
|
||||
project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>. For
|
||||
details see below.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@@ -132,7 +141,13 @@
|
||||
<para>All mounted file systems are checked with the appropriate <citerefentry
|
||||
project='man-pages'><refentrytitle>fsck</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
implementation in automatic fixing mode, unless explicitly turned off (<option>--fsck=no</option>) or
|
||||
read-only operation is requested (<option>--read-only</option>).</para></listitem>
|
||||
read-only operation is requested (<option>--read-only</option>).</para>
|
||||
|
||||
<para>Note that this functionality is also available in <citerefentry
|
||||
project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry> via a
|
||||
command such as <command>mount -t ddi myimage.raw targetdir/</command>, as well as in <citerefentry
|
||||
project='man-pages'><refentrytitle>fstab</refentrytitle><manvolnum>5</manvolnum></citerefentry>. For
|
||||
details, see below.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -359,6 +374,35 @@
|
||||
command is used the exit status of the invoked command is propagated.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Invocation as <command>/sbin/mount.ddi</command></title>
|
||||
|
||||
<para>The <command>systemd-dissect</command> executable may be symlinked to
|
||||
<filename>/sbin/mount.ddi</filename>. If invoked through that it implements <citerefentry
|
||||
project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>'s
|
||||
"external helper" interface for the (pseudo) file system type <literal>ddi</literal>. This means
|
||||
conformant disk images may be mounted directly via</para>
|
||||
|
||||
<programlisting># mount -t ddi myimage.raw targetdir/</programlisting>
|
||||
|
||||
<para>in a fashion mostly equivalent to:</para>
|
||||
|
||||
<programlisting># systemd-dissect --mount myimage.raw targetdir/</programlisting>
|
||||
|
||||
<para>Note that since a single DDI may contain multiple file systems it should later be unmounted with
|
||||
<command>umount -R targetdir/</command>, for recursive operation.</para>
|
||||
|
||||
<para>This functionality is particularly useful to mount DDIs automatically at boot via simple
|
||||
<filename>/etc/fstab</filename> entries. For example:</para>
|
||||
|
||||
<programlisting>/path/to/myimage.raw /images/myimage/ ddi defaults 0 0</programlisting>
|
||||
|
||||
<para>When invoked this way the mount options <literal>ro</literal>, <literal>rw</literal>,
|
||||
<literal>discard</literal>, <literal>nodiscard</literal> map to the corresponding options listed above
|
||||
(i.e. <option>--read-only</option>, <option>--discard=all</option>,
|
||||
<option>--discard=disabled</option>). Mount options are <emphasis>not</emphasis> generically passed on to
|
||||
the file systems inside the images.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
@@ -366,7 +410,7 @@
|
||||
<example>
|
||||
<title>Generate a tarball from an OS disk image</title>
|
||||
|
||||
<programlisting>$ systemd-dissect --with foo.raw tar cz . >foo.tar.gz</programlisting>
|
||||
<programlisting># systemd-dissect --with foo.raw tar cz . >foo.tar.gz</programlisting>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
@@ -377,6 +421,7 @@
|
||||
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
<ulink url="https://uapi-group.org/specifications/specs/discoverable_partitions_specification">Discoverable Partitions Specification</ulink>,
|
||||
<citerefentry project='man-pages'><refentrytitle>mount</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry project='man-pages'><refentrytitle>umount</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
<citerefentry project='man-pages'><refentrytitle>fdisk</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
</para>
|
||||
|
||||
@@ -2478,6 +2478,10 @@ if conf.get('HAVE_BLKID') == 1
|
||||
dependencies : [versiondep],
|
||||
install_rpath : rootpkglibdir,
|
||||
install : true)
|
||||
|
||||
meson.add_install_script(meson_make_symlink,
|
||||
bindir / 'systemd-dissect',
|
||||
rootsbindir / 'mount.ddi')
|
||||
endif
|
||||
|
||||
if conf.get('ENABLE_RESOLVE') == 1
|
||||
|
||||
+78
-1
@@ -522,6 +522,80 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_argv_as_mount_helper(int argc, char *argv[]) {
|
||||
const char *options = NULL;
|
||||
bool fake = false;
|
||||
int c, r;
|
||||
|
||||
/* Implements util-linux "external helper" command line interface, as per mount(8) man page. */
|
||||
|
||||
while ((c = getopt(argc, argv, "sfnvN:o:t:")) >= 0) {
|
||||
switch(c) {
|
||||
|
||||
case 'f':
|
||||
fake = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
options = optarg;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (!streq(optarg, "ddi"))
|
||||
log_debug("Unexpected file system type '%s', ignoring.", optarg);
|
||||
break;
|
||||
|
||||
case 's': /* sloppy mount options */
|
||||
case 'n': /* aka --no-mtab */
|
||||
case 'v': /* aka --verbose */
|
||||
log_debug("Ignoring option -%c, not implemented.", c);
|
||||
break;
|
||||
|
||||
case 'N': /* aka --namespace= */
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Option -%c is not implemented, refusing.", c);
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind + 2 != argc)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Expected an image file path and target directory as only argument.");
|
||||
|
||||
for (const char *p = options;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, ",", EXTRACT_KEEP_QUOTE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract mount option: %m");
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(word, "ro"))
|
||||
SET_FLAG(arg_flags, DISSECT_IMAGE_READ_ONLY, true);
|
||||
else if (streq(word, "rw"))
|
||||
SET_FLAG(arg_flags, DISSECT_IMAGE_READ_ONLY, false);
|
||||
else if (streq(word, "discard"))
|
||||
SET_FLAG(arg_flags, DISSECT_IMAGE_DISCARD_ANY, true);
|
||||
else if (streq(word, "nodiscard"))
|
||||
SET_FLAG(arg_flags, DISSECT_IMAGE_DISCARD_ANY, false);
|
||||
else
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Unknown mount option '%s'.", word);
|
||||
}
|
||||
|
||||
if (fake)
|
||||
return 0;
|
||||
|
||||
arg_image = argv[optind];
|
||||
arg_path = argv[optind+1];
|
||||
|
||||
arg_flags |= DISSECT_IMAGE_REQUIRE_ROOT;
|
||||
arg_action = ACTION_MOUNT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int strv_pair_to_json(char **l, JsonVariant **ret) {
|
||||
_cleanup_strv_free_ char **jl = NULL;
|
||||
|
||||
@@ -1420,7 +1494,10 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
log_setup();
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
if (invoked_as(argv, "mount.ddi"))
|
||||
r = parse_argv_as_mount_helper(argc, argv);
|
||||
else
|
||||
r = parse_argv(argc, argv);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -424,6 +424,12 @@ grep -q -F '{"name":"b","type":"raw","class":"portable","ro":false,"path":"/run/
|
||||
grep -q -F '{"name":"c","type":"raw","class":"extension","ro":false,"path":"/run/extensions/c.raw"' /tmp/discover.json
|
||||
rm /tmp/discover.json /run/machines/a.raw /run/portables/b.raw /run/extensions/c.raw
|
||||
|
||||
# Check that the /sbin/mount.ddi helper works
|
||||
T="/tmp/mounthelper.$RANDOM"
|
||||
mount -t ddi "${image}.gpt" "$T" -o ro,X-mount.mkdir,discard
|
||||
umount -R "$T"
|
||||
rmdir "$T"
|
||||
|
||||
echo OK >/testok
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user