From: Luca Boccassi Date: Wed, 16 Aug 2023 01:00:47 +0000 (+0100) Subject: sd-mount: allow creating tmpfs X-Git-Tag: v255-rc1~683 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2322c6c7355a4546930f10fb35e983835c86daeb;p=thirdparty%2Fsystemd.git sd-mount: allow creating tmpfs Mount units can do it, but the command line tool cannot, as it needs a valid 'what'. If --tmpfs/-T if passed, parse the argument as 'where' and send a literal 'tmpfs' as the 'what' if not specified. --- diff --git a/man/systemd-mount.xml b/man/systemd-mount.xml index e25d5c435e9..890c950cd05 100644 --- a/man/systemd-mount.xml +++ b/man/systemd-mount.xml @@ -29,6 +29,13 @@ WHAT WHERE + + systemd-mount + OPTIONS + + NAME + WHERE + systemd-mount OPTIONS @@ -63,7 +70,9 @@ whose name is generated from the file system label. In this mode the block device or image file must exist at the time of invocation of the command, so that it may be probed. If the device is found to be a removable block device (e.g. a USB stick), an automount point is created instead of a regular mount point - (i.e. the option is implied, see below). + (i.e. the option is implied, see below). If the option + is specified, then the argument will be interpreted as the path where the new temporary file system will + be mounted on. If two arguments are specified, the first indicates the mount source (the WHAT) and the second indicates the path to mount it on (the @@ -273,6 +282,16 @@ information. + + + + + + Create and mount a new temporary file system on WHERE, with an + optional NAME that defaults to tmpfs. + + + diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 89bf7fd80d2..31abc0685dc 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -71,6 +71,7 @@ static uid_t arg_uid = UID_INVALID; static gid_t arg_gid = GID_INVALID; static bool arg_fsck = true; static bool arg_aggressive_gc = false; +static bool arg_tmpfs = false; STATIC_DESTRUCTOR_REGISTER(arg_mount_what, freep); STATIC_DESTRUCTOR_REGISTER(arg_mount_where, freep); @@ -80,6 +81,34 @@ STATIC_DESTRUCTOR_REGISTER(arg_description, freep); STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_automount_property, strv_freep); +static int parse_where(const char *input, char **ret_where) { + _cleanup_free_ char *where = NULL; + int r; + + assert(input); + assert(ret_where); + + if (arg_transport == BUS_TRANSPORT_LOCAL) { + r = chase(input, NULL, CHASE_NONEXISTENT, &where, NULL); + if (r < 0) + return log_error_errno(r, "Failed to make path %s absolute: %m", input); + } else { + where = strdup(input); + if (!where) + return log_oom(); + + path_simplify(where); + + if (!path_is_absolute(where)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Path must be absolute when operating remotely: %s", + where); + } + + *ret_where = TAKE_PTR(where); + return 0; +} + static int help(void) { _cleanup_free_ char *link = NULL; int r; @@ -89,6 +118,7 @@ static int help(void) { return log_oom(); printf("systemd-mount [OPTIONS...] WHAT [WHERE]\n" + "systemd-mount [OPTIONS...] --tmpfs [NAME] WHERE\n" "systemd-mount [OPTIONS...] --list\n" "%s [OPTIONS...] %sWHAT|WHERE...\n\n" "Establish a mount or auto-mount point transiently.\n\n" @@ -118,6 +148,7 @@ static int help(void) { " --list List mountable block devices\n" " -u --umount Unmount mount points\n" " -G --collect Unload unit after it stopped, even when failed\n" + " -T --tmpfs Create a new tmpfs on the mount point\n" "\nSee the %s for details.\n", program_invocation_short_name, streq(program_invocation_short_name, "systemd-umount") ? "" : "--umount ", @@ -177,6 +208,7 @@ static int parse_argv(int argc, char *argv[]) { { "umount", no_argument, NULL, 'u' }, { "unmount", no_argument, NULL, 'u' }, { "collect", no_argument, NULL, 'G' }, + { "tmpfs", no_argument, NULL, 'T' }, {}, }; @@ -188,7 +220,7 @@ static int parse_argv(int argc, char *argv[]) { if (invoked_as(argv, "systemd-umount")) arg_action = ACTION_UMOUNT; - while ((c = getopt_long(argc, argv, "hqH:M:t:o:p:AuGl", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hqH:M:t:o:p:AuGlT", options, NULL)) >= 0) switch (c) { @@ -327,6 +359,10 @@ static int parse_argv(int argc, char *argv[]) { arg_aggressive_gc = true; break; + case 'T': + arg_tmpfs = true; + break; + case '?': return -EINVAL; @@ -361,7 +397,8 @@ static int parse_argv(int argc, char *argv[]) { for (i = optind; i < argc; i++) if (!path_is_absolute(argv[i]) ) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Only absolute path is supported: %s", argv[i]); + "Path must be absolute when operating remotely: %s", + argv[i]); } } else { if (optind >= argc) @@ -372,50 +409,59 @@ static int parse_argv(int argc, char *argv[]) { return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "At most two arguments required."); - if (arg_mount_type && !fstype_is_blockdev_backed(arg_mount_type)) { - arg_mount_what = strdup(argv[optind]); - if (!arg_mount_what) - return log_oom(); + if (arg_tmpfs) { + if (argc <= optind+1) { + arg_mount_what = strdup("tmpfs"); + if (!arg_mount_what) + return log_oom(); - } else if (arg_transport == BUS_TRANSPORT_LOCAL) { - _cleanup_free_ char *u = NULL; + r = parse_where(argv[optind], &arg_mount_where); + if (r < 0) + return r; + } else { + arg_mount_what = strdup(argv[optind]); + if (!arg_mount_what) + return log_oom(); + } - u = fstab_node_to_udev_node(argv[optind]); - if (!u) + if (!strv_contains(arg_property, "Type=tmpfs") && + strv_extend(&arg_property, "Type=tmpfs") < 0) return log_oom(); - - r = chase(u, NULL, 0, &arg_mount_what, NULL); - if (r < 0) - return log_error_errno(r, "Failed to make path %s absolute: %m", u); } else { - arg_mount_what = strdup(argv[optind]); - if (!arg_mount_what) - return log_oom(); + if (arg_mount_type && !fstype_is_blockdev_backed(arg_mount_type)) { + arg_mount_what = strdup(argv[optind]); + if (!arg_mount_what) + return log_oom(); - path_simplify(arg_mount_what); + } else if (arg_transport == BUS_TRANSPORT_LOCAL) { + _cleanup_free_ char *u = NULL; - if (!path_is_absolute(arg_mount_what)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Only absolute path is supported: %s", arg_mount_what); - } + u = fstab_node_to_udev_node(argv[optind]); + if (!u) + return log_oom(); - if (argc > optind+1) { - if (arg_transport == BUS_TRANSPORT_LOCAL) { - r = chase(argv[optind+1], NULL, CHASE_NONEXISTENT, &arg_mount_where, NULL); + r = chase(u, NULL, 0, &arg_mount_what, NULL); if (r < 0) - return log_error_errno(r, "Failed to make path %s absolute: %m", argv[optind+1]); + return log_error_errno(r, "Failed to make path %s absolute: %m", u); } else { - arg_mount_where = strdup(argv[optind+1]); - if (!arg_mount_where) + arg_mount_what = strdup(argv[optind]); + if (!arg_mount_what) return log_oom(); - path_simplify(arg_mount_where); + path_simplify(arg_mount_what); - if (!path_is_absolute(arg_mount_where)) + if (!path_is_absolute(arg_mount_what)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Only absolute path is supported: %s", arg_mount_where); + "Path must be absolute when operating remotely: %s", + arg_mount_what); } - } else + } + + if (argc > optind+1) { + r = parse_where(argv[optind+1], &arg_mount_where); + if (r < 0) + return r; + } else if (!arg_tmpfs) arg_discover = true; if (arg_discover && arg_transport != BUS_TRANSPORT_LOCAL) diff --git a/test/units/testsuite-74.mount.sh b/test/units/testsuite-74.mount.sh index c4ecfdcadad..41c5c8652a2 100755 --- a/test/units/testsuite-74.mount.sh +++ b/test/units/testsuite-74.mount.sh @@ -140,3 +140,12 @@ systemctl status "$WORK_DIR/mnt" touch "$WORK_DIR/mnt/hello" [[ "$(stat -c "%U:%G" "$WORK_DIR/mnt/hello")" == "testuser:testuser" ]] systemd-umount LABEL=owner-vfat + +# tmpfs +mkdir -p "$WORK_DIR/mnt/foo/bar" +systemd-mount --tmpfs "$WORK_DIR/mnt/foo" +test ! -d "$WORK_DIR/mnt/foo/bar" +touch "$WORK_DIR/mnt/foo/baz" +systemd-umount "$WORK_DIR/mnt/foo" +test -d "$WORK_DIR/mnt/foo/bar" +test ! -e "$WORK_DIR/mnt/foo/baz"