From a9f42ed01515026fecf12233e59076504e532b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Aug 2026 01:31:38 +0200 Subject: [PATCH] mstack: convert to VERB_COMMAND and add --introspect-cli The custom help() is replaced by a COMMAND() description, and --introspect-cli is added. The "Commands" option group is moved before the other options and an explicit "Options" group is added, so that the sections are printed in the same order as before. --help now goes through the pager, like other commands with --no-pager. The mount.mstack helper interface is described by a second COMMAND(), so that it is exposed by --introspect-cli too. --- src/mstack/mstack-tool.c | 110 ++++++++---------- .../units/TEST-74-AUX-UTILS.introspect-cli.sh | 17 +-- 2 files changed, 60 insertions(+), 67 deletions(-) diff --git a/src/mstack/mstack-tool.c b/src/mstack/mstack-tool.c index 45c699d574..ea2aa404c3 100644 --- a/src/mstack/mstack-tool.c +++ b/src/mstack/mstack-tool.c @@ -3,6 +3,8 @@ #include #include +#include "sd-json.h" + #include "argv-util.h" #include "build.h" #include "chase.h" @@ -11,15 +13,14 @@ #include "extract-word.h" #include "fd-util.h" #include "format-table.h" -#include "help-util.h" #include "image-policy.h" #include "main-func.h" #include "mount-util.h" #include "mountpoint-util.h" #include "mstack.h" -#include "options.h" #include "parse-argument.h" #include "string-util.h" +#include "verbs.h" static enum { ACTION_INSPECT, @@ -41,38 +42,17 @@ STATIC_DESTRUCTOR_REGISTER(arg_where, freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_image_filter, image_filter_freep); -static int help(void) { - _cleanup_(table_unrefp) Table *options = NULL, *commands = NULL; - int r; - - r = option_parser_get_help_table_ns("systemd-mstack", &options); - if (r < 0) - return r; - - r = option_parser_get_help_table_full("systemd-mstack", "Commands", &commands); - if (r < 0) - return r; - - (void) table_sync_column_widths(0, options, commands); - - help_cmdline("[OPTIONS...] WHAT"); - help_cmdline("[OPTIONS...] --mount WHAT WHERE"); - help_cmdline("[OPTIONS...] --umount WHERE"); - help_abstract("Inspect or apply mount stack."); - - help_section("Commands"); - r = table_print_or_warn(commands); - if (r < 0) - return r; - - help_section("Options"); - r = table_print_or_warn(options); - if (r < 0) - return r; - - help_man_page_reference("systemd-mstack", "1"); - return 0; -} +COMMAND( + "systemd-mstack\0", + "Inspect or apply mount stack.", + .argspec = + "WHAT\0" + "--mount WHAT WHERE\0" + "--umount WHERE\0", + .man_pages = "systemd-mstack.1\0", + .option_namespace = "systemd-mstack", + .pager_flags = &arg_pager_flags, +); static int parse_argv(int argc, char *argv[]) { int r; @@ -87,6 +67,34 @@ static int parse_argv(int argc, char *argv[]) { OPTION_NAMESPACE("systemd-mstack"): {} + OPTION_GROUP("Commands"): {} + + OPTION_COMMON_HELP: + return command_print_help("systemd-mstack"); + + OPTION_COMMON_VERSION: + return version(); + + OPTION('m', "mount", NULL, "Mount the mstack to the specified directory"): + arg_action = ACTION_MOUNT; + break; + + OPTION_SHORT('M', NULL, "Shortcut for --mount --mkdir"): + arg_action = ACTION_MOUNT; + arg_mstack_flags |= MSTACK_MKDIR; + break; + + OPTION('u', "umount", NULL, "Unmount the image from the specified directory"): + arg_action = ACTION_UMOUNT; + break; + + OPTION_SHORT('U', NULL, "Shortcut for --umount --rmdir"): + arg_action = ACTION_UMOUNT; + arg_rmdir = true; + break; + + OPTION_GROUP("Options"): {} + OPTION('r', "read-only", NULL, "Mount read-only"): arg_mstack_flags |= MSTACK_RDONLY; break; @@ -130,31 +138,8 @@ static int parse_argv(int argc, char *argv[]) { return r; break; - OPTION_GROUP("Commands"): {} - - OPTION_COMMON_HELP: - return help(); - - OPTION_COMMON_VERSION: - return version(); - - OPTION('m', "mount", NULL, "Mount the mstack to the specified directory"): - arg_action = ACTION_MOUNT; - break; - - OPTION_SHORT('M', NULL, "Shortcut for --mount --mkdir"): - arg_action = ACTION_MOUNT; - arg_mstack_flags |= MSTACK_MKDIR; - break; - - OPTION('u', "umount", NULL, "Unmount the image from the specified directory"): - arg_action = ACTION_UMOUNT; - break; - - OPTION_SHORT('U', NULL, "Shortcut for --umount --rmdir"): - arg_action = ACTION_UMOUNT; - arg_rmdir = true; - break; + OPTION_COMMON_INTROSPECT_CLI: + return introspect_cli(arg_json_format_flags); } char **args = option_parser_get_args(&opts); @@ -203,6 +188,13 @@ static int parse_argv(int argc, char *argv[]) { return 1; } +COMMAND( + "mount.mstack\0", + "External helper for mount.8 to mount mount stacks.", + .man_pages = "systemd-mstack.1\0", + .option_namespace = "mount.mstack", +); + static int parse_argv_as_mount_helper(int argc, char *argv[]) { const char *mount_options = NULL; bool fake = false; diff --git a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh index 5236631860..e1b5d023c3 100755 --- a/test/units/TEST-74-AUX-UTILS.introspect-cli.sh +++ b/test/units/TEST-74-AUX-UTILS.introspect-cli.sh @@ -61,6 +61,7 @@ INTROSPECTABLE=( systemd-machine-id-setup systemd-measure systemd-modules-load + systemd-mstack systemd-mute-console systemd-network-generator systemd-networkd-wait-online @@ -111,20 +112,20 @@ for i in "${INTROSPECTABLE[@]}"; do fi done -# systemd-hwdb defines verbs, check that they are described +# check verbs and multicall binaries if command -v systemd-hwdb >/dev/null; then systemd-hwdb --introspect-cli | jq -e \ '.commands[0].verbs | map(.names[0]) | sort == ["help", "query", "update"]' fi -# systemd-id128 defines many verbs, check that some are described -systemd-id128 --introspect-cli | jq -e \ - '.commands[0].verbs | map(.names[0]) | contains(["new", "machine-id", "show", "help"])' +resolvectl --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["resolvconf", "resolvectl", "systemd-resolve"]' -# systemd-clonesetup defines verbs, check that they are described systemd-clonesetup --introspect-cli | jq -e \ '.commands[0].verbs | map(.names[0]) | sort == ["add", "remove"]' -# resolvectl is a multicall binary, check that both commands are described -resolvectl --introspect-cli | jq -e \ - '[.commands[].names[0]] | sort == ["resolvconf", "resolvectl", "systemd-resolve"]' +systemd-id128 --introspect-cli | jq -e \ + '.commands[0].verbs | map(.names[0]) | contains(["new", "machine-id", "show", "help"])' + +systemd-mstack --introspect-cli | jq -e \ + '[.commands[].names[0]] | sort == ["mount.mstack", "systemd-mstack"]'