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 <dsterba@suse.com>
This commit is contained in:
David Sterba 2023-10-24 14:35:06 +02:00
parent 2c747dd83f
commit 39c63831a0
5 changed files with 29 additions and 3 deletions

14
btrfs.c
View file

@ -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 <level> 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;

View file

@ -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)

View file

@ -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")

View file

@ -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)

View file

@ -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 */