mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
command: refactor to use const command structure
Refactor code so the definitions may become 'static const' and with configure_command_option_values() we update options val_enum for actually running command option when used. Also update _update_relative_opt() which is used for generating man pages and command help. Introduce enumeration for lvm2 commands - so we may use enum cmd_COMMAND instead of string checking. So running command now does not modified opt_names.
This commit is contained in:
parent
0b064aedb3
commit
b4670db008
150
tools/command.c
150
tools/command.c
@ -47,7 +47,7 @@ static const struct val_name val_names[VAL_COUNT + 1] = {
|
||||
|
||||
/* create table of option names, e.g. --foo, and corresponding enum from args.h */
|
||||
|
||||
static struct opt_name opt_names[ARG_COUNT + 1] = {
|
||||
static const struct opt_name opt_names[ARG_COUNT + 1] = {
|
||||
#define arg(a, b, c, d, e, f, g) { # a, b, a, "--" c, d, e, f, g },
|
||||
#include "args.h"
|
||||
#undef arg
|
||||
@ -85,7 +85,7 @@ static const struct cmd_name cmd_names[CMD_COUNT + 1] = {
|
||||
#ifdef MAN_PAGE_GENERATOR
|
||||
|
||||
static struct command_name command_names[] = {
|
||||
#define xx(a, b, c...) { # a, b, c },
|
||||
#define xx(a, b, c...) { # a, b, c, NULL, a ## _COMMAND },
|
||||
#include "commands.h"
|
||||
#undef xx
|
||||
{ .name = NULL }
|
||||
@ -95,7 +95,7 @@ static struct command commands[COMMAND_COUNT];
|
||||
#else /* MAN_PAGE_GENERATOR */
|
||||
|
||||
struct command_name command_names[] = {
|
||||
#define xx(a, b, c...) { # a, b, c, a},
|
||||
#define xx(a, b, c...) { # a, b, c, a, a ## _COMMAND },
|
||||
#include "commands.h"
|
||||
#undef xx
|
||||
{ .name = NULL }
|
||||
@ -130,7 +130,7 @@ const struct lv_type *get_lv_type(int lvt_enum)
|
||||
|
||||
/* array of pointers into opt_names[] that is sorted alphabetically (by long opt name) */
|
||||
|
||||
static struct opt_name *opt_names_alpha[ARG_COUNT + 1];
|
||||
static const struct opt_name *opt_names_alpha[ARG_COUNT + 1];
|
||||
|
||||
/* lvm_all is for recording options that are common for all lvm commands */
|
||||
|
||||
@ -1517,6 +1517,7 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef MAN_PAGE_GENERATOR
|
||||
/*
|
||||
* The opt_names[] table describes each option. It is indexed by the
|
||||
* option typedef, e.g. size_ARG. The size_ARG entry specifies the
|
||||
@ -1533,8 +1534,10 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
|
||||
* (they are created at build time), but different commands accept different
|
||||
* types of values for the same option, e.g. one command will accept
|
||||
* signed size values (ssizemb_VAL), while another does not accept a signed
|
||||
* number, (sizemb_VAL). This function deals with this problem by tweaking
|
||||
* the opt_names[] table at run time according to the specific command being run.
|
||||
* number, (sizemb_VAL).
|
||||
*
|
||||
* To resolve the issue, at run time command 'reconfigures' its opt_names[]
|
||||
* values by querying particular arg_enum for particular command.
|
||||
* i.e. it changes size_ARG to accept sizemb_VAL or ssizemb_VAL depending
|
||||
* on the command.
|
||||
*
|
||||
@ -1558,53 +1561,57 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
|
||||
* so the commands[] entry for the cmd def already references the
|
||||
* correct ssizemb_VAL.
|
||||
*/
|
||||
void configure_command_option_values(const char *name)
|
||||
int configure_command_option_values(const struct command_name *cname, int arg_enum, int val_enum)
|
||||
{
|
||||
if (!strcmp(name, "lvresize")) {
|
||||
/* relative +|- allowed for LV, + allowed for metadata */
|
||||
opt_names[size_ARG].val_enum = ssizemb_VAL;
|
||||
opt_names[extents_ARG].val_enum = sextents_VAL;
|
||||
opt_names[poolmetadatasize_ARG].val_enum = psizemb_VAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "lvextend")) {
|
||||
/* relative + allowed */
|
||||
opt_names[size_ARG].val_enum = psizemb_VAL;
|
||||
opt_names[extents_ARG].val_enum = pextents_VAL;
|
||||
opt_names[poolmetadatasize_ARG].val_enum = psizemb_VAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "lvreduce")) {
|
||||
/* relative - allowed */
|
||||
opt_names[size_ARG].val_enum = nsizemb_VAL;
|
||||
opt_names[extents_ARG].val_enum = nextents_VAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "lvconvert")) {
|
||||
opt_names[mirrors_ARG].val_enum = snumber_VAL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "lvcreate")) {
|
||||
switch (cname->lvm_command_enum) {
|
||||
case lvconvert_COMMAND:
|
||||
switch (arg_enum) {
|
||||
case mirrors_ARG: return snumber_VAL;
|
||||
}
|
||||
break;
|
||||
case lvcreate_COMMAND:
|
||||
/*
|
||||
* lvcreate is a bit of a mess because it has previously
|
||||
* accepted + but used it as an absolute value, so we
|
||||
* have to recognize it. (We don't want to show the +
|
||||
* option in man/help, though, since it's confusing,
|
||||
* lvcreate is accepts also sizes with + (positive) value,
|
||||
* so we have to recognize it. But we don't want to show
|
||||
* the + option in man/help as it can be seen confusing,
|
||||
* so there's a special case when printing man/help
|
||||
* output to show sizemb_VAL/extents_VAL rather than
|
||||
* psizemb_VAL/pextents_VAL.)
|
||||
*/
|
||||
opt_names[size_ARG].val_enum = psizemb_VAL;
|
||||
opt_names[extents_ARG].val_enum = pextents_VAL;
|
||||
opt_names[poolmetadatasize_ARG].val_enum = psizemb_VAL;
|
||||
opt_names[mirrors_ARG].val_enum = pnumber_VAL;
|
||||
return;
|
||||
switch (arg_enum) {
|
||||
case size_ARG: return psizemb_VAL;
|
||||
case extents_ARG: return pextents_VAL;
|
||||
case poolmetadatasize_ARG: return psizemb_VAL;
|
||||
case mirrors_ARG: return pnumber_VAL;
|
||||
}
|
||||
break;
|
||||
case lvextend_COMMAND:
|
||||
/* relative + allowed */
|
||||
switch (arg_enum) {
|
||||
case size_ARG: return psizemb_VAL;
|
||||
case extents_ARG: return pextents_VAL;
|
||||
case poolmetadatasize_ARG: return psizemb_VAL;
|
||||
}
|
||||
break;
|
||||
case lvreduce_COMMAND:
|
||||
/* relative - allowed */
|
||||
switch (arg_enum) {
|
||||
case size_ARG: return nsizemb_VAL;
|
||||
case extents_ARG: return nextents_VAL;
|
||||
}
|
||||
break;
|
||||
case lvresize_COMMAND:
|
||||
switch (arg_enum) {
|
||||
case size_ARG: return ssizemb_VAL;
|
||||
case extents_ARG: return sextents_VAL;
|
||||
case poolmetadatasize_ARG: return psizemb_VAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return val_enum;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* type_LVT to "type" */
|
||||
|
||||
@ -1644,38 +1651,49 @@ static void _print_usage_description(struct command *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
static void _update_relative_opt(const char *name, int opt_enum, int *val_enum)
|
||||
/* Function remappas existing command definitions val_enums for printing
|
||||
* within man pages or command's help lines */
|
||||
static int _update_relative_opt(const char *name, int opt_enum, int val_enum)
|
||||
{
|
||||
/* check for relative sign */
|
||||
switch (opt_enum) {
|
||||
case extents_ARG:
|
||||
case mirrors_ARG:
|
||||
case poolmetadatasize_ARG:
|
||||
case size_ARG:
|
||||
if (!strcmp(name, "lvconvert"))
|
||||
switch (opt_enum) {
|
||||
case mirrors_ARG: return snumber_VAL;
|
||||
}
|
||||
else if (!strcmp(name, "lvcreate"))
|
||||
/*
|
||||
* Suppress the [+] prefix for lvcreate which we have to
|
||||
* accept for backwards compat, but don't want to advertise.
|
||||
* 'command-lines.in' currently uses PNumber in definition
|
||||
*/
|
||||
if (!strcmp(name, "lvcreate")) {
|
||||
switch (*val_enum) {
|
||||
case psizemb_VAL:
|
||||
*val_enum = sizemb_VAL;
|
||||
break;
|
||||
case pextents_VAL:
|
||||
*val_enum = extents_VAL;
|
||||
break;
|
||||
case pnumber_VAL:
|
||||
if (opt_enum == mirrors_ARG)
|
||||
*val_enum = number_VAL;
|
||||
break;
|
||||
}
|
||||
switch (opt_enum) {
|
||||
case mirrors_ARG: return number_VAL;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(name, "lvextend"))
|
||||
switch (opt_enum) {
|
||||
case extents_ARG: return pextents_VAL;
|
||||
case poolmetadatasize_ARG:
|
||||
case size_ARG: return psizemb_VAL;
|
||||
}
|
||||
else if (!strcmp(name, "lvreduce"))
|
||||
switch (opt_enum) {
|
||||
case extents_ARG: return nextents_VAL;
|
||||
case poolmetadatasize_ARG:
|
||||
case size_ARG: return nsizemb_VAL;
|
||||
}
|
||||
else if (!strcmp(name, "lvresize"))
|
||||
switch (opt_enum) {
|
||||
case extents_ARG: return sextents_VAL;
|
||||
case poolmetadatasize_ARG:
|
||||
case size_ARG: return ssizemb_VAL;
|
||||
}
|
||||
|
||||
return val_enum;
|
||||
}
|
||||
|
||||
static void _print_val_usage(struct command *cmd, int opt_enum, int val_enum)
|
||||
{
|
||||
_update_relative_opt(cmd->name, opt_enum, &val_enum);
|
||||
val_enum = _update_relative_opt(cmd->name, opt_enum, val_enum);
|
||||
|
||||
if (!val_names[val_enum].usage)
|
||||
printf("%s", val_names[val_enum].name);
|
||||
|
@ -35,6 +35,7 @@ struct command_name {
|
||||
const char *desc; /* general command description from commands.h */
|
||||
unsigned int flags;
|
||||
command_fn fn; /* old style */
|
||||
uint16_t lvm_command_enum; /* as declared in commands.h with _COMMAND */
|
||||
|
||||
/* union of {required,optional}_opt_args for all commands with this name */
|
||||
uint16_t valid_args[ARG_COUNT]; /* used for getopt */
|
||||
@ -274,7 +275,7 @@ void print_usage_common_lvm(const struct command_name *cname, struct command *cm
|
||||
void print_usage_notes(const struct command_name *cname);
|
||||
void factor_common_options(void);
|
||||
int command_has_alternate_extents(const char *name);
|
||||
void configure_command_option_values(const char *name);
|
||||
int configure_command_option_values(const struct command_name *cname, int arg_enum, int val_enum);
|
||||
const struct command_name *find_command_name(const char *name);
|
||||
|
||||
#endif
|
||||
|
@ -49,6 +49,13 @@ enum {
|
||||
#undef lvt
|
||||
};
|
||||
|
||||
enum {
|
||||
#define xx(a, b...) a ## _COMMAND,
|
||||
#include "commands.h"
|
||||
#undef xx
|
||||
LVM_COMMAND_COUNT
|
||||
};
|
||||
|
||||
#define PERMITTED_READ_ONLY 0x00000002
|
||||
/* Process all VGs if none specified on the command line. */
|
||||
#define ALL_VGS_IS_DEFAULT 0x00000004
|
||||
|
@ -2021,8 +2021,6 @@ static int _usage(const char *name, int longhelp, int skip_notes)
|
||||
return 0;
|
||||
}
|
||||
|
||||
configure_command_option_values(name);
|
||||
|
||||
/*
|
||||
* Looks at all variants of each command name and figures out
|
||||
* which options are common to all variants (for compact output)
|
||||
@ -2200,6 +2198,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, char ***arg
|
||||
struct arg_values *av;
|
||||
struct arg_value_group_list *current_group = NULL;
|
||||
int arg_enum; /* e.g. foo_ARG */
|
||||
int val_enum;
|
||||
int goval; /* the number returned from getopt_long identifying what it found */
|
||||
int i;
|
||||
|
||||
@ -2291,8 +2290,8 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, char ***arg
|
||||
}
|
||||
|
||||
av->value = optarg;
|
||||
|
||||
if (!get_val_name(a->val_enum)->fn(cmd, av)) {
|
||||
val_enum = configure_command_option_values(cmd->cname, arg_enum, a->val_enum);
|
||||
if (!get_val_name(val_enum)->fn(cmd, av)) {
|
||||
log_error("Invalid argument for %s: %s", a->long_opt, optarg);
|
||||
return 0;
|
||||
}
|
||||
@ -3072,8 +3071,6 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
init_log_command(find_config_tree_bool(cmd, log_command_names_CFG, NULL), 0);
|
||||
|
||||
configure_command_option_values(cmd->name);
|
||||
|
||||
/* eliminate '-' from all options starting with -- */
|
||||
for (i = 1; i < argc; i++) {
|
||||
|
||||
|
@ -119,6 +119,10 @@ static const char *_lvt_enum_to_name(int lvt_enum)
|
||||
return lv_types[lvt_enum].name;
|
||||
}
|
||||
|
||||
static int _get_val_enum(const struct command_name *cname, int opt_enum)
|
||||
{
|
||||
return _update_relative_opt(cname->name, opt_enum, opt_names[opt_enum].val_enum);
|
||||
}
|
||||
/*
|
||||
* FIXME: this just replicates the val usage strings
|
||||
* that officially lives in vals.h. Should there
|
||||
@ -137,8 +141,6 @@ static void _print_val_man(const struct command_name *cname, int opt_enum, int v
|
||||
|
||||
_was_hyphen = 0;
|
||||
|
||||
_update_relative_opt(cname->name, opt_enum, &val_enum);
|
||||
|
||||
switch (val_enum) {
|
||||
case sizemb_VAL:
|
||||
printf("\\fISize\\fP[m|UNIT]");
|
||||
@ -232,7 +234,7 @@ static void _print_val_man(const struct command_name *cname, int opt_enum, int v
|
||||
|
||||
static void _print_def_man(const struct command_name *cname, int opt_enum, struct arg_def *def, int usage, uint64_t *lv_type_bits)
|
||||
{
|
||||
int val_enum;
|
||||
int val_enum, tmp_val;
|
||||
int sep = 0;
|
||||
|
||||
if (lv_type_bits)
|
||||
@ -264,7 +266,8 @@ static void _print_def_man(const struct command_name *cname, int opt_enum, struc
|
||||
printf("\\fI%s\\fP", val_names[val_enum].name);
|
||||
}
|
||||
} else {
|
||||
_print_val_man(cname, opt_enum, val_enum);
|
||||
tmp_val = _update_relative_opt(cname->name, opt_enum, val_enum);
|
||||
_print_val_man(cname, opt_enum, tmp_val);
|
||||
}
|
||||
|
||||
sep = 1;
|
||||
@ -577,7 +580,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
|
||||
* in opt_names[] according to the command name.
|
||||
*/
|
||||
printf("[ \\fB-l\\fP|\\fB--extents\\fP ");
|
||||
_print_val_man(cname, extents_ARG, opt_names[extents_ARG].val_enum);
|
||||
_print_val_man(cname, extents_ARG, _get_val_enum(cname, extents_ARG));
|
||||
|
||||
printf_hyphen(']');
|
||||
sep = 1;
|
||||
@ -1020,7 +1023,7 @@ static void _print_man_all_options_list(const struct command_name *cname)
|
||||
printf(" \\fB%s\\fP", _man_long_opt_name(cname->name, opt_enum));
|
||||
}
|
||||
|
||||
val_enum = opt_names[opt_enum].val_enum;
|
||||
val_enum = _get_val_enum(cname, opt_enum);
|
||||
|
||||
if (!val_names[val_enum].fn) {
|
||||
/* takes no arg */
|
||||
@ -1059,7 +1062,7 @@ static void _print_man_all_options_desc(const struct command_name *cname)
|
||||
if (!cname->all_options[opt_enum])
|
||||
continue;
|
||||
|
||||
val_enum = opt_names[opt_enum].val_enum;
|
||||
val_enum = _get_val_enum(cname, opt_enum);
|
||||
|
||||
if (val_names[val_enum].usage &&
|
||||
(strlen(val_names[val_enum].usage) > _LONG_LINE)) {
|
||||
@ -1781,9 +1784,6 @@ int main(int argc, char *argv[])
|
||||
if (!define_commands(&cmdtool, NULL))
|
||||
goto out_free;
|
||||
|
||||
if (!check)
|
||||
configure_command_option_values(cmdname);
|
||||
|
||||
factor_common_options();
|
||||
|
||||
if (primary && cmdname)
|
||||
|
Loading…
Reference in New Issue
Block a user