From 39c63831a03698fda6252670a789c38d7067fb97 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 24 Oct 2023 14:35:06 +0200 Subject: [PATCH] btrfs-progs: add support for dry-run options Some commands could be run in a dry-run mode, i.e. not doing any write/change actions, only printing the steps and ignoring errors. There are two possibilities where to put the option: - as a global one: btrfs --dry-run subvolume delete /path - local option: btrfs subvolume delete --dry-run /path As we have several global options already, let's put it there, dry-run should not be very common so the slight inconvenience of writing the option out of order of command arguments should be acceptable. Issue: #629 Signed-off-by: David Sterba --- btrfs.c | 14 ++++++++++++-- cmds/commands.h | 1 + common/help.h | 3 ++- common/utils.c | 10 ++++++++++ common/utils.h | 4 ++++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/btrfs.c b/btrfs.c index 591dd45e..3be87542 100644 --- a/btrfs.c +++ b/btrfs.c @@ -44,6 +44,7 @@ static const char * const btrfs_cmd_group_usage[] = { " -v|--verbose increase verbosity of the subcommand\n" " -q|--quiet print only errors\n" " --log set log level (default, info, verbose, debug, quiet)\n" + " --dry-run if supported, do not do any active/changing actions\n" "\n" "Options for the main command only:\n" " --help print condensed help for all subcommands\n" @@ -119,7 +120,7 @@ parse_command_token(const char *arg, const struct cmd_group *grp) return cmd; } -static void check_output_format(const struct cmd_struct *cmd) +static void check_command_flags(const struct cmd_struct *cmd) { if (cmd->next) return; @@ -129,6 +130,11 @@ static void check_output_format(const struct cmd_struct *cmd) output_format_name(bconf.output_format)); exit(1); } + + if (bconf.dry_run && !(cmd->flags & CMD_DRY_RUN)) { + error("--dry-run option not supported for %s\n", cmd->token); + exit(1); + } } static void handle_help_options_next_level(const struct cmd_struct *cmd, @@ -165,7 +171,7 @@ int handle_command_group(const struct cmd_struct *cmd, int argc, subcmd = parse_command_token(argv[0], cmd->next); handle_help_options_next_level(subcmd, argc, argv); - check_output_format(subcmd); + check_command_flags(subcmd); fixup_argv0(argv, subcmd->token); return cmd_execute(subcmd, argc, argv); @@ -288,6 +294,7 @@ static int handle_global_options(int argc, char **argv) { "quiet", no_argument, NULL, 'q' }, { "log", required_argument, NULL, OPT_LOG }, { "param", required_argument, NULL, GETOPT_VAL_PARAM }, + { "dry-run", no_argument, NULL, GETOPT_VAL_DRY_RUN }, { NULL, 0, NULL, 0} }; int shift; @@ -316,6 +323,9 @@ static int handle_global_options(int argc, char **argv) case GETOPT_VAL_PARAM: bconf_save_param(optarg); break; + case GETOPT_VAL_DRY_RUN: + bconf_set_dry_run(); + break; case 'v': bconf_be_verbose(); break; diff --git a/cmds/commands.h b/cmds/commands.h index 5ab7c881..464f9017 100644 --- a/cmds/commands.h +++ b/cmds/commands.h @@ -22,6 +22,7 @@ enum { CMD_ALIAS = (1 << 1), /* alias of next command in cmd_group */ CMD_FORMAT_TEXT = (1 << 2), /* output as plain text */ CMD_FORMAT_JSON = (1 << 3), /* output in json */ + CMD_DRY_RUN = (1 << 4), /* Accepts global --dry-run option. */ }; #define CMD_FORMAT_MASK (CMD_FORMAT_TEXT | CMD_FORMAT_JSON) diff --git a/common/help.h b/common/help.h index f6bf9782..851034b9 100644 --- a/common/help.h +++ b/common/help.h @@ -37,6 +37,7 @@ struct cmd_group; #define GETOPT_VAL_HELP 520 #define GETOPT_VAL_PARAM 521 +#define GETOPT_VAL_DRY_RUN 522 #define ARGV0_BUF_SIZE PATH_MAX @@ -83,7 +84,7 @@ struct cmd_group; "Global options:" #define HELPINFO_INSERT_FORMAT "--format TYPE" - +#define HELPINFO_INSERT_DRY_RUN OPTLINE("--dry-run", "do not do any active/changing actions") #define HELPINFO_INSERT_VERBOSE OPTLINE("-v|--verbose", "increase output verbosity") #define HELPINFO_INSERT_QUIET OPTLINE("-q|--quiet", "print only errors") diff --git a/common/utils.c b/common/utils.c index b0a61126..274bc298 100644 --- a/common/utils.c +++ b/common/utils.c @@ -1000,6 +1000,16 @@ void bconf_save_param(const char *str) } } +void bconf_set_dry_run(void) +{ + pr_verbose(LOG_INFO, "Dry-run requested\n"); + bconf.dry_run = 1; +} + +bool bconf_is_dry_run(void) +{ + return bconf.dry_run == 1; +} /* Returns total size of main memory in bytes, -1UL if error. */ unsigned long total_memory(void) diff --git a/common/utils.h b/common/utils.h index 30899ab2..e267814b 100644 --- a/common/utils.h +++ b/common/utils.h @@ -87,6 +87,8 @@ struct btrfs_config { * > 0: verbose level */ int verbose; + /* Command line request to skip any modification actions. */ + int dry_run; struct list_head params; }; extern struct btrfs_config bconf; @@ -102,6 +104,8 @@ void bconf_be_verbose(void); void bconf_be_quiet(void); void bconf_add_param(const char *key, const char *value); void bconf_save_param(const char *str); +void bconf_set_dry_run(void); +bool bconf_is_dry_run(void); const char *bconf_param_value(const char *key); /* Pseudo random number generator wrappers */