1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-16 23:33:16 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
David Teigland
9d326f4ffb commands: new method for defining commands 2016-09-06 16:30:00 -05:00
10 changed files with 155 additions and 7844 deletions

View File

@@ -89,8 +89,8 @@ struct cmd_context {
*/
const char *cmd_line;
struct command *command;
char **pos_arg_values;
struct arg_values *opt_arg_values;
char **argv;
struct arg_values *arg_values;
struct dm_list arg_value_groups;
/*

View File

@@ -1,12 +1,3 @@
#
# When this file is changed, tools/command-lines.h
# and tools/command-lines-count.h must be regenerated
# with:
#
# scripts/create-commands --output count scripts/command-lines.in > tools/command-lines-count.h
# scripts/create-commands --output struct scripts/command-lines.in > tools/command-lines.h
#
#
# A new command has a unique combination of:
# command name, required option args and required
@@ -37,7 +28,7 @@
# --foo is accepted by the command. (This is uncommon.)
#
# Possible option arg types that can follow --opt are:
# Bool, Number, String, PV, VG, LV, Tag.
# Bool, Number, String, PV, VG, LV, Tag, Select.
#
# Option args outside the list of types are treated as literal
# (non-variable) strings or numbers.

View File

@@ -78,52 +78,6 @@ static struct opt_name opt_names[ARG_COUNT + 1] = {
#include "command.h"
#define ARG_DEF_TYPES 16
struct arg_def_type {
const char *name;
int flag;
};
/* The names used for arg_def types in command-lines.in */
static struct arg_def_type arg_def_types[ARG_DEF_TYPES] = {
{ "None", ARG_DEF_TYPE_NONE},
{ "Bool", ARG_DEF_TYPE_BOOL},
{ "Number", ARG_DEF_TYPE_NUM_ANY},
{ "String", ARG_DEF_TYPE_STR_ANY},
{ "Name", ARG_DEF_TYPE_NAME_ANY},
{ "PV", ARG_DEF_TYPE_NAME_PV},
{ "VG", ARG_DEF_TYPE_NAME_VG},
{ "LV", ARG_DEF_TYPE_NAME_LV},
{ "Tag", ARG_DEF_TYPE_TAG},
{ "Select", ARG_DEF_TYPE_SELECT},
};
#define ARG_DEF_LVS 64
struct arg_def_lv {
const char *name;
int flag;
};
/* The names used for arg_def lv_types in command-lines.in */
static struct arg_def_lv arg_def_lvs[ARG_DEF_LVS] = {
{ "LV", ARG_DEF_LV_ANY},
{ "LV_linear", ARG_DEF_LV_LINEAR},
{ "LV_striped", ARG_DEF_LV_STRIPED},
{ "LV_snapshot", ARG_DEF_LV_SNAPSHOT},
{ "LV_mirror", ARG_DEF_LV_MIRROR},
{ "LV_raid", ARG_DEF_LV_RAID},
{ "LV_raid0", ARG_DEF_LV_RAID0},
{ "LV_raid1", ARG_DEF_LV_RAID1},
{ "LV_raid4", ARG_DEF_LV_RAID4},
{ "LV_raid5", ARG_DEF_LV_RAID5},
{ "LV_raid6", ARG_DEF_LV_RAID6},
{ "LV_raid10", ARG_DEF_LV_RAID10},
{ "LV_thin", ARG_DEF_LV_THIN},
{ "LV_thinpool", ARG_DEF_LV_THINPOOL},
{ "LV_cache", ARG_DEF_LV_CACHE},
{ "LV_cachepool", ARG_DEF_LV_CACHEPOOL},
};
#define MAX_CMD_NAMES 128
struct cmd_name {
const char *name;
@@ -890,33 +844,23 @@ static void print_def(struct arg_def *def)
printf(" ...");
}
void print_expanded(void)
void print_data_expanded(void)
{
struct command *cmd;
int onereq;
int i, ro, rp, oo, op;
for (i = 0; i < cmd_count; i++) {
cmd = &cmd_array[i];
printf("%s", cmd->name);
onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
if (cmd->ro_count) {
if (onereq)
printf(" (");
for (ro = 0; ro < cmd->ro_count; ro++) {
if (ro && onereq)
printf(",");
printf(" %s", opt_names[cmd->required_opt_args[ro].opt].long_opt);
if (cmd->required_opt_args[ro].def.types) {
printf(" ");
print_def(&cmd->required_opt_args[ro].def);
}
}
if (onereq)
printf(" )");
}
if (cmd->rp_count) {
@@ -1159,8 +1103,6 @@ static char *flags_to_str(int flags)
void print_define_command_count(void)
{
printf("/* Do not edit. This file is generated by scripts/create-commands */\n");
printf("/* using command definitions from scripts/command-lines.in */\n");
printf("#define COMMAND_COUNT %d\n", cmd_count);
}
@@ -1203,7 +1145,7 @@ void print_usage(struct command *cmd)
goto op_count;
printf("\n");
printf("\" [");
printf("\"[");
if (cmd->oo_count) {
for (oo = 0; oo < cmd->oo_count; oo++) {
@@ -1224,7 +1166,7 @@ void print_usage(struct command *cmd)
goto done;
printf("\n");
printf("\" [");
printf("\"[");
if (cmd->op_count) {
for (op = 0; op < cmd->op_count; op++) {
@@ -1241,33 +1183,21 @@ void print_usage(struct command *cmd)
printf(";\n");
}
void print_command_struct(int only_usage)
void print_command_count(void)
{
printf("#define COMMAND_COUNT %d\n", cmd_count);
}
void print_command_structs(void)
{
struct command *cmd;
int i, j, ro, rp, oo, op;
printf("/* Do not edit. This file is generated by scripts/create-commands */\n");
printf("/* using command definitions from scripts/command-lines.in */\n");
for (i = 0; i < cmd_count; i++) {
cmd = &cmd_array[i];
if (only_usage) {
print_usage(cmd);
printf("\n");
continue;
}
printf("commands[%d].name = \"%s\";\n", i, cmd->name);
printf("commands[%d].fn = %s;\n", i, cmd->name);
printf("commands[%d].ro_count = %d;\n", i, cmd->ro_count);
printf("commands[%d].rp_count = %d;\n", i, cmd->rp_count);
printf("commands[%d].oo_count = %d;\n", i, cmd->oo_count);
printf("commands[%d].op_count = %d;\n", i, cmd->op_count);
if (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT)
printf("commands[%d].cmd_flags = CMD_FLAG_ONE_REQUIRED_OPT;\n", i);
printf("commands[%d].desc = \"%s\";\n", i, cmd->desc ?: "");
printf("commands[%d].usage = ", i);
print_usage(cmd);
@@ -1426,20 +1356,18 @@ void print_option_list(void)
int i;
for (i = 0; i < ARG_COUNT; i++)
printf("%d %s %s %c (%d)\n",
printf("%d %s %s %c\n",
opt_names[i].enum_val, opt_names[i].enum_name,
opt_names[i].long_opt, opt_names[i].short_opt ?: ' ',
opt_names[i].short_opt ? opt_names[i].short_opt : 0);
opt_names[i].long_opt, opt_names[i].short_opt ?: ' ');
}
static void print_help(int argc, char *argv[])
{
printf("%s --output struct|count|usage|expanded <filename>\n", argv[0]);
printf("%s --output struct|count|expand <filename>\n", argv[0]);
printf("\n");
printf("struct: print C structures.\n");
printf("usage: print usage format.\n");
printf("expanded: print expanded input format.\n");
printf("count: print #define COMMAND_COUNT <Number>\n");
printf("struct: print C structures for command definitions.\n");
printf("expand: print expanded input format.\n");
printf("count: print #define COMMAND_COUNT <Number>\n");
}
int main(int argc, char *argv[])
@@ -1463,12 +1391,6 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
if (!strcmp(argv[1], "debug")) {
print_command_list();
print_option_list();
return 0;
}
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
{"output", required_argument, 0, 'o' },
@@ -1543,7 +1465,7 @@ int main(int argc, char *argv[])
char *desc = strdup(strstr(line_orig, ":") + 2);
if (cmd->desc) {
cmd->desc = realloc((char *)cmd->desc, strlen(cmd->desc) + strlen(desc) + 2);
strcat((char *)cmd->desc, " ");
strcat((char *)cmd->desc, "\n");
strcat((char *)cmd->desc, desc);
free(desc);
} else
@@ -1599,15 +1521,13 @@ int main(int argc, char *argv[])
fclose(file);
if (!outputformat)
print_command_struct(1);
print_data_expanded();
else if (!strcmp(outputformat, "struct"))
print_command_struct(0);
print_command_structs();
else if (!strcmp(outputformat, "count"))
print_define_command_count();
else if (!strcmp(outputformat, "usage"))
print_command_struct(1);
else if (!strcmp(outputformat, "expanded"))
print_expanded();
print_command_count();
else if (!strcmp(outputformat, "expand"))
print_data_expanded();
else
print_help(argc, argv);
}

View File

@@ -1,3 +0,0 @@
/* Do not edit. This file is generated by scripts/create-commands */
/* using command definitions from scripts/command-lines.in */
#define COMMAND_COUNT 144

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,7 @@ enum {
ARG_DEF_TYPE_STR_ANY = 1 << 2,
ARG_DEF_TYPE_NUM_CONST = 1 << 3,
ARG_DEF_TYPE_STR_CONST = 1 << 4,
ARG_DEF_TYPE_STR_SET = 1 << 5,
ARG_DEF_TYPE_STR_SET = 1 << 5, /* a set of specific accepted string values */
ARG_DEF_TYPE_NAME_ANY = 1 << 6,
ARG_DEF_TYPE_NAME_PV = 1 << 7,
ARG_DEF_TYPE_NAME_VG = 1 << 8,
@@ -56,6 +56,26 @@ enum {
ARG_DEF_TYPE_SELECT = 1 << 11,
};
#define ARG_DEF_TYPES 16
struct arg_def_type {
const char *name;
int flag;
};
/* The names used for arg_def types in command-lines.in */
static struct arg_def_type arg_def_types[ARG_DEF_TYPES] = {
{ "None", ARG_DEF_TYPE_NONE},
{ "Bool", ARG_DEF_TYPE_BOOL},
{ "Number", ARG_DEF_TYPE_NUM_ANY},
{ "String", ARG_DEF_TYPE_STR_ANY},
{ "Name", ARG_DEF_TYPE_NAME_ANY},
{ "PV", ARG_DEF_TYPE_NAME_PV},
{ "VG", ARG_DEF_TYPE_NAME_VG},
{ "LV", ARG_DEF_TYPE_NAME_LV},
{ "Tag", ARG_DEF_TYPE_TAG},
{ "Select", ARG_DEF_TYPE_SELECT},
};
/* arg_def lv_types, can be multiple */
enum {
ARG_DEF_LV_ANY = 0,
@@ -76,6 +96,32 @@ enum {
ARG_DEF_LV_CACHEPOOL = 1 << 14,
};
#define ARG_DEF_LVS 64
struct arg_def_lv {
const char *name;
int flag;
};
/* The names used for arg_def lv_types in command-lines.in */
static struct arg_def_lv arg_def_lvs[ARG_DEF_LVS] = {
{ "LV", ARG_DEF_LV_ANY},
{ "LV_linear", ARG_DEF_LV_LINEAR},
{ "LV_striped", ARG_DEF_LV_STRIPED},
{ "LV_snapshot", ARG_DEF_LV_SNAPSHOT},
{ "LV_mirror", ARG_DEF_LV_MIRROR},
{ "LV_raid", ARG_DEF_LV_RAID},
{ "LV_raid0", ARG_DEF_LV_RAID0},
{ "LV_raid1", ARG_DEF_LV_RAID1},
{ "LV_raid4", ARG_DEF_LV_RAID4},
{ "LV_raid5", ARG_DEF_LV_RAID5},
{ "LV_raid6", ARG_DEF_LV_RAID6},
{ "LV_raid10", ARG_DEF_LV_RAID10},
{ "LV_thin", ARG_DEF_LV_THIN},
{ "LV_thinpool", ARG_DEF_LV_THINPOOL},
{ "LV_cache", ARG_DEF_LV_CACHE},
{ "LV_cachepool", ARG_DEF_LV_CACHEPOOL},
};
/* Description a value that follows an option or exists in a position. */
struct arg_def {
@@ -106,8 +152,8 @@ struct pos_arg {
* of which one is required after which the rest are
* optional.
*/
#define CMD_RO_ARGS 64 /* required opt args */
#define CMD_OO_ARGS 150 /* optional opt args */
#define CMD_RO_ARGS 32 /* required opt args */
#define CMD_OO_ARGS ARG_COUNT /* optional opt args */
#define CMD_RP_ARGS 8 /* required positional args */
#define CMD_OP_ARGS 8 /* optional positional args */

View File

@@ -55,11 +55,10 @@ static char *_list_cmds(const char *text, int state)
/* List matching arguments */
static char *_list_args(const char *text, int state)
{
#if 0 /* FIXME: just go through args.h */
static int match_no = 0;
static size_t len = 0;
static struct command *com;
/* Initialise if this is a new completion attempt */
if (!state) {
char *s = rl_line_buffer;
@@ -119,7 +118,7 @@ static char *_list_args(const char *text, int state)
if (*(l + 2) && !strncmp(text, l, len))
return strdup(l);
}
#endif
return NULL;
}

View File

@@ -22,6 +22,7 @@ struct cmdline_context {
struct arg_props *arg_props;
struct command *commands;
int num_commands;
int commands_size;
};
int lvm2_main(int argc, char **argv);

View File

@@ -49,13 +49,16 @@ extern char *optarg;
# define OPTIND_INIT 1
#endif
#if 0
#include "command-lines-count.h" /* #define COMMAND_COUNT, generated from command-lines.in */
#endif
#define COMMAND_COUNT 128
/*
* Table of valid switches
*/
static struct arg_props _arg_props[ARG_COUNT + 1] = {
#define arg(a, b, c, d, e, f) {a, b, "", "--" c, d, e, f},
#define arg(a, b, c, d, e, f) {b, "", "--" c, d, e, f},
#include "args.h"
#undef arg
};
@@ -71,10 +74,10 @@ struct command_name {
};
struct command_name command_names[MAX_COMMAND_NAMES] = {
#define xx(a, b, c...) { # a, b, c },
#define xx(a, b, c...) { # a, b, c }
#include "commands.h"
#undef xx
};
}
/*
* Table of valid command lines
@@ -731,7 +734,7 @@ int metadatacopies_arg(struct cmd_context *cmd, struct arg_values *av)
return int_arg(cmd, av);
}
static struct command_name *_find_command_name(const char *name)
static struct command_name *_find_command_name(char *name)
{
int i;
@@ -744,7 +747,7 @@ static struct command_name *_find_command_name(const char *name)
return NULL;
}
static void _define_commands(void)
void _define_commands(void)
{
/* command-lines.h defines command[] structs, generated from command-lines.in */
#include "command-lines.h" /* generated from command-lines.in */
@@ -755,11 +758,9 @@ void lvm_register_commands(void)
struct command_name *cname;
int i;
memset(&commands, 0, sizeof(commands));
_define_commands();
_cmdline.commands = commands;
_cmdline.commands = &commands;
_cmdline.num_commands = COMMAND_COUNT;
for (i = 0; i < COMMAND_COUNT; i++) {
@@ -793,37 +794,37 @@ void lvm_register_commands(void)
static int _opt_equivalent_is_set(struct cmd_context *cmd, int opt)
{
if ((opt == mirrorlog_ARG) && arg_is_set(cmd, corelog_ARG))
if ((opt == mirrorlog_ARG) && arg_is_set(cmd, corelog_ARG, NULL))
return 1;
if ((opt == resizeable_ARG) && arg_is_set(cmd, resizable_ARG))
if ((opt == resizeable_ARG) && arg_is_set(cmd, resizable_ARG, NULL))
return 1;
if ((opt == allocatable_ARG) && arg_is_set(cmd, allocation_ARG))
if ((opt == allocatable_ARG) && arg_is_set(cmd, allocation_ARG, NULL))
return 1;
if ((opt == resizeable_ARG) && arg_is_set(cmd, allocation_ARG))
if ((opt == resizeable_ARG) && arg_is_set(cmd, allocation_ARG, NULL))
return 1;
if ((opt == activate_ARG) && arg_is_set(cmd, available_ARG))
if ((opt == activate_ARG) && arg_is_set(cmd, available_ARG, NULL))
return 1;
if ((opt == rebuild_ARG) && arg_is_set(cmd, raidrebuild_ARG))
if ((opt == rebuild_ARG) && arg_is_set(cmd, raidrebuild_ARG, NULL))
return 1;
if ((opt == syncaction_ARG) && arg_is_set(cmd, raidsyncaction_ARG))
if ((opt == syncaction_ARG) && arg_is_set(cmd, raidsyncaction_ARG, NULL))
return 1;
if ((opt == writemostly_ARG) && arg_is_set(cmd, raidwritemostly_ARG))
if ((opt == writemostly_ARG) && arg_is_set(cmd, raidwritemostly_ARG, NULL))
return 1;
if ((opt == minrecoveryrate_ARG) && arg_is_set(cmd, raidminrecoveryrate_ARG))
if ((opt == minrecoveryrate_ARG) && arg_is_set(cmd, raidminrecoveryrate_ARG, NULL))
return 1;
if ((opt == maxrecoveryrate_ARG) && arg_is_set(cmd, raidmaxrecoveryrate_ARG))
if ((opt == maxrecoveryrate_ARG) && arg_is_set(cmd, raidmaxrecoveryrate_ARG, NULL))
return 1;
if ((opt == writebehind_ARG) && arg_is_set(cmd, raidwritebehind_ARG))
if ((opt == writebehind_ARG) && arg_is_set(cmd, raidwritebehind_ARG, NULL))
return 1;
return 0;
@@ -831,18 +832,18 @@ static int _opt_equivalent_is_set(struct cmd_context *cmd, int opt)
static int _command_required_opt_matches(struct cmd_context *cmd, int ci, int ro)
{
if (arg_is_set(cmd, commands[ci].required_opt_args[ro].opt))
if (arg_is_set(cmd, commands[ci].required_opt_args[ro].opt, NULL))
return 1;
/*
* For some commands, --size and --extents are interchanable,
* but command[] definitions use only --size.
*/
if ((commands[ci].required_opt_args[ro].opt == size_ARG) && arg_is_set(cmd, extents_ARG)) {
if (!strcmp(commands[ci].name, "lvcreate") ||
!strcmp(commands[ci].name, "lvresize") ||
!strcmp(commands[ci].name, "lvextend") ||
!strcmp(commands[ci].name, "lvreduce"))
if ((commands[ci].required_opt_args[ro].opt == size_ARG) && arg_is_set(cmd, extents_ARG, NULL)) {
if (!strcmp(commands[i].name, "lvcreate") ||
!strcmp(commands[i].name, "lvresize")
!strcmp(commands[i].name, "lvextend")
!strcmp(commands[i].name, "lvreduce"))
return 1;
}
@@ -850,8 +851,6 @@ static int _command_required_opt_matches(struct cmd_context *cmd, int ci, int ro
if (_opt_equivalent_is_set(cmd, commands[ci].required_opt_args[ro].opt))
return 1;
return 0;
}
static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp)
@@ -867,7 +866,7 @@ static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp
* empty if --select is used.
*/
if ((commands[ci].required_pos_args[rp].def.types & ARG_DEF_TYPE_SELECT) &&
arg_is_set(cmd, select_ARG))
arg_is_set(cmd, select_ARG, NULL))
return 1;
return 0;
@@ -876,11 +875,8 @@ static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp
static struct command *_find_command(struct cmd_context *cmd, const char *path)
{
const char *name;
int match_count, mismatch_count;
int best_match_i = 0, best_match_count = 0;
int closest_i = 0, closest_count = 0;
int ro_matches;
int ro, rp;
int found = 0;
int i;
name = last_path_component(path);
@@ -889,60 +885,39 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path)
if (strcmp(name, commands[i].name))
continue;
match_count = 0;
match_count = 1; /* for command name matching */
mismatch_count = 0;
ro_matches = 0;
/* if the command name alone is enough, then that's a match */
if (!commands[i].ro_count && !commands[i].rp_count) {
/* log_warn("match %d command name %s", i, name); */
match_count = 1;
}
/* match required_opt_args */
for (ro = 0; ro < commands[i].ro_count; ro++) {
if (_command_required_opt_matches(cmd, i, ro)) {
/* log_warn("match %d ro opt %d", i, commands[i].required_opt_args[ro].opt); */
if (_command_required_opt_matches(cmd, i, ro))
match_count++;
ro_matches++;
} else {
/* cmd is missing a required opt arg */
/* log_warn("mismatch %d ro opt %d", i, commands[i].required_opt_args[ro].opt); */
else
mismatch_count++;
}
}
/*
* Special case where missing required_opt_arg's does not matter
* if one required_opt_arg did match.
* One item in required_opt_args must be set for
* a match, and the rest are optional (don't count
* as mismatches).
*/
if (commands[i].cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) {
if (ro_matches) {
/* one or more of the required_opt_args is used */
if (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) {
if (match_count >= 2) {
match_count = 2;
mismatch_count = 0;
} else {
/* not even one of the required_opt_args is used */
mismatch_count = 1;
}
}
/* match required_pos_args */
for (rp = 0; rp < commands[i].rp_count; rp++) {
if (_command_required_pos_matches(cmd, i, rp)) {
/* log_warn("match %d rp %d", i, commands[i].required_pos_args[rp].pos); */
if (_command_required_pos_matches(cmd, i, rp))
match_count++;
} else {
/* cmd is missing a required pos arg */
/* log_warn("mismatch %d rp %d", i, commands[i].required_pos_args[rp].pos); */
else
mismatch_count++;
}
}
/* if cmd is missing any required opt/pos args, it can't be this command. */
if (mismatch_count) {
/* save i/match_count for "closest" command that doesn't match */
if (!closest_count || (match_count > closest_count)) {
@@ -952,21 +927,18 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path)
continue;
}
/* use command that has the most matching required opt/pos */
if (!best_match_count || (match_count > best_match_count)) {
/* log_warn("match best i %d count %d", i, match_count); */
best_match_i = i;
best_match_count = match_count;
}
}
if (!best_match_count) {
/* cmd did not have all the required opt/pos args of any command */
/* nothing matches */
/* TODO: report closest matching command and report missing required opt/pos args for that? */
log_error("Failed to find a matching command definition.");
if (closest_count) {
log_warn("Closest command usage is:");
/* FIXME: _print_usage_required(commands[closest_i].usage); with new lines, aligned, etc */
log_warn("%s", commands[closest_i].usage);
}
return NULL;
@@ -980,7 +952,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path)
* Same for pos args.
*/
/* log_warn("command matched: %.256s ...", commands[best_match_i].usage); */
log_debug("matched command usage: %.80s ...", commands[best_match_i].usage);
return &commands[best_match_i];
}
@@ -1006,83 +978,53 @@ static int _usage(const char *name)
}
/*
* Sets up the arguments to pass to getopt_long().
*
* getopt_long() takes a string of short option characters
* where the char is followed by ":" if the option takes an arg,
* e.g. "abc:d:" This string is created in optstrp.
*
* getopt_long() also takes an array of struct option which
* has the name of the long option, if it takes an arg, etc,
* e.g.
*
* option long_options[] = {
* { "foo", required_argument, 0, 0 },
* { "bar", no_argument, 0, 'b' }
* };
*
* this array is created in longoptsp.
*
* Original comment:
* Sets up the short and long argument. If there
* is no short argument then the index of the
* argument in the the_args array is set as the
* long opt value. Yuck. Of course this means we
* can't have more than 'a' long arguments.
*/
static void _add_getopt_arg(int arg_enum, char **optstrp, struct option **longoptsp)
static void _add_getopt_arg(int arg, char **ptr, struct option **o)
{
struct arg_props *a = _cmdline.arg_props + arg_enum;
struct arg_props *a = _cmdline.arg_props + arg;
if (a->short_arg) {
*(*optstrp)++ = a->short_arg;
*(*ptr)++ = a->short_arg;
if (a->fn)
*(*optstrp)++ = ':';
*(*ptr)++ = ':';
}
#ifdef HAVE_GETOPTLONG
/* long_arg is "--foo", so +2 is the offset of the name after "--" */
if (*(a->long_arg + 2)) {
(*longoptsp)->name = a->long_arg + 2;
(*longoptsp)->has_arg = a->fn ? 1 : 0;
(*longoptsp)->flag = NULL;
/*
* When getopt_long() sees an option that has an associated
* single letter, it returns the ascii value of that letter.
* e.g. getopt_long() returns 100 for '-d' or '--debug'
* (100 is the ascii value of 'd').
*
* When getopt_long() sees an option that does not have an
* associated single letter, it returns the value of the
* the enum for that long option name plus 128.
* e.g. getopt_long() returns 139 for --cachepool
* (11 is the enum value for --cachepool, so 11+128)
*/
(*o)->name = a->long_arg + 2;
(*o)->has_arg = a->fn ? 1 : 0;
(*o)->flag = NULL;
if (a->short_arg)
(*longoptsp)->val = a->short_arg;
(*o)->val = a->short_arg;
else
(*longoptsp)->val = arg_enum + 128;
(*longoptsp)++;
(*o)->val = arg + 128;
(*o)++;
}
#endif
}
static int _find_arg(int goval)
static int _find_arg(struct command *com, int opt)
{
int i;
struct arg_props *a;
int i, arg;
for (i = 0; i < ARG_COUNT; i++) {
/* the value returned by getopt matches the ascii value of single letter option */
if (_cmdline.arg_props[i].short_arg && (goval == _cmdline.arg_props[i].short_arg))
return _cmdline.arg_props[i].enum_val;
for (i = 0; i < com->num_args; i++) {
arg = com->valid_args[i];
a = _cmdline.arg_props + arg;
/* the value returned by getopt matches the enum value plus 128 */
if (!_cmdline.arg_props[i].short_arg && (goval == _cmdline.arg_props[i].enum_val + 128))
return _cmdline.arg_props[i].enum_val;
/*
* opt should equal either the
* short arg, or the index into
* the_args.
*/
if ((a->short_arg && (opt == a->short_arg)) ||
(!a->short_arg && (opt == (arg + 128))))
return arg;
}
return -1;
@@ -1091,27 +1033,21 @@ static int _find_arg(int goval)
static int _process_command_line(struct cmd_context *cmd, int *argc,
char ***argv)
{
int i, opt, arg;
char str[((ARG_COUNT + 1) * 2) + 1], *ptr = str;
struct option opts[ARG_COUNT + 1], *o = opts;
struct arg_props *a;
struct arg_values *av;
struct arg_value_group_list *current_group = NULL;
int arg_enum; /* e.g. foo_ARG */
int goval; /* the number returned from getopt_long identifying what it found */
int i;
if (!(cmd->opt_arg_values = dm_pool_zalloc(cmd->mem, sizeof(*cmd->opt_arg_values) * ARG_COUNT))) {
log_fatal("Unable to allocate memory for command line arguments.");
return 0;
}
/*
* create the short-form character array (str) and the long-form option
* array (opts) to pass to the getopt_long() function. IOW we generate
* the arguments to pass to getopt_long() from the args.h/arg_props data.
*/
for (i = 0; i < ARG_COUNT; i++)
_add_getopt_arg(_cmdline.arg_props[i].enum_val, &ptr, &o);
/* fill in the short and long opts */
for (i = 0; i < cmd->command->num_args; i++)
_add_getopt_arg(cmd->command->valid_args[i], &ptr, &o);
*ptr = '\0';
memset(o, 0, sizeof(*o));
@@ -1119,23 +1055,19 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
/* initialise getopt_long & scan for command line switches */
optarg = 0;
optind = OPTIND_INIT;
while ((goval = GETOPTLONG_FN(*argc, *argv, str, opts, NULL)) >= 0) {
while ((opt = GETOPTLONG_FN(*argc, *argv, str, opts, NULL)) >= 0) {
if (goval == '?')
if (opt == '?')
return 0;
/*
* translate the option value used by getopt into the enum
* value (e.g. foo_ARG) from the args array....
*/
if ((arg_enum = _find_arg(goval)) < 0) {
if ((arg = _find_arg(cmd->command, opt)) < 0) {
log_fatal("Unrecognised option.");
return 0;
}
a = _cmdline.arg_props + arg_enum;
a = _cmdline.arg_props + arg;
av = &cmd->opt_arg_values[arg_enum];
av = &cmd->opt_arg_values[arg];
if (a->flags & ARG_GROUPABLE) {
/*
@@ -1145,7 +1077,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
* - or if argument has higher priority than current group.
*/
if (!current_group ||
(current_group->arg_values[arg_enum].count && !(a->flags & ARG_COUNTABLE)) ||
(current_group->arg_values[arg].count && !(a->flags & ARG_COUNTABLE)) ||
(current_group->prio < a->prio)) {
/* FIXME Reduce size including only groupable args */
if (!(current_group = dm_pool_zalloc(cmd->mem, sizeof(struct arg_value_group_list) + sizeof(*cmd->opt_arg_values) * ARG_COUNT))) {
@@ -1158,7 +1090,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
}
/* Maintain total argument count as well as count within each group */
av->count++;
av = &current_group->arg_values[arg_enum];
av = &current_group->arg_values[arg];
}
if (av->count && !(a->flags & ARG_COUNTABLE)) {
@@ -1720,7 +1652,6 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
{
struct dm_config_tree *config_string_cft, *config_profile_command_cft, *config_profile_metadata_cft;
const char *reason = NULL;
const char *cmd_name;
int ret = 0;
int locking_type;
int monitoring;
@@ -1734,8 +1665,6 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
/* each command should start out with sigint flag cleared */
sigint_clear();
cmd_name = strdup(argv[0]);
/* eliminate '-' from all options starting with -- */
for (i = 1; i < argc; i++) {
@@ -1779,10 +1708,10 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
if (!(cmd->command = _find_command(cmd, cmd_name)))
if (!(cmd->command = _find_command(cmd, argv[0])))
return ENO_SUCH_CMD;
set_cmd_name(cmd_name);
set_cmd_name(cmd->command->name);
if (arg_is_set(cmd, backgroundfork_ARG)) {
if (!become_daemon(cmd, 1)) {

View File

@@ -81,7 +81,6 @@ struct arg_values {
/* a global table of possible arguments */
struct arg_props {
int enum_val;
const char short_arg;
char _padding[7];
const char *long_arg;