From f976133dbfd138a71b3d307b75d96ba927ac4e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Aug 2026 20:51:40 +0200 Subject: [PATCH] mount: convert to VERB_COMMAND and add --introspect-cli The custom help() is replaced by a COMMAND() description, and --introspect-cli is added. Options are now in two groups: "Common options" and Mount options". In --help, for systemd-mount, both groups are shown. For systemd-umount, only the first. This changes the behaviour a bit: previously, both groups were shown together as one list. I think the new behaviour is actually a bit better, because it makes it easier for the user to figure out that the commands share common options and one of the commands has its private second group. But if people think that the previous behaviour should be restored, we could add a display options to squish the groups back together. --help now goes through the pager, like other commands with --no-pager. --- src/mount/mount-tool.c | 90 +++++++++---------- .../units/TEST-74-AUX-UTILS.introspect-cli.sh | 11 +++ 2 files changed, 56 insertions(+), 45 deletions(-) diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index 58b689190d..5ecd7c097a 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -2,6 +2,7 @@ #include "sd-bus.h" #include "sd-device.h" +#include "sd-json.h" #include "ansi-color.h" #include "argv-util.h" @@ -21,11 +22,9 @@ #include "format-table.h" #include "format-util.h" #include "fstab-util.h" -#include "help-util.h" #include "libmount-util.h" #include "main-func.h" #include "mountpoint-util.h" -#include "options.h" #include "pager.h" #include "parse-argument.h" #include "parse-util.h" @@ -41,6 +40,7 @@ #include "unit-def.h" #include "unit-name.h" #include "user-util.h" +#include "verbs.h" static enum { ACTION_DEFAULT, @@ -86,6 +86,33 @@ STATIC_DESTRUCTOR_REGISTER(arg_description, freep); STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_automount_property, strv_freep); +COMMAND( + "systemd-mount\0", + "Establish a mount or auto-mount point.", + .argspec = + "WHAT [WHERE]\0" + "--tmpfs [NAME] WHERE\0" + "--list\0" + "--umount WHAT|WHERE…\0", + .option_groups = + "Common options\0" + "Mount options\0", + .man_pages = "systemd-mount.1\0", + .flags = COMMAND_VERBS_SHARED, + .pager_flags = &arg_pager_flags, +); +COMMAND( + "systemd-umount\0", + "Unmount one or more mount points.", + .argspec = + "WHAT|WHERE…\0", + .option_groups = + "Common options\0", + .man_pages = "systemd-mount.1\0", + .flags = COMMAND_VERBS_SHARED, + .pager_flags = &arg_pager_flags, +); + static int parse_where(const char *input, char **ret_where) { int r; @@ -110,46 +137,6 @@ static int parse_where(const char *input, char **ret_where) { return 0; } -static int help(char *argv[]) { - _cleanup_(table_unrefp) Table *options_common = NULL, *options_mount = NULL; - int r; - - r = option_parser_get_help_table(&options_common); - if (r < 0) - return r; - - if (invoked_as(argv, "systemd-umount")) { - help_cmdline("[OPTIONS…] WHAT|WHERE…"); - help_abstract("Unmount one or more mount points."); - } else { - help_cmdline("[OPTIONS…] WHAT [WHERE]"); - help_cmdline("[OPTIONS…] --tmpfs [NAME] WHERE"); - help_cmdline("[OPTIONS…] --list"); - help_cmdline("[OPTIONS…] --umount WHAT|WHERE…"); - help_abstract("Establish a mount or auto-mount point."); - - r = option_parser_get_help_table_group("Mount options", &options_mount); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, options_common, options_mount); - } - - help_section("Options"); - r = table_print_or_warn(options_common); - if (r < 0) - return r; - - if (options_mount) { - r = table_print_or_warn(options_mount); - if (r < 0) - return r; - } - - help_man_page_reference("systemd-mount", "1"); - return 0; -} - static int parse_argv(int argc, char *argv[], char ***remaining_args) { int r; @@ -157,16 +144,26 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { assert(argv); assert(remaining_args); - if (invoked_as(argv, "systemd-umount")) + bool is_umount = invoked_as(argv, "systemd-umount"); + + const CommandDescription *cmd; + assert_se(verbs_find_command(is_umount ? "systemd-umount" : "systemd-mount", &cmd)); + + if (is_umount) arg_action = ACTION_UMOUNT; - OptionParser opts = { argc, argv }; + OptionParser opts = { + argc, argv, + .option_groups = cmd->option_groups, + }; FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_GROUP("Common options"): {} + OPTION_COMMON_HELP: - return help(argv); + return command_print_help_full(cmd->names, /* footer_ansi_seq= */ NULL); OPTION_COMMON_VERSION: return version(); @@ -227,6 +224,9 @@ static int parse_argv(int argc, char *argv[], char ***remaining_args) { return r; break; + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); + OPTION_GROUP("Mount options"): {} OPTION_LONG("discover", NULL, "Discover mount device metadata"): diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index 47847d6e8d..ce9124696b 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -80,6 +80,7 @@ INTROSPECTABLE=( systemd-machine-id-setup systemd-measure systemd-modules-load + systemd-mount systemd-mstack systemd-mute-console systemd-network-generator @@ -119,6 +120,7 @@ INTROSPECTABLE=( systemd-tpm2-clear systemd-tpm2-setup systemd-tty-ask-password-agent + systemd-umount systemd-update-done systemd-validatefs systemd-veritysetup @@ -181,6 +183,15 @@ systemd-dissect --introspect-cli | jq -e \ systemd-id128 --introspect-cli | jq -e \ '.commands[0].verbs | map(.names[0]) | contains(["new", "machine-id", "show", "help"])' +if command -v systemd-mount >/dev/null; then + systemd-mount --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["systemd-mount", "systemd-umount"]' + + # --tmpfs is only valid for systemd-mount + (! systemd-mount --tmpfs 2>&1) | grep "one argument required" >/dev/null + (! systemd-umount --tmpfs 2>&1) | grep "unrecognized option" >/dev/null +fi + systemd-mstack --introspect-cli | jq -e \ '[.commands[].names[0]] | sort == ["mount.mstack", "systemd-mstack"]'