From a164d9d5aab40cdcf5685bbfa286d8e08ae76150 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 6 Mar 2023 18:25:25 +0100 Subject: dissect: implement external helper plugin interface for /bin/mount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this change we'll install a symlink /sbin/mount.ddi → systemd-dissect. If invoked that way we'll do the equivalent of systemd-dissect --mount. This makes DDIs mountable directly via the "mount" command, by specifying the "-t ddi" pseudo file system type. Moreover you can now mount DDIs directly via /etc/fstab, by specifying "ddi" in the file system column (3rd column). --- src/dissect/dissect.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index f08e745a55..db26645fd9 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -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; -- cgit v1.2.1