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 */
|
/* 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 },
|
#define arg(a, b, c, d, e, f, g) { # a, b, a, "--" c, d, e, f, g },
|
||||||
#include "args.h"
|
#include "args.h"
|
||||||
#undef arg
|
#undef arg
|
||||||
@ -85,7 +85,7 @@ static const struct cmd_name cmd_names[CMD_COUNT + 1] = {
|
|||||||
#ifdef MAN_PAGE_GENERATOR
|
#ifdef MAN_PAGE_GENERATOR
|
||||||
|
|
||||||
static struct command_name command_names[] = {
|
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"
|
#include "commands.h"
|
||||||
#undef xx
|
#undef xx
|
||||||
{ .name = NULL }
|
{ .name = NULL }
|
||||||
@ -95,7 +95,7 @@ static struct command commands[COMMAND_COUNT];
|
|||||||
#else /* MAN_PAGE_GENERATOR */
|
#else /* MAN_PAGE_GENERATOR */
|
||||||
|
|
||||||
struct command_name command_names[] = {
|
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"
|
#include "commands.h"
|
||||||
#undef xx
|
#undef xx
|
||||||
{ .name = NULL }
|
{ .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) */
|
/* 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 */
|
/* 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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef MAN_PAGE_GENERATOR
|
||||||
/*
|
/*
|
||||||
* The opt_names[] table describes each option. It is indexed by the
|
* The opt_names[] table describes each option. It is indexed by the
|
||||||
* option typedef, e.g. size_ARG. The size_ARG entry specifies 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
|
* (they are created at build time), but different commands accept different
|
||||||
* types of values for the same option, e.g. one command will accept
|
* 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
|
* signed size values (ssizemb_VAL), while another does not accept a signed
|
||||||
* number, (sizemb_VAL). This function deals with this problem by tweaking
|
* number, (sizemb_VAL).
|
||||||
* the opt_names[] table at run time according to the specific command being run.
|
*
|
||||||
|
* 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
|
* i.e. it changes size_ARG to accept sizemb_VAL or ssizemb_VAL depending
|
||||||
* on the command.
|
* 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
|
* so the commands[] entry for the cmd def already references the
|
||||||
* correct ssizemb_VAL.
|
* 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")) {
|
switch (cname->lvm_command_enum) {
|
||||||
/* relative +|- allowed for LV, + allowed for metadata */
|
case lvconvert_COMMAND:
|
||||||
opt_names[size_ARG].val_enum = ssizemb_VAL;
|
switch (arg_enum) {
|
||||||
opt_names[extents_ARG].val_enum = sextents_VAL;
|
case mirrors_ARG: return snumber_VAL;
|
||||||
opt_names[poolmetadatasize_ARG].val_enum = psizemb_VAL;
|
}
|
||||||
return;
|
break;
|
||||||
}
|
case lvcreate_COMMAND:
|
||||||
|
|
||||||
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")) {
|
|
||||||
/*
|
/*
|
||||||
* lvcreate is a bit of a mess because it has previously
|
* lvcreate is accepts also sizes with + (positive) value,
|
||||||
* accepted + but used it as an absolute value, so we
|
* so we have to recognize it. But we don't want to show
|
||||||
* have to recognize it. (We don't want to show the +
|
* the + option in man/help as it can be seen confusing,
|
||||||
* option in man/help, though, since it's confusing,
|
|
||||||
* so there's a special case when printing man/help
|
* so there's a special case when printing man/help
|
||||||
* output to show sizemb_VAL/extents_VAL rather than
|
* output to show sizemb_VAL/extents_VAL rather than
|
||||||
* psizemb_VAL/pextents_VAL.)
|
* psizemb_VAL/pextents_VAL.)
|
||||||
*/
|
*/
|
||||||
opt_names[size_ARG].val_enum = psizemb_VAL;
|
switch (arg_enum) {
|
||||||
opt_names[extents_ARG].val_enum = pextents_VAL;
|
case size_ARG: return psizemb_VAL;
|
||||||
opt_names[poolmetadatasize_ARG].val_enum = psizemb_VAL;
|
case extents_ARG: return pextents_VAL;
|
||||||
opt_names[mirrors_ARG].val_enum = pnumber_VAL;
|
case poolmetadatasize_ARG: return psizemb_VAL;
|
||||||
return;
|
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" */
|
/* 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 */
|
/* check for relative sign */
|
||||||
switch (opt_enum) {
|
if (!strcmp(name, "lvconvert"))
|
||||||
case extents_ARG:
|
switch (opt_enum) {
|
||||||
case mirrors_ARG:
|
case mirrors_ARG: return snumber_VAL;
|
||||||
case poolmetadatasize_ARG:
|
}
|
||||||
case size_ARG:
|
else if (!strcmp(name, "lvcreate"))
|
||||||
/*
|
/*
|
||||||
* Suppress the [+] prefix for lvcreate which we have to
|
* Suppress the [+] prefix for lvcreate which we have to
|
||||||
* accept for backwards compat, but don't want to advertise.
|
* accept for backwards compat, but don't want to advertise.
|
||||||
|
* 'command-lines.in' currently uses PNumber in definition
|
||||||
*/
|
*/
|
||||||
if (!strcmp(name, "lvcreate")) {
|
switch (opt_enum) {
|
||||||
switch (*val_enum) {
|
case mirrors_ARG: return number_VAL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
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)
|
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)
|
if (!val_names[val_enum].usage)
|
||||||
printf("%s", val_names[val_enum].name);
|
printf("%s", val_names[val_enum].name);
|
||||||
|
@ -35,6 +35,7 @@ struct command_name {
|
|||||||
const char *desc; /* general command description from commands.h */
|
const char *desc; /* general command description from commands.h */
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
command_fn fn; /* old style */
|
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 */
|
/* union of {required,optional}_opt_args for all commands with this name */
|
||||||
uint16_t valid_args[ARG_COUNT]; /* used for getopt */
|
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 print_usage_notes(const struct command_name *cname);
|
||||||
void factor_common_options(void);
|
void factor_common_options(void);
|
||||||
int command_has_alternate_extents(const char *name);
|
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);
|
const struct command_name *find_command_name(const char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,6 +49,13 @@ enum {
|
|||||||
#undef lvt
|
#undef lvt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
#define xx(a, b...) a ## _COMMAND,
|
||||||
|
#include "commands.h"
|
||||||
|
#undef xx
|
||||||
|
LVM_COMMAND_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
#define PERMITTED_READ_ONLY 0x00000002
|
#define PERMITTED_READ_ONLY 0x00000002
|
||||||
/* Process all VGs if none specified on the command line. */
|
/* Process all VGs if none specified on the command line. */
|
||||||
#define ALL_VGS_IS_DEFAULT 0x00000004
|
#define ALL_VGS_IS_DEFAULT 0x00000004
|
||||||
|
@ -2021,8 +2021,6 @@ static int _usage(const char *name, int longhelp, int skip_notes)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_command_option_values(name);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Looks at all variants of each command name and figures out
|
* Looks at all variants of each command name and figures out
|
||||||
* which options are common to all variants (for compact output)
|
* 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_values *av;
|
||||||
struct arg_value_group_list *current_group = NULL;
|
struct arg_value_group_list *current_group = NULL;
|
||||||
int arg_enum; /* e.g. foo_ARG */
|
int arg_enum; /* e.g. foo_ARG */
|
||||||
|
int val_enum;
|
||||||
int goval; /* the number returned from getopt_long identifying what it found */
|
int goval; /* the number returned from getopt_long identifying what it found */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -2291,8 +2290,8 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, char ***arg
|
|||||||
}
|
}
|
||||||
|
|
||||||
av->value = optarg;
|
av->value = optarg;
|
||||||
|
val_enum = configure_command_option_values(cmd->cname, arg_enum, a->val_enum);
|
||||||
if (!get_val_name(a->val_enum)->fn(cmd, av)) {
|
if (!get_val_name(val_enum)->fn(cmd, av)) {
|
||||||
log_error("Invalid argument for %s: %s", a->long_opt, optarg);
|
log_error("Invalid argument for %s: %s", a->long_opt, optarg);
|
||||||
return 0;
|
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);
|
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 -- */
|
/* eliminate '-' from all options starting with -- */
|
||||||
for (i = 1; i < argc; i++) {
|
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;
|
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
|
* FIXME: this just replicates the val usage strings
|
||||||
* that officially lives in vals.h. Should there
|
* 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;
|
_was_hyphen = 0;
|
||||||
|
|
||||||
_update_relative_opt(cname->name, opt_enum, &val_enum);
|
|
||||||
|
|
||||||
switch (val_enum) {
|
switch (val_enum) {
|
||||||
case sizemb_VAL:
|
case sizemb_VAL:
|
||||||
printf("\\fISize\\fP[m|UNIT]");
|
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)
|
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;
|
int sep = 0;
|
||||||
|
|
||||||
if (lv_type_bits)
|
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);
|
printf("\\fI%s\\fP", val_names[val_enum].name);
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
sep = 1;
|
||||||
@ -577,7 +580,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
|
|||||||
* in opt_names[] according to the command name.
|
* in opt_names[] according to the command name.
|
||||||
*/
|
*/
|
||||||
printf("[ \\fB-l\\fP|\\fB--extents\\fP ");
|
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(']');
|
printf_hyphen(']');
|
||||||
sep = 1;
|
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));
|
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) {
|
if (!val_names[val_enum].fn) {
|
||||||
/* takes no arg */
|
/* 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])
|
if (!cname->all_options[opt_enum])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
val_enum = opt_names[opt_enum].val_enum;
|
val_enum = _get_val_enum(cname, opt_enum);
|
||||||
|
|
||||||
if (val_names[val_enum].usage &&
|
if (val_names[val_enum].usage &&
|
||||||
(strlen(val_names[val_enum].usage) > _LONG_LINE)) {
|
(strlen(val_names[val_enum].usage) > _LONG_LINE)) {
|
||||||
@ -1781,9 +1784,6 @@ int main(int argc, char *argv[])
|
|||||||
if (!define_commands(&cmdtool, NULL))
|
if (!define_commands(&cmdtool, NULL))
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
if (!check)
|
|
||||||
configure_command_option_values(cmdname);
|
|
||||||
|
|
||||||
factor_common_options();
|
factor_common_options();
|
||||||
|
|
||||||
if (primary && cmdname)
|
if (primary && cmdname)
|
||||||
|
Loading…
Reference in New Issue
Block a user