mirror of
git://sourceware.org/git/lvm2.git
synced 2025-10-03 01:44:19 +03:00
Compare commits
1 Commits
dev-dct-cm
...
dev-dct-cm
Author | SHA1 | Date | |
---|---|---|---|
|
45e5f204be |
@@ -56,7 +56,7 @@ fail lvcreate -l 1 --cachepool pool8 $vg
|
||||
|
||||
# no size specified
|
||||
invalid lvcreate --cachepool pool $vg 2>&1 | tee err
|
||||
grep "specify either size or extents" err
|
||||
# grep "specify either size or extents" err
|
||||
|
||||
# Check nothing has been created yet
|
||||
check vg_field $vg lv_count 0
|
||||
|
@@ -23,7 +23,6 @@ lvcreate -l 1 -n lv1 $vg "$dev1"
|
||||
invalid vgextend
|
||||
# --metadatacopies => use --pvmetadatacopies
|
||||
invalid vgextend --metadatacopies 3 $vg "$dev1" 2>&1 | tee out
|
||||
grep -- "use --pvmetadatacopies" out
|
||||
|
||||
# VG name should exist
|
||||
fail vgextend --restoremissing $vg-invalid "$dev1"
|
||||
|
@@ -76,6 +76,7 @@ SOURCES2 =\
|
||||
|
||||
TARGETS =\
|
||||
.commands \
|
||||
command-lines.h \
|
||||
liblvm2cmd.a \
|
||||
lvm
|
||||
|
||||
@@ -99,7 +100,8 @@ LIB_VERSION = $(LIB_VERSION_LVM)
|
||||
CLEAN_TARGETS = liblvm2cmd.$(LIB_SUFFIX) $(TARGETS_DM) \
|
||||
liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION) lvm-static.o \
|
||||
liblvm2cmd-static.a dmsetup.static lvm.static \
|
||||
$(LDDEPS) .exported_symbols_generated
|
||||
$(LDDEPS) .exported_symbols_generated \
|
||||
ccmd command-lines.h command-lines-count.h
|
||||
|
||||
ifeq ("@CMDLIB@", "yes")
|
||||
TARGETS += liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION)
|
||||
@@ -171,6 +173,13 @@ liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION): liblvm2cmd.$(LIB_SUFFIX)
|
||||
$(CC) -E -P $(srcdir)/cmdnames.h 2> /dev/null | \
|
||||
egrep -v '^ *(|#.*|config|devtypes|dumpconfig|formats|fullreport|help|lastlog|lvpoll|pvdata|segtypes|systemid|tags|version) *$$' > .commands
|
||||
|
||||
ccmd: create-commands.c
|
||||
$(CC) create-commands.c -o ccmd
|
||||
|
||||
command-lines.h: ccmd
|
||||
./ccmd --output struct command-lines.in > command-lines.h
|
||||
./ccmd --output count command-lines.in > command-lines-count.h
|
||||
|
||||
ifneq ("$(CFLOW_CMD)", "")
|
||||
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
|
||||
-include $(top_builddir)/libdm/libdevmapper.cflow
|
||||
|
@@ -87,7 +87,7 @@ arg(poolmetadata_ARG, '\0', "poolmetadata", lv_VAL, 0, 0)
|
||||
arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", sizemb_VAL, 0, 0)
|
||||
arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", bool_VAL, 0, 0)
|
||||
arg(profile_ARG, '\0', "profile", string_VAL, 0, 0)
|
||||
arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", number_VAL, 0, 0)
|
||||
arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", pvmetadatacopies_VAL, 0, 0)
|
||||
arg(raidrebuild_ARG, '\0', "raidrebuild", string_VAL, ARG_GROUPABLE, 0)
|
||||
arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", sizekb_VAL, 0, 0)
|
||||
arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", sizekb_VAL, 0, 0)
|
||||
@@ -133,7 +133,7 @@ arg(unquoted_ARG, '\0', "unquoted", 0, 0, 0)
|
||||
arg(usepolicies_ARG, '\0', "usepolicies", 0, 0, 0)
|
||||
arg(validate_ARG, '\0', "validate", 0, 0, 0)
|
||||
arg(version_ARG, '\0', "version", 0, 0, 0)
|
||||
arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", metadatacopies_VAL, 0, 0)
|
||||
arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", vgmetadatacopies_VAL, 0, 0)
|
||||
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", sizemb_VAL, 0, 0)
|
||||
arg(withsummary_ARG, '\0', "withsummary", 0, 0, 0)
|
||||
arg(withcomments_ARG, '\0', "withcomments", 0, 0, 0)
|
||||
|
@@ -1,133 +0,0 @@
|
||||
/* Do not edit. This file is generated by scripts/create-commands */
|
||||
/* using command definitions from scripts/command-lines.in */
|
||||
#define COMMAND_COUNT 147
|
||||
enum {
|
||||
no_CMD,
|
||||
lvchange_properties_CMD,
|
||||
lvchange_resync_CMD,
|
||||
lvchange_syncaction_CMD,
|
||||
lvchange_rebuild_CMD,
|
||||
lvchange_activate_CMD,
|
||||
lvchange_refresh_CMD,
|
||||
lvchange_monitor_CMD,
|
||||
lvchange_poll_CMD,
|
||||
lvchange_persistent_CMD,
|
||||
lvconvert_merge_CMD,
|
||||
lvconvert_combine_split_snapshot_CMD,
|
||||
lvconvert_to_thin_with_external_CMD,
|
||||
lvconvert_to_cache_vol_CMD,
|
||||
lvconvert_to_thinpool_CMD,
|
||||
lvconvert_to_cachepool_CMD,
|
||||
lvconvert_to_mirror_CMD,
|
||||
lvconvert_to_mirror_or_raid1_CMD,
|
||||
lvconvert_raid1_to_mirror_CMD,
|
||||
lvconvert_mirror_to_raid1_CMD,
|
||||
lvconvert_general_to_raid_CMD,
|
||||
lvconvert_change_mirror_images_CMD,
|
||||
lvconvert_raid_to_striped_CMD,
|
||||
lvconvert_raid_or_mirror_to_linear_CMD,
|
||||
lvconvert_split_mirror_images_to_new_CMD,
|
||||
lvconvert_split_mirror_images_and_track_CMD,
|
||||
lvconvert_repair_pvs_or_thinpool_CMD,
|
||||
lvconvert_replace_pv_CMD,
|
||||
lvconvert_change_mirrorlog_CMD,
|
||||
lvconvert_split_and_keep_cachepool_CMD,
|
||||
lvconvert_split_and_delete_cachepool_CMD,
|
||||
lvconvert_split_cow_snapshot_CMD,
|
||||
lvconvert_poll_mirror_CMD,
|
||||
lvconvert_swap_pool_metadata_CMD,
|
||||
lvcreate_error_vol_CMD,
|
||||
lvcreate_zero_vol_CMD,
|
||||
lvcreate_linear_CMD,
|
||||
lvcreate_striped_CMD,
|
||||
lvcreate_mirror_CMD,
|
||||
lvcreate_raid_any_CMD,
|
||||
lvcreate_cow_snapshot_CMD,
|
||||
lvcreate_cow_snapshot_with_virtual_origin_CMD,
|
||||
lvcreate_thinpool_CMD,
|
||||
lvcreate_cachepool_CMD,
|
||||
lvcreate_thin_vol_CMD,
|
||||
lvcreate_thin_snapshot_CMD,
|
||||
lvcreate_thin_snapshot_of_external_CMD,
|
||||
lvcreate_thin_vol_with_thinpool_CMD,
|
||||
lvcreate_thin_vol_with_thinpool_or_sparse_snapshot_CMD,
|
||||
lvcreate_convert_to_cache_vol_with_cachepool_CMD,
|
||||
lvcreate_cache_vol_with_new_origin_CMD,
|
||||
lvdisplay_general_CMD,
|
||||
lvextend_by_size_CMD,
|
||||
lvextend_by_pv_CMD,
|
||||
lvextend_pool_metadata_by_size_CMD,
|
||||
lvextend_by_policy_CMD,
|
||||
lvmconfig_general_CMD,
|
||||
lvreduce_general_CMD,
|
||||
lvremove_general_CMD,
|
||||
lvrename_vg_lv_lv_CMD,
|
||||
lvrename_lv_lv_CMD,
|
||||
lvresize_by_size_CMD,
|
||||
lvresize_by_pv_CMD,
|
||||
lvresize_pool_metadata_by_size_CMD,
|
||||
lvs_general_CMD,
|
||||
lvscan_general_CMD,
|
||||
pvchange_properties_all_CMD,
|
||||
pvchange_properties_some_CMD,
|
||||
pvresize_general_CMD,
|
||||
pvck_general_CMD,
|
||||
pvcreate_general_CMD,
|
||||
pvdisplay_general_CMD,
|
||||
pvmove_one_CMD,
|
||||
pvmove_any_CMD,
|
||||
pvremove_general_CMD,
|
||||
pvs_general_CMD,
|
||||
pvscan_show_CMD,
|
||||
pvscan_cache_CMD,
|
||||
vgcfgbackup_general_CMD,
|
||||
vgcfgrestore_by_vg_CMD,
|
||||
vgcfgrestore_by_file_CMD,
|
||||
vgchange_properties_CMD,
|
||||
vgchange_monitor_CMD,
|
||||
vgchange_poll_CMD,
|
||||
vgchange_activate_CMD,
|
||||
vgchange_refresh_CMD,
|
||||
vgchange_lockstart_CMD,
|
||||
vgchange_lockstop_CMD,
|
||||
vgck_general_CMD,
|
||||
vgconvert_general_CMD,
|
||||
vgcreate_general_CMD,
|
||||
vgdisplay_general_CMD,
|
||||
vgexport_some_CMD,
|
||||
vgexport_all_CMD,
|
||||
vgextend_general_CMD,
|
||||
vgimport_some_CMD,
|
||||
vgimport_all_CMD,
|
||||
vgimportclone_general_CMD,
|
||||
vgmerge_general_CMD,
|
||||
vgmknodes_general_CMD,
|
||||
vgreduce_by_pv_CMD,
|
||||
vgreduce_all_CMD,
|
||||
vgreduce_missing_CMD,
|
||||
vgremove_general_CMD,
|
||||
vgrename_by_name_CMD,
|
||||
vgrename_by_uuid_CMD,
|
||||
vgs_general_CMD,
|
||||
vgscan_general_CMD,
|
||||
vgsplit_by_pv_to_existing_CMD,
|
||||
vgsplit_by_lv_to_existing_CMD,
|
||||
vgsplit_by_pv_to_new_CMD,
|
||||
vgsplit_by_lv_to_new_CMD,
|
||||
devtypes_general_CMD,
|
||||
fullreport_general_CMD,
|
||||
lastlog_general_CMD,
|
||||
lvpoll_general_CMD,
|
||||
formats_general_CMD,
|
||||
help_general_CMD,
|
||||
version_general_CMD,
|
||||
pvdata_general_CMD,
|
||||
segtypes_general_CMD,
|
||||
systemid_general_CMD,
|
||||
tags_general_CMD,
|
||||
lvmchange_general_CMD,
|
||||
lvmdiskscan_general_CMD,
|
||||
lvmsadc_general_CMD,
|
||||
lvmsar_general_CMD,
|
||||
COMMAND_ID_COUNT,
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -51,8 +51,8 @@ struct command_name {
|
||||
*/
|
||||
|
||||
/* arg_def flags */
|
||||
#define ARG_DEF_FLAG_NEW 1 << 0
|
||||
#define ARG_DEF_FLAG_MAY_REPEAT 1 << 1
|
||||
#define ARG_DEF_FLAG_NEW 1 << 0
|
||||
#define ARG_DEF_FLAG_MAY_REPEAT 1 << 1
|
||||
|
||||
/* arg_def lv_types */
|
||||
enum {
|
||||
@@ -123,7 +123,8 @@ struct pos_arg {
|
||||
* one or more from required_opt_args is required,
|
||||
* then the rest are optional.
|
||||
*/
|
||||
#define CMD_FLAG_ONE_REQUIRED_OPT 1
|
||||
#define CMD_FLAG_ONE_REQUIRED_OPT 1
|
||||
#define CMD_FLAG_SECONDARY_SYNTAX 2
|
||||
|
||||
/* a register of the lvm commands */
|
||||
struct command {
|
||||
|
@@ -47,6 +47,8 @@ int segtype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
|
||||
int alloc_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
|
||||
int locktype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
|
||||
int readahead_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
|
||||
int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
|
||||
int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
|
||||
int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
|
||||
|
||||
/* also see arg_props */
|
||||
@@ -108,6 +110,8 @@ static struct opt_name opt_names[ARG_COUNT + 1] = {
|
||||
struct cmd_name {
|
||||
const char *name;
|
||||
const char *desc;
|
||||
int variants;
|
||||
int common_options[ARG_COUNT + 1];
|
||||
};
|
||||
|
||||
/* create table of command names, e.g. vgcreate */
|
||||
@@ -133,7 +137,7 @@ struct oo_line {
|
||||
int cmd_count;
|
||||
struct command cmd_array[MAX_CMDS];
|
||||
|
||||
struct command common_options; /* for printing common usage */
|
||||
struct command lvm_all; /* for printing common options for all lvm commands */
|
||||
|
||||
#define MAX_OO_LINES 256
|
||||
int oo_line_count;
|
||||
@@ -499,6 +503,19 @@ static const char *cmd_name_desc(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct cmd_name *find_command_name(const char *str)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CMD_NAMES; i++) {
|
||||
if (!cmd_names[i].name)
|
||||
break;
|
||||
if (!strcmp(cmd_names[i].name, str))
|
||||
return &cmd_names[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int is_opt_name(char *str)
|
||||
{
|
||||
if (!strncmp(str, "--", 2))
|
||||
@@ -562,6 +579,13 @@ static int is_desc_line(char *str)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_flags_line(char *str)
|
||||
{
|
||||
if (!strncmp(str, "FLAGS:", 6))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_id_line(char *str)
|
||||
{
|
||||
if (!strncmp(str, "ID:", 3))
|
||||
@@ -977,7 +1001,7 @@ static void print_def(struct arg_def *def, int usage)
|
||||
printf("%s", def->str);
|
||||
|
||||
else if (val_enum == constnum_VAL)
|
||||
printf("ll%u", (unsigned long long)def->num);
|
||||
printf("%llu", (unsigned long long)def->num);
|
||||
|
||||
else {
|
||||
if (sep) printf("|");
|
||||
@@ -1132,14 +1156,46 @@ static char *flags_to_str(int flags)
|
||||
|
||||
memset(buf_flags, 0, sizeof(buf_flags));
|
||||
|
||||
if (flags & ARG_DEF_FLAG_MAY_REPEAT)
|
||||
if (flags & ARG_DEF_FLAG_MAY_REPEAT) {
|
||||
if (buf_flags[0])
|
||||
strcat(buf_flags, " | ");
|
||||
strcat(buf_flags, "ARG_DEF_FLAG_MAY_REPEAT");
|
||||
if (flags & ARG_DEF_FLAG_NEW)
|
||||
}
|
||||
if (flags & ARG_DEF_FLAG_NEW) {
|
||||
if (buf_flags[0])
|
||||
strcat(buf_flags, " | ");
|
||||
strcat(buf_flags, "ARG_DEF_FLAG_NEW");
|
||||
}
|
||||
|
||||
return buf_flags;
|
||||
}
|
||||
|
||||
static void add_flags(struct command *cmd, char *line)
|
||||
{
|
||||
if (strstr(line, "SECONDARY_SYNTAX"))
|
||||
cmd->cmd_flags |= CMD_FLAG_SECONDARY_SYNTAX;
|
||||
}
|
||||
|
||||
static char *cmd_flags_to_str(uint32_t flags)
|
||||
{
|
||||
static char buf_cmd_flags[32];
|
||||
|
||||
memset(buf_cmd_flags, 0, sizeof(buf_cmd_flags));
|
||||
|
||||
if (flags & CMD_FLAG_SECONDARY_SYNTAX) {
|
||||
if (buf_cmd_flags[0])
|
||||
strcat(buf_cmd_flags, " | ");
|
||||
strcat(buf_cmd_flags, "CMD_FLAG_SECONDARY_SYNTAX");
|
||||
}
|
||||
if (flags & CMD_FLAG_ONE_REQUIRED_OPT) {
|
||||
if (buf_cmd_flags[0])
|
||||
strcat(buf_cmd_flags, " | ");
|
||||
strcat(buf_cmd_flags, "CMD_FLAG_ONE_REQUIRED_OPT");
|
||||
}
|
||||
|
||||
return buf_cmd_flags;
|
||||
}
|
||||
|
||||
void print_command_count(void)
|
||||
{
|
||||
struct command *cmd;
|
||||
@@ -1173,35 +1229,156 @@ void print_command_count(void)
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
static int is_common_opt(int opt)
|
||||
static int is_lvm_all_opt(int opt)
|
||||
{
|
||||
int oo;
|
||||
|
||||
for (oo = 0; oo < common_options.oo_count; oo++) {
|
||||
if (common_options.optional_opt_args[oo].opt == opt)
|
||||
for (oo = 0; oo < lvm_all.oo_count; oo++) {
|
||||
if (lvm_all.optional_opt_args[oo].opt == opt)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For certain commands (esp commands like lvcreate with many variants), common
|
||||
* options should not be printed for every variation, but once for all. The
|
||||
* list of commands this applies to is fixed for now but could be encoded in
|
||||
* command-lines.in.
|
||||
*
|
||||
* The common options are defined in OO_USAGE_COMMON. Those options
|
||||
* are skipped when creating the usage strings for each variation of
|
||||
* these commands. Instead they are set in the usage_common string.
|
||||
*/
|
||||
|
||||
void print_usage(struct command *cmd, int skip_required)
|
||||
static void factor_common_options(void)
|
||||
{
|
||||
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
|
||||
int i, sep, ro, rp, oo, op;
|
||||
int cn, opt_enum, ci, oo, found;
|
||||
struct command *cmd;
|
||||
|
||||
if (skip_required)
|
||||
goto oo_count;
|
||||
for (cn = 0; cn < MAX_CMD_NAMES; cn++) {
|
||||
if (!cmd_names[cn].name)
|
||||
break;
|
||||
|
||||
for (ci = 0; ci < cmd_count; ci++) {
|
||||
cmd = &cmd_array[ci];
|
||||
|
||||
if (strcmp(cmd->name, cmd_names[cn].name))
|
||||
continue;
|
||||
|
||||
cmd_names[cn].variants++;
|
||||
}
|
||||
|
||||
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
|
||||
|
||||
for (ci = 0; ci < cmd_count; ci++) {
|
||||
cmd = &cmd_array[ci];
|
||||
|
||||
if (strcmp(cmd->name, cmd_names[cn].name))
|
||||
continue;
|
||||
|
||||
found = 0;
|
||||
|
||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||
if (cmd->optional_opt_args[oo].opt == opt_enum) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
goto next_opt;
|
||||
}
|
||||
|
||||
/* all commands starting with this name use this option */
|
||||
cmd_names[cn].common_options[opt_enum] = 1;
|
||||
next_opt:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (cn = 0; cn < MAX_CMD_NAMES; cn++) {
|
||||
if (!cmd_names[cn].name)
|
||||
break;
|
||||
|
||||
printf("%s (%d)\n", cmd_names[cn].name, cmd_names[cn].variants);
|
||||
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
|
||||
if (cmd_names[cn].common_options[opt_enum])
|
||||
printf(" %s\n", opt_names[opt_enum].long_opt);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void print_usage_common(struct command *cmd)
|
||||
{
|
||||
struct cmd_name *cname;
|
||||
int i, sep, ro, rp, oo, op, opt_enum;
|
||||
|
||||
if (!(cname = find_command_name(cmd->name)))
|
||||
return;
|
||||
|
||||
sep = 0;
|
||||
|
||||
/*
|
||||
* when there's more than one variant, options that
|
||||
* are common to all commands with a common name.
|
||||
*/
|
||||
|
||||
if (cname->variants < 2)
|
||||
goto all;
|
||||
|
||||
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
|
||||
if (!cname->common_options[opt_enum])
|
||||
continue;
|
||||
|
||||
if (is_lvm_all_opt(opt_enum))
|
||||
continue;
|
||||
|
||||
if (!sep) {
|
||||
printf("\n");
|
||||
printf("\" [");
|
||||
} else {
|
||||
printf(",");
|
||||
}
|
||||
|
||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
||||
continue;
|
||||
|
||||
printf(" %s", opt_names[opt_enum].long_opt);
|
||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
print_def(&cmd->optional_opt_args[oo].def, 1);
|
||||
}
|
||||
sep = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
all:
|
||||
/* options that are common to all lvm commands */
|
||||
|
||||
for (oo = 0; oo < lvm_all.oo_count; oo++) {
|
||||
opt_enum = lvm_all.optional_opt_args[oo].opt;
|
||||
|
||||
if (!sep) {
|
||||
printf("\n");
|
||||
printf("\" [");
|
||||
} else {
|
||||
printf(",");
|
||||
}
|
||||
|
||||
printf(" %s", opt_names[opt_enum].long_opt);
|
||||
if (lvm_all.optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
print_def(&lvm_all.optional_opt_args[oo].def, 1);
|
||||
}
|
||||
sep = 1;
|
||||
}
|
||||
|
||||
printf(" ]\"");
|
||||
printf(";\n");
|
||||
}
|
||||
|
||||
void print_usage(struct command *cmd)
|
||||
{
|
||||
struct cmd_name *cname;
|
||||
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
|
||||
int i, sep, ro, rp, oo, op, opt_enum;
|
||||
|
||||
if (!(cname = find_command_name(cmd->name)))
|
||||
return;
|
||||
|
||||
printf("\"%s", cmd->name);
|
||||
|
||||
@@ -1240,30 +1417,40 @@ void print_usage(struct command *cmd, int skip_required)
|
||||
sep = 0;
|
||||
|
||||
if (cmd->oo_count) {
|
||||
printf("\n");
|
||||
printf("\" [");
|
||||
|
||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||
/* skip common opts which are in the usage_common string */
|
||||
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
|
||||
opt_enum = cmd->optional_opt_args[oo].opt;
|
||||
|
||||
/*
|
||||
* Skip common opts which are in the usage_common string.
|
||||
* The common opts are those in lvm_all and in
|
||||
* cname->common_options.
|
||||
*/
|
||||
|
||||
if (is_lvm_all_opt(opt_enum))
|
||||
continue;
|
||||
|
||||
if (!sep) {
|
||||
printf("\n");
|
||||
printf("\" [");
|
||||
}
|
||||
if ((cname->variants > 1) && cname->common_options[opt_enum])
|
||||
continue;
|
||||
|
||||
if (sep)
|
||||
printf(",");
|
||||
|
||||
printf(" %s", opt_names[cmd->optional_opt_args[oo].opt].long_opt);
|
||||
printf(" %s", opt_names[opt_enum].long_opt);
|
||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
print_def(&cmd->optional_opt_args[oo].def, 1);
|
||||
}
|
||||
sep = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep)
|
||||
if (sep)
|
||||
printf(",");
|
||||
printf(" COMMON_OPTIONS");
|
||||
printf(" ]\"");
|
||||
}
|
||||
|
||||
op_count:
|
||||
if (!cmd->op_count)
|
||||
@@ -1352,7 +1539,7 @@ static void print_def_man(struct arg_def *def, int usage)
|
||||
|
||||
else if (val_enum == constnum_VAL) {
|
||||
printf("\\fB");
|
||||
printf("ll%u", (unsigned long long)def->num);
|
||||
printf("%llu", (unsigned long long)def->num);
|
||||
printf("\\fP");
|
||||
}
|
||||
|
||||
@@ -1393,13 +1580,14 @@ static void print_def_man(struct arg_def *def, int usage)
|
||||
printf(" ...");
|
||||
}
|
||||
|
||||
void print_cmd_man(struct command *cmd, int skip_required)
|
||||
void print_man_usage(struct command *cmd)
|
||||
{
|
||||
struct cmd_name *cname;
|
||||
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
|
||||
int i, sep, ro, rp, oo, op;
|
||||
int i, sep, ro, rp, oo, op, opt_enum;
|
||||
|
||||
if (skip_required)
|
||||
goto oo_count;
|
||||
if (!(cname = find_command_name(cmd->name)))
|
||||
return;
|
||||
|
||||
printf("\\fB%s\\fP", cmd->name);
|
||||
|
||||
@@ -1424,6 +1612,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
|
||||
sep = 0;
|
||||
|
||||
/* print required options with a short opt */
|
||||
for (ro = 0; ro < cmd->ro_count; ro++) {
|
||||
if (!opt_names[cmd->required_opt_args[ro].opt].short_opt)
|
||||
continue;
|
||||
@@ -1451,6 +1640,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
sep = 1;
|
||||
}
|
||||
|
||||
/* print required options without a short opt */
|
||||
for (ro = 0; ro < cmd->ro_count; ro++) {
|
||||
if (opt_names[cmd->required_opt_args[ro].opt].short_opt)
|
||||
continue;
|
||||
@@ -1476,6 +1666,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
printf(".RE\n");
|
||||
}
|
||||
|
||||
/* print required positional args on a new line after the onereq set */
|
||||
if (cmd->rp_count) {
|
||||
printf(".RS 4\n");
|
||||
for (rp = 0; rp < cmd->rp_count; rp++) {
|
||||
@@ -1498,7 +1689,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
|
||||
/*
|
||||
* all are required options, print as:
|
||||
* -a|--a, -b|--b
|
||||
* -a|--aaa <val> -b|--bbb <val>
|
||||
*/
|
||||
|
||||
if (cmd->ro_count) {
|
||||
@@ -1518,6 +1709,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
}
|
||||
}
|
||||
|
||||
/* print required positional args on the same line as the required options */
|
||||
if (cmd->rp_count) {
|
||||
for (rp = 0; rp < cmd->rp_count; rp++) {
|
||||
if (cmd->required_pos_args[rp].def.val_bits) {
|
||||
@@ -1539,22 +1731,29 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
|
||||
sep = 0;
|
||||
|
||||
printf(".br\n");
|
||||
|
||||
if (cmd->oo_count) {
|
||||
printf(".RS 4\n");
|
||||
printf("[");
|
||||
|
||||
/* print optional options with short opts */
|
||||
|
||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||
/* skip common opts which are in the usage_common string */
|
||||
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
|
||||
opt_enum = cmd->optional_opt_args[oo].opt;
|
||||
|
||||
if (!opt_names[opt_enum].short_opt)
|
||||
continue;
|
||||
|
||||
if (!opt_names[cmd->optional_opt_args[oo].opt].short_opt)
|
||||
/*
|
||||
* Skip common opts which are in the usage_common string.
|
||||
* The common opts are those in lvm_all and in
|
||||
* cname->common_options.
|
||||
*/
|
||||
|
||||
if (is_lvm_all_opt(opt_enum))
|
||||
continue;
|
||||
|
||||
if (!sep) {
|
||||
printf(".RS 4\n");
|
||||
printf("[");
|
||||
}
|
||||
if ((cname->variants > 1) && cname->common_options[opt_enum])
|
||||
continue;
|
||||
|
||||
if (sep) {
|
||||
printf(",");
|
||||
@@ -1563,8 +1762,8 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
}
|
||||
|
||||
printf(" \\fB-%c\\fP|\\fB%s\\fP",
|
||||
opt_names[cmd->optional_opt_args[oo].opt].short_opt,
|
||||
opt_names[cmd->optional_opt_args[oo].opt].long_opt);
|
||||
opt_names[opt_enum].short_opt,
|
||||
opt_names[opt_enum].long_opt);
|
||||
|
||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
@@ -1573,18 +1772,25 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
sep = 1;
|
||||
}
|
||||
|
||||
/* print optional options without short opts */
|
||||
|
||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||
/* skip common opts which are in the usage_common string */
|
||||
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
|
||||
opt_enum = cmd->optional_opt_args[oo].opt;
|
||||
|
||||
if (opt_names[opt_enum].short_opt)
|
||||
continue;
|
||||
|
||||
if (opt_names[cmd->optional_opt_args[oo].opt].short_opt)
|
||||
/*
|
||||
* Skip common opts which are in the usage_common string.
|
||||
* The common opts are those in lvm_all and in
|
||||
* cname->common_options.
|
||||
*/
|
||||
|
||||
if (is_lvm_all_opt(opt_enum))
|
||||
continue;
|
||||
|
||||
if (!sep) {
|
||||
printf(".RS 4\n");
|
||||
printf("[");
|
||||
}
|
||||
if ((cname->variants > 1) && cname->common_options[opt_enum])
|
||||
continue;
|
||||
|
||||
if (sep) {
|
||||
printf(",");
|
||||
@@ -1595,7 +1801,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
/* space alignment without short opt */
|
||||
printf(" ");
|
||||
|
||||
printf(" \\fB%s\\fP", opt_names[cmd->optional_opt_args[oo].opt].long_opt);
|
||||
printf(" \\fB%s\\fP", opt_names[opt_enum].long_opt);
|
||||
|
||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
@@ -1603,9 +1809,15 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
}
|
||||
sep = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sep) {
|
||||
if (sep) {
|
||||
printf(",");
|
||||
printf("\n.br\n");
|
||||
printf(" ");
|
||||
/* space alignment without short opt */
|
||||
printf(" ");
|
||||
}
|
||||
printf(" COMMON_OPTIONS");
|
||||
printf(" ]\n");
|
||||
printf(".RE\n");
|
||||
printf(".br\n");
|
||||
@@ -1634,6 +1846,151 @@ void print_cmd_man(struct command *cmd, int skip_required)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void print_man_usage_common(struct command *cmd)
|
||||
{
|
||||
struct cmd_name *cname;
|
||||
int i, sep, ro, rp, oo, op, opt_enum;
|
||||
|
||||
if (!(cname = find_command_name(cmd->name)))
|
||||
return;
|
||||
|
||||
sep = 0;
|
||||
|
||||
printf(".RS 4\n");
|
||||
printf("[");
|
||||
|
||||
/*
|
||||
* when there's more than one variant, options that
|
||||
* are common to all commands with a common name.
|
||||
*/
|
||||
|
||||
if (cname->variants < 2)
|
||||
goto all;
|
||||
|
||||
/* print those with short opts */
|
||||
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
|
||||
if (!cname->common_options[opt_enum])
|
||||
continue;
|
||||
|
||||
if (!opt_names[opt_enum].short_opt)
|
||||
continue;
|
||||
|
||||
if (is_lvm_all_opt(opt_enum))
|
||||
continue;
|
||||
|
||||
if (sep) {
|
||||
printf(",");
|
||||
printf("\n.br\n");
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
||||
continue;
|
||||
|
||||
printf(" \\fB-%c\\fP|\\fB%s\\fP",
|
||||
opt_names[opt_enum].short_opt,
|
||||
opt_names[opt_enum].long_opt);
|
||||
|
||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
||||
}
|
||||
sep = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* print those without short opts */
|
||||
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
|
||||
if (!cname->common_options[opt_enum])
|
||||
continue;
|
||||
|
||||
if (opt_names[opt_enum].short_opt)
|
||||
continue;
|
||||
|
||||
if (is_lvm_all_opt(opt_enum))
|
||||
continue;
|
||||
|
||||
if (sep) {
|
||||
printf(",");
|
||||
printf("\n.br\n");
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
for (oo = 0; oo < cmd->oo_count; oo++) {
|
||||
if (cmd->optional_opt_args[oo].opt != opt_enum)
|
||||
continue;
|
||||
|
||||
/* space alignment without short opt */
|
||||
printf(" ");
|
||||
|
||||
printf(" \\fB%s\\fP", opt_names[opt_enum].long_opt);
|
||||
|
||||
if (cmd->optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
print_def_man(&cmd->optional_opt_args[oo].def, 1);
|
||||
}
|
||||
sep = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
all:
|
||||
/* options that are common to all lvm commands */
|
||||
|
||||
/* those with short opts */
|
||||
for (oo = 0; oo < lvm_all.oo_count; oo++) {
|
||||
opt_enum = lvm_all.optional_opt_args[oo].opt;
|
||||
|
||||
if (!opt_names[opt_enum].short_opt)
|
||||
continue;
|
||||
|
||||
if (sep) {
|
||||
printf(",");
|
||||
printf("\n.br\n");
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf(" \\fB-%c\\fP|\\fB%s\\fP",
|
||||
opt_names[opt_enum].short_opt,
|
||||
opt_names[opt_enum].long_opt);
|
||||
|
||||
if (lvm_all.optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
print_def(&lvm_all.optional_opt_args[oo].def, 1);
|
||||
}
|
||||
sep = 1;
|
||||
}
|
||||
|
||||
/* those without short opts */
|
||||
for (oo = 0; oo < lvm_all.oo_count; oo++) {
|
||||
opt_enum = lvm_all.optional_opt_args[oo].opt;
|
||||
|
||||
if (opt_names[opt_enum].short_opt)
|
||||
continue;
|
||||
|
||||
if (sep) {
|
||||
printf(",");
|
||||
printf("\n.br\n");
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
/* space alignment without short opt */
|
||||
printf(" ");
|
||||
|
||||
printf(" \\fB%s\\fP", opt_names[opt_enum].long_opt);
|
||||
|
||||
if (lvm_all.optional_opt_args[oo].def.val_bits) {
|
||||
printf(" ");
|
||||
print_def(&lvm_all.optional_opt_args[oo].def, 1);
|
||||
}
|
||||
sep = 1;
|
||||
}
|
||||
printf(" ]\"");
|
||||
printf(";\n");
|
||||
}
|
||||
|
||||
#define DESC_LINE 256
|
||||
|
||||
void print_desc_man(const char *desc)
|
||||
@@ -1674,16 +2031,16 @@ void print_desc_man(const char *desc)
|
||||
}
|
||||
}
|
||||
|
||||
void print_command_man(void)
|
||||
void print_man_command(void)
|
||||
{
|
||||
struct command *cmd;
|
||||
const char *last_cmd_name = NULL;
|
||||
const char *desc;
|
||||
int i, j, ro, rp, oo, op;
|
||||
|
||||
include_optional_opt_args(&common_options, "OO_USAGE_COMMON");
|
||||
include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
|
||||
|
||||
printf(".TH LVM_ALL 8\n");
|
||||
printf(".TH LVM_COMMANDS 8\n");
|
||||
|
||||
for (i = 0; i < cmd_count; i++) {
|
||||
|
||||
@@ -1711,12 +2068,12 @@ void print_command_man(void)
|
||||
printf(".P\n");
|
||||
}
|
||||
|
||||
print_cmd_man(cmd, 0);
|
||||
print_man_usage(cmd);
|
||||
|
||||
if ((i == (cmd_count - 1)) || strcmp(cmd->name, cmd_array[i+1].name)) {
|
||||
printf("Common options:\n");
|
||||
printf(".\n");
|
||||
print_cmd_man(&common_options, 1);
|
||||
print_man_usage_common(cmd);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
@@ -1729,7 +2086,7 @@ void print_command_struct(int only_usage)
|
||||
struct command *cmd;
|
||||
int i, j, ro, rp, oo, op;
|
||||
|
||||
include_optional_opt_args(&common_options, "OO_USAGE_COMMON");
|
||||
include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
|
||||
|
||||
printf("/* Do not edit. This file is generated by scripts/create-commands */\n");
|
||||
printf("/* using command definitions from scripts/command-lines.in */\n");
|
||||
@@ -1739,8 +2096,8 @@ void print_command_struct(int only_usage)
|
||||
cmd = &cmd_array[i];
|
||||
|
||||
if (only_usage) {
|
||||
print_usage(cmd, 0);
|
||||
print_usage(&common_options, 1);
|
||||
print_usage(cmd);
|
||||
print_usage_common(cmd);
|
||||
printf("\n");
|
||||
continue;
|
||||
}
|
||||
@@ -1754,16 +2111,18 @@ void print_command_struct(int only_usage)
|
||||
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);
|
||||
if (cmd->cmd_flags)
|
||||
printf("commands[%d].cmd_flags = %s;\n", i, cmd_flags_to_str(cmd->cmd_flags));
|
||||
else
|
||||
printf("commands[%d].cmd_flags = 0;\n", i, cmd_flags_to_str(cmd->cmd_flags));
|
||||
|
||||
printf("commands[%d].desc = \"%s\";\n", i, cmd->desc ?: "");
|
||||
printf("commands[%d].usage = ", i);
|
||||
print_usage(cmd, 0);
|
||||
print_usage(cmd);
|
||||
|
||||
if (cmd->oo_count) {
|
||||
printf("commands[%d].usage_common = ", i);
|
||||
print_usage(&common_options, 1);
|
||||
print_usage_common(cmd);
|
||||
} else {
|
||||
printf("commands[%d].usage_common = \"NULL\";\n", i);
|
||||
}
|
||||
@@ -1911,12 +2270,8 @@ static void print_ambiguous(void)
|
||||
continue;
|
||||
if (cmd->ro_count != dup->ro_count)
|
||||
continue;
|
||||
if (cmd->oo_count != dup->oo_count)
|
||||
continue;
|
||||
if (cmd->rp_count != dup->rp_count)
|
||||
continue;
|
||||
if (cmd->op_count != dup->op_count)
|
||||
continue;
|
||||
|
||||
for (ro = 0; ro < cmd->ro_count; ro++) {
|
||||
if (!opt_arg_matches(&cmd->required_opt_args[ro],
|
||||
@@ -1936,8 +2291,8 @@ static void print_ambiguous(void)
|
||||
}
|
||||
|
||||
printf("Ambiguous commands %d and %d:\n", i, j);
|
||||
print_usage(cmd, 0);
|
||||
print_usage(dup, 0);
|
||||
print_usage(cmd);
|
||||
print_usage(dup);
|
||||
printf("\n");
|
||||
|
||||
dups[found].i = i;
|
||||
@@ -1977,11 +2332,11 @@ static void print_help(int argc, char *argv[])
|
||||
{
|
||||
printf("%s --output struct|count|usage|expanded <filename>\n", argv[0]);
|
||||
printf("\n");
|
||||
printf("struct: print C structures.\n");
|
||||
printf("struct: print C structures for command-lines.h\n");
|
||||
printf("count: print defines and enums for command-lines-count.h\n");
|
||||
printf("ambiguous: print commands differing only by LV types\n");
|
||||
printf("usage: print usage format.\n");
|
||||
printf("expanded: print expanded input format.\n");
|
||||
printf("count: print #define COMMAND_COUNT <Number>\n");
|
||||
printf("ambiguous: print commands differing only by LV types\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -2086,15 +2441,22 @@ int main(int argc, char *argv[])
|
||||
if (is_desc_line(line_argv[0])) {
|
||||
char *desc = strdup(line_orig);
|
||||
if (cmd->desc) {
|
||||
cmd->desc = realloc((char *)cmd->desc, strlen(cmd->desc) + strlen(desc) + 2);
|
||||
strcat((char *)cmd->desc, " ");
|
||||
strcat((char *)cmd->desc, desc);
|
||||
int newlen = strlen(cmd->desc) + strlen(desc) + 2;
|
||||
char *newdesc = malloc(newlen);
|
||||
memset(newdesc, 0, newlen);
|
||||
snprintf(newdesc, newlen, "%s %s", cmd->desc, desc);
|
||||
cmd->desc = newdesc;
|
||||
free(desc);
|
||||
} else
|
||||
cmd->desc = desc;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_flags_line(line_argv[0])) {
|
||||
add_flags(cmd, line_orig);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_id_line(line_argv[0])) {
|
||||
cmd->command_line_id = strdup(line_argv[1]);
|
||||
continue;
|
||||
@@ -2147,10 +2509,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
fclose(file);
|
||||
|
||||
factor_common_options();
|
||||
|
||||
if (!outputformat)
|
||||
print_command_struct(1);
|
||||
else if (!strcmp(outputformat, "struct"))
|
||||
else if (!strcmp(outputformat, "struct")) {
|
||||
print_command_struct(0);
|
||||
print_ambiguous();
|
||||
}
|
||||
else if (!strcmp(outputformat, "count"))
|
||||
print_command_count();
|
||||
else if (!strcmp(outputformat, "usage"))
|
||||
@@ -2160,8 +2526,10 @@ int main(int argc, char *argv[])
|
||||
else if (!strcmp(outputformat, "ambiguous"))
|
||||
print_ambiguous();
|
||||
else if (!strcmp(outputformat, "man"))
|
||||
print_command_man();
|
||||
print_man_command();
|
||||
else
|
||||
print_help(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -30,12 +30,12 @@ void *cmdlib_lvm2_init(unsigned static_compile)
|
||||
{
|
||||
struct cmd_context *cmd;
|
||||
|
||||
lvm_register_commands();
|
||||
|
||||
init_is_static(static_compile);
|
||||
if (!(cmd = init_lvm(1, 1)))
|
||||
return NULL;
|
||||
|
||||
lvm_register_commands();
|
||||
|
||||
return (void *) cmd;
|
||||
}
|
||||
|
||||
|
@@ -733,23 +733,134 @@ int readahead_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_va
|
||||
/*
|
||||
* Non-zero, positive integer, "all", or "unmanaged"
|
||||
*/
|
||||
int metadatacopies_arg(struct cmd_context *cmd, struct arg_values *av)
|
||||
int vgmetadatacopies_arg(struct cmd_context *cmd, struct arg_values *av)
|
||||
{
|
||||
if (!strncmp(cmd->name, "vg", 2)) {
|
||||
if (!strcasecmp(av->value, "all")) {
|
||||
av->ui_value = VGMETADATACOPIES_ALL;
|
||||
return 1;
|
||||
}
|
||||
if (!strcasecmp(av->value, "all")) {
|
||||
av->ui_value = VGMETADATACOPIES_ALL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcasecmp(av->value, "unmanaged")) {
|
||||
av->ui_value = VGMETADATACOPIES_UNMANAGED;
|
||||
return 1;
|
||||
}
|
||||
if (!strcasecmp(av->value, "unmanaged")) {
|
||||
av->ui_value = VGMETADATACOPIES_UNMANAGED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return int_arg(cmd, av);
|
||||
}
|
||||
|
||||
int pvmetadatacopies_arg(struct cmd_context *cmd, struct arg_values *av)
|
||||
{
|
||||
int num;
|
||||
|
||||
if (!int_arg(cmd, av))
|
||||
return 0;
|
||||
|
||||
num = av->i_value;
|
||||
|
||||
if ((num != 0) && (num != 1) && (num != 2))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int metadatacopies_arg(struct cmd_context *cmd, struct arg_values *av)
|
||||
{
|
||||
if (!strncmp(cmd->name, "pv", 2))
|
||||
return pvmetadatacopies_arg(cmd, av);
|
||||
if (!strncmp(cmd->name, "vg", 2))
|
||||
return vgmetadatacopies_arg(cmd, av);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: there's been a confusing mixup among:
|
||||
* resizeable, resizable, allocatable, allocation.
|
||||
*
|
||||
* resizeable and allocatable are the preferred,
|
||||
* standard option names.
|
||||
*
|
||||
* The dispreferred "resizable" is always translated
|
||||
* to the preferred resizeable.
|
||||
*
|
||||
* But, the dispreferred "allocation" name seems
|
||||
* to translate to either or both resizeable
|
||||
* and allocatable, it's not clear which.
|
||||
*/
|
||||
|
||||
static int _opt_standard_to_synonym(const char *cmd_name, int opt)
|
||||
{
|
||||
switch (opt) {
|
||||
case mirrorlog_ARG:
|
||||
return corelog_ARG;
|
||||
case resizeable_ARG:
|
||||
return resizable_ARG;
|
||||
case allocatable_ARG:
|
||||
return allocation_ARG;
|
||||
case activate_ARG:
|
||||
return available_ARG;
|
||||
case rebuild_ARG:
|
||||
return raidrebuild_ARG;
|
||||
case syncaction_ARG:
|
||||
return raidsyncaction_ARG;
|
||||
case writemostly_ARG:
|
||||
return raidwritemostly_ARG;
|
||||
case minrecoveryrate_ARG:
|
||||
return raidminrecoveryrate_ARG;
|
||||
case maxrecoveryrate_ARG:
|
||||
return raidmaxrecoveryrate_ARG;
|
||||
case writebehind_ARG:
|
||||
return raidwritebehind_ARG;
|
||||
case virtualsize_ARG:
|
||||
return virtualoriginsize_ARG;
|
||||
case pvmetadatacopies_ARG:
|
||||
if (!strncmp(cmd_name, "pv", 2))
|
||||
return metadatacopies_ARG;
|
||||
return 0;
|
||||
case vgmetadatacopies_ARG:
|
||||
if (!strncmp(cmd_name, "vg", 2))
|
||||
return metadatacopies_ARG;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _opt_synonym_to_standard(const char *cmd_name, int opt)
|
||||
{
|
||||
switch (opt) {
|
||||
case corelog_ARG:
|
||||
return mirrorlog_ARG;
|
||||
case resizable_ARG:
|
||||
return resizeable_ARG;
|
||||
case allocation_ARG:
|
||||
return allocatable_ARG;
|
||||
case available_ARG:
|
||||
return activate_ARG;
|
||||
case raidrebuild_ARG:
|
||||
return rebuild_ARG;
|
||||
case raidsyncaction_ARG:
|
||||
return syncaction_ARG;
|
||||
case raidwritemostly_ARG:
|
||||
return writemostly_ARG;
|
||||
case raidminrecoveryrate_ARG:
|
||||
return minrecoveryrate_ARG;
|
||||
case raidmaxrecoveryrate_ARG:
|
||||
return maxrecoveryrate_ARG;
|
||||
case raidwritebehind_ARG:
|
||||
return writebehind_ARG;
|
||||
case virtualoriginsize_ARG:
|
||||
return virtualsize_ARG;
|
||||
case metadatacopies_ARG:
|
||||
if (!strncmp(cmd_name, "pv", 2))
|
||||
return pvmetadatacopies_ARG;
|
||||
if (!strncmp(cmd_name, "vg", 2))
|
||||
return vgmetadatacopies_ARG;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _add_getopt_arg(int arg_enum, char **optstrp, struct option **longoptsp);
|
||||
|
||||
/*
|
||||
* The valid args for a command name in general is a union of
|
||||
* required_opt_args and optional_opt_args for all commands[]
|
||||
@@ -761,6 +872,7 @@ static void _set_valid_args_for_command_name(int ci)
|
||||
int all_args[ARG_COUNT] = { 0 };
|
||||
int num_args = 0;
|
||||
int opt_enum; /* foo_ARG from args.h */
|
||||
int opt_syn;
|
||||
int i, ro, oo;
|
||||
|
||||
/*
|
||||
@@ -774,6 +886,7 @@ static void _set_valid_args_for_command_name(int ci)
|
||||
for (ro = 0; ro < commands[i].ro_count; ro++) {
|
||||
opt_enum = commands[i].required_opt_args[ro].opt;
|
||||
all_args[opt_enum] = 1;
|
||||
|
||||
}
|
||||
for (oo = 0; oo < commands[i].oo_count; oo++) {
|
||||
opt_enum = commands[i].optional_opt_args[oo].opt;
|
||||
@@ -783,16 +896,36 @@ static void _set_valid_args_for_command_name(int ci)
|
||||
|
||||
for (i = 0; i < ARG_COUNT; i++) {
|
||||
if (all_args[i]) {
|
||||
command_names[ci].valid_args[num_args] = _cmdline.arg_props[i].arg_enum;
|
||||
opt_enum = _cmdline.arg_props[i].arg_enum;
|
||||
|
||||
command_names[ci].valid_args[num_args] = opt_enum;
|
||||
num_args++;
|
||||
|
||||
/* Automatically recognize --extents in addition to --size. */
|
||||
if (_cmdline.arg_props[i].arg_enum == size_ARG) {
|
||||
if (opt_enum == size_ARG) {
|
||||
command_names[ci].valid_args[num_args] = extents_ARG;
|
||||
num_args++;
|
||||
}
|
||||
|
||||
/* Recognize synonyms */
|
||||
if ((opt_syn = _opt_standard_to_synonym(command_names[ci].name, opt_enum))) {
|
||||
command_names[ci].valid_args[num_args] = opt_syn;
|
||||
num_args++;
|
||||
}
|
||||
|
||||
/*
|
||||
* "--allocation" is a weird option that seems to be
|
||||
* a synonym for either allocatable or resizeable,
|
||||
* each which already have their own other synonyms,
|
||||
* so just add allocation whenever either is seen.
|
||||
*/
|
||||
if ((opt_enum == allocatable_ARG) || (opt_enum == resizeable_ARG)) {
|
||||
command_names[ci].valid_args[num_args] = allocation_ARG;
|
||||
num_args++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
command_names[ci].num_args = num_args;
|
||||
}
|
||||
|
||||
@@ -861,49 +994,25 @@ void lvm_register_commands(void)
|
||||
_set_valid_args_for_command_name(i);
|
||||
}
|
||||
|
||||
static int _opt_equivalent_is_set(struct cmd_context *cmd, int opt)
|
||||
/*
|
||||
* Also see merge_synonym(). The command definitions
|
||||
* are written using just one variation of the option
|
||||
* name (opt below). This function checks if the user
|
||||
* entered a synonym (arg_is_set).
|
||||
*/
|
||||
|
||||
static int _opt_synonym_is_set(struct cmd_context *cmd, int opt_std)
|
||||
{
|
||||
if ((opt == mirrorlog_ARG) && arg_is_set(cmd, corelog_ARG))
|
||||
return 1;
|
||||
int opt_syn = _opt_standard_to_synonym(cmd->name, opt_std);
|
||||
|
||||
if ((opt == resizeable_ARG) && arg_is_set(cmd, resizable_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == allocatable_ARG) && arg_is_set(cmd, allocation_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == resizeable_ARG) && arg_is_set(cmd, allocation_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == activate_ARG) && arg_is_set(cmd, available_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == rebuild_ARG) && arg_is_set(cmd, raidrebuild_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == syncaction_ARG) && arg_is_set(cmd, raidsyncaction_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == writemostly_ARG) && arg_is_set(cmd, raidwritemostly_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == minrecoveryrate_ARG) && arg_is_set(cmd, raidminrecoveryrate_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == maxrecoveryrate_ARG) && arg_is_set(cmd, raidmaxrecoveryrate_ARG))
|
||||
return 1;
|
||||
|
||||
if ((opt == writebehind_ARG) && arg_is_set(cmd, raidwritebehind_ARG))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return opt_syn && arg_is_set(cmd, opt_syn);
|
||||
}
|
||||
|
||||
static int _command_required_opt_matches(struct cmd_context *cmd, int ci, int ro)
|
||||
{
|
||||
int opt_enum = commands[ci].required_opt_args[ro].opt;
|
||||
|
||||
if (arg_is_set(cmd, opt_enum))
|
||||
if (arg_is_set(cmd, opt_enum) || _opt_synonym_is_set(cmd, opt_enum))
|
||||
goto check_val;
|
||||
|
||||
/*
|
||||
@@ -918,9 +1027,6 @@ static int _command_required_opt_matches(struct cmd_context *cmd, int ci, int ro
|
||||
goto check_val;
|
||||
}
|
||||
|
||||
if (_opt_equivalent_is_set(cmd, opt_enum))
|
||||
goto check_val;
|
||||
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@@ -952,12 +1058,13 @@ check_val:
|
||||
|
||||
static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp, char **argv)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
/*
|
||||
* rp is the index in required_pos_args[] of the required positional arg.
|
||||
* The pos values begin with 1, so the first positional arg has
|
||||
* pos 1, rp 0.
|
||||
*/
|
||||
|
||||
if (argv[rp]) {
|
||||
/* FIXME: can we match object type better than just checking something exists? */
|
||||
/* Some cases could be validated by looking at defs.types and at the value. */
|
||||
@@ -972,6 +1079,36 @@ static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp
|
||||
arg_is_set(cmd, select_ARG))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* For an lvcreate command with VG as the first required positional arg,
|
||||
* the VG position is allowed to be empty if --name VG/LV is used, or if the
|
||||
* LVM_VG_NAME env var is set.
|
||||
*
|
||||
* --thinpool VG/LV and --cachepool VG/LV can also function like --name
|
||||
* to provide the VG name in place of the positional arg.
|
||||
*/
|
||||
if (!strcmp(cmd->name, "lvcreate") &&
|
||||
(rp == 0) &&
|
||||
val_bit_is_set(commands[ci].required_pos_args[rp].def.val_bits, vg_VAL) &&
|
||||
(arg_is_set(cmd, name_ARG) || arg_is_set(cmd, thinpool_ARG) || arg_is_set(cmd, cachepool_ARG))) {
|
||||
if ((name = arg_str_value(cmd, name_ARG, NULL))) {
|
||||
if (strstr(name, "/") || getenv("LVM_VG_NAME"))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME: does LVM_VG_NAME also work with --thinpool/--cachepool ? */
|
||||
|
||||
if ((name = arg_str_value(cmd, thinpool_ARG, NULL))) {
|
||||
if (strstr(name, "/"))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((name = arg_str_value(cmd, cachepool_ARG, NULL))) {
|
||||
if (strstr(name, "/"))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1136,17 +1273,14 @@ static void _print_description(int ci)
|
||||
int bi = 0;
|
||||
|
||||
for (di = 0; di < strlen(desc); di++) {
|
||||
if (desc[di] == '\0')
|
||||
break;
|
||||
if (desc[di] == '\n')
|
||||
continue;
|
||||
|
||||
if (!strncmp(&desc[di], "DESC:", 5)) {
|
||||
if (bi) {
|
||||
buf[bi] = '\0';
|
||||
log_print("%s", buf);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
bi = 0;
|
||||
}
|
||||
/* skip DESC: */
|
||||
di += 5;
|
||||
continue;
|
||||
}
|
||||
@@ -1160,8 +1294,10 @@ static void _print_description(int ci)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bi)
|
||||
if (bi) {
|
||||
buf[bi] = '\0';
|
||||
log_print("%s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1186,14 +1322,22 @@ static void _print_description(int ci)
|
||||
* cmd->argv[] in that pos can be NULL if arg_is_set(select_ARG)
|
||||
*/
|
||||
|
||||
/* The max number of unused options we keep track of to warn about */
|
||||
#define MAX_UNUSED_COUNT 8
|
||||
|
||||
static struct command *_find_command(struct cmd_context *cmd, const char *path, int *argc, char **argv)
|
||||
{
|
||||
const char *name;
|
||||
int match_count, match_count_ro, match_count_rp, mismatch_count;
|
||||
int best_i = 0, best_count = 0;
|
||||
int closest_i = 0, closest_count_ro = 0;
|
||||
int match_required, match_ro, match_rp, match_type, match_unused, mismatch_required;
|
||||
int best_i = 0, best_required = 0, best_type = 0, best_unused = 0;
|
||||
int close_i = 0, close_ro = 0, close_type;
|
||||
int temp_unused_options[MAX_UNUSED_COUNT];
|
||||
int temp_unused_count;
|
||||
int best_unused_options[MAX_UNUSED_COUNT] = { 0 };
|
||||
int best_unused_count = 0;
|
||||
int ro, rp;
|
||||
int i, j;
|
||||
int opt_enum, opt_i;
|
||||
int accepted, count;
|
||||
|
||||
name = last_path_component(path);
|
||||
@@ -1206,27 +1350,34 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
|
||||
if (arg_is_set(cmd, help_ARG) || arg_is_set(cmd, help2_ARG) || arg_is_set(cmd, version_ARG))
|
||||
return &commands[i];
|
||||
|
||||
match_count = 0; /* total parameters that match */
|
||||
match_count_ro = 0; /* required opt_args that match */
|
||||
match_count_rp = 0; /* required pos_args that match */
|
||||
mismatch_count = 0; /* total parameters that do not match */
|
||||
match_required = 0; /* required parameters that match */
|
||||
match_ro = 0; /* required opt_args that match */
|
||||
match_rp = 0; /* required pos_args that match */
|
||||
match_type = 0; /* type arg matches */
|
||||
match_unused = 0; /* options set that are not accepted by command */
|
||||
mismatch_required = 0; /* required parameters that do not match */
|
||||
temp_unused_count = 0;
|
||||
memset(&temp_unused_options, 0, sizeof(temp_unused_options));
|
||||
|
||||
/* if the command name alone is enough, then that's a match */
|
||||
|
||||
if (!commands[i].ro_count && !commands[i].rp_count)
|
||||
match_count = 1;
|
||||
match_required = 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); */
|
||||
match_count++;
|
||||
match_count_ro++;
|
||||
match_required++;
|
||||
match_ro++;
|
||||
|
||||
if (commands[i].required_opt_args[ro].opt == type_ARG)
|
||||
match_type = 1;
|
||||
} else {
|
||||
/* cmd is missing a required opt arg */
|
||||
/* log_warn("mismatch %d ro opt %d", i, commands[i].required_opt_args[ro].opt); */
|
||||
mismatch_count++;
|
||||
mismatch_required++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1235,12 +1386,12 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
|
||||
* if one required_opt_arg did match.
|
||||
*/
|
||||
if (commands[i].cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) {
|
||||
if (match_count_ro) {
|
||||
if (match_ro) {
|
||||
/* one or more of the required_opt_args is used */
|
||||
mismatch_count = 0;
|
||||
mismatch_required = 0;
|
||||
} else {
|
||||
/* not even one of the required_opt_args is used */
|
||||
mismatch_count = 1;
|
||||
mismatch_required = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1249,134 +1400,139 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
|
||||
for (rp = 0; rp < commands[i].rp_count; rp++) {
|
||||
if (_command_required_pos_matches(cmd, i, rp, argv)) {
|
||||
/* log_warn("match %d rp %d", i, commands[i].required_pos_args[rp].pos); */
|
||||
match_count++;
|
||||
match_count_rp++;
|
||||
match_required++;
|
||||
match_rp++;
|
||||
} else {
|
||||
/* cmd is missing a required pos arg */
|
||||
/* log_warn("mismatch %d rp %d", i, commands[i].required_pos_args[rp].pos); */
|
||||
mismatch_count++;
|
||||
mismatch_required++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if cmd is missing any required opt/pos args, it can't be this command. */
|
||||
|
||||
if (mismatch_count) {
|
||||
if (mismatch_required) {
|
||||
/* save "closest" command that doesn't match */
|
||||
if (match_count_ro && (match_count_ro > closest_count_ro)) {
|
||||
closest_i = i;
|
||||
closest_count_ro = match_count_ro;
|
||||
if ((match_type && !close_type) ||
|
||||
((match_type == close_type) && (match_ro > close_ro))) {
|
||||
close_i = i;
|
||||
close_ro = match_ro;
|
||||
close_type = match_type;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!match_count)
|
||||
if (!match_required)
|
||||
continue;
|
||||
|
||||
/* Count the command name as a match if all the required opt/pos args match. */
|
||||
|
||||
if ((commands[i].ro_count || commands[i].rp_count) &&
|
||||
(match_count_ro || match_count_rp))
|
||||
match_count++;
|
||||
if ((commands[i].ro_count || commands[i].rp_count) && (match_ro || match_rp))
|
||||
match_required++;
|
||||
|
||||
/* log_warn("command %d has match_count %d match_ro %d match_rp %d",
|
||||
i, match_count, match_count_ro, match_count_rp); */
|
||||
/* log_warn("command %d has match_required %d match_ro %d match_rp %d",
|
||||
i, match_required, match_ro, match_rp); */
|
||||
|
||||
/* Count how many options cmd has set that are not accepted by commands[i]. */
|
||||
/* FIXME: also count unused positional args? */
|
||||
|
||||
for (opt_i = 0; opt_i < ARG_COUNT; opt_i++) {
|
||||
if (!arg_is_set(cmd, opt_i))
|
||||
continue;
|
||||
|
||||
if (!(opt_enum = _opt_synonym_to_standard(cmd->name, opt_i)))
|
||||
opt_enum = opt_i;
|
||||
|
||||
/* extents are not used in command definitions */
|
||||
if (opt_enum == extents_ARG)
|
||||
continue;
|
||||
|
||||
accepted = 0;
|
||||
|
||||
/* NB in some cases required_opt_args are optional */
|
||||
for (j = 0; j < commands[i].ro_count; j++) {
|
||||
if (commands[i].required_opt_args[j].opt == opt_enum) {
|
||||
accepted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (accepted)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < commands[i].oo_count; j++) {
|
||||
if (commands[i].optional_opt_args[j].opt == opt_enum) {
|
||||
accepted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!accepted) {
|
||||
match_unused++;
|
||||
if (temp_unused_count < MAX_UNUSED_COUNT)
|
||||
temp_unused_options[temp_unused_count++] = opt_enum;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose the best match, which in general is the command with
|
||||
* the most matching required_{opt,pos}.
|
||||
*
|
||||
* A match is better if:
|
||||
* . more required opt/pos args match
|
||||
* . type arg matches when other doesn't
|
||||
* . those being equal, less unused options
|
||||
*/
|
||||
|
||||
if (!best_count || (match_count > best_count)) {
|
||||
/* log_warn("best %d has match_count %d match_ro %d match_rp %d",
|
||||
i, match_count, match_count_ro, match_count_rp); */
|
||||
if (!best_required || (match_required > best_required) || (match_type > best_type) ||
|
||||
((match_required == best_required) && (match_type == best_type) && (match_unused < best_unused))) {
|
||||
/* log_warn("best %d has match_required %d match_ro %d match_rp %d",
|
||||
i, match_required, match_ro, match_rp); */
|
||||
best_i = i;
|
||||
best_count = match_count;
|
||||
best_required = match_required;
|
||||
best_type = match_type;
|
||||
best_unused = match_unused;
|
||||
best_unused_count = temp_unused_count;
|
||||
memcpy(&best_unused_options, &temp_unused_options, sizeof(best_unused_options));
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_count) {
|
||||
if (!best_required) {
|
||||
/* cmd did not have all the required opt/pos args of any command */
|
||||
log_error("Failed to find a matching command definition.");
|
||||
if (closest_count_ro) {
|
||||
if (close_ro) {
|
||||
log_warn("Closest command usage is:");
|
||||
_print_usage(_cmdline.commands[closest_i].usage, 1);
|
||||
_print_usage(_cmdline.commands[close_i].usage, 1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: should there be a config setting to fail the command if an
|
||||
* unused option or pos arg is set? Or a user prompt to continue or
|
||||
* not without the ignored args? There are ad hoc checks in various
|
||||
* commands to fail sometimes if an unused option or pos arg is set.
|
||||
* Does this mean a per-command flag is needed to determine if that
|
||||
* command ignores or fails with unused args? e.g. "pvscan vg" would
|
||||
* fail based on the vg arg, but now it's just ignored.
|
||||
* If the user passed an option that is not accepted by the matched
|
||||
* command, then fail.
|
||||
*
|
||||
* FIXME: it might be nice to have a config setting that would turn
|
||||
* these into warnings, and just ignore the unused options.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Warn about options that are set but are not used by the command.
|
||||
*/
|
||||
|
||||
for (i = 0; i < ARG_COUNT; i++) {
|
||||
if (!arg_is_set(cmd, i))
|
||||
continue;
|
||||
|
||||
accepted = 0;
|
||||
|
||||
/* NB in some cases required_opt_args are optional */
|
||||
for (j = 0; j < commands[best_i].ro_count; j++) {
|
||||
if (commands[best_i].required_opt_args[j].opt == i) {
|
||||
accepted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (accepted)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < commands[best_i].oo_count; j++) {
|
||||
if (commands[best_i].optional_opt_args[j].opt == i) {
|
||||
accepted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* --type is one option that when set but not accepted by the
|
||||
* command, will not be ignored to make a match. Perhaps there
|
||||
* are others like this, and perhaps this is a property that
|
||||
* should be encoded in args.h?
|
||||
*/
|
||||
if (!accepted && (i == type_ARG)) {
|
||||
log_error("Failed to find a matching command definition with --type.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --extents is a special case which is accepted in place of --size */
|
||||
|
||||
if (!accepted && (i != extents_ARG)) {
|
||||
log_error("Invalid option for the specified command (%s %d): %s.",
|
||||
commands[best_i].command_line_id, best_i, arg_long_option_name(i));
|
||||
return NULL;
|
||||
#if 0
|
||||
log_warn("Ignoring option which is not used by the specified command: %s.",
|
||||
arg_long_option_name(i));
|
||||
/* clear so it can't be used when processing. */
|
||||
cmd->opt_arg_values[i].count = 0;
|
||||
cmd->opt_arg_values[i].value = NULL;
|
||||
#endif
|
||||
if (best_unused_count) {
|
||||
for (i = 0; i < best_unused_count; i++) {
|
||||
log_error("Invalid option for command (%s %d): %s.",
|
||||
commands[best_i].command_line_id, best_i,
|
||||
arg_long_option_name(best_unused_options[i]));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Warn about positional args that are set but are not used by the command.
|
||||
* If the user provided a positional arg that is not accepted by
|
||||
* the mached command, then fail.
|
||||
*
|
||||
* If the last required_pos_arg or the last optional_pos_arg may repeat,
|
||||
* then there won't be unused positional args.
|
||||
*
|
||||
* Otherwise, warn about positional args that exist beyond the number of
|
||||
* required + optional pos_args.
|
||||
* FIXME: same question as above, should there be a config setting
|
||||
* to just warn/ignore about unused positional args?
|
||||
*/
|
||||
|
||||
count = commands[best_i].rp_count;
|
||||
@@ -1392,10 +1548,15 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
|
||||
break;
|
||||
|
||||
if (count >= (commands[best_i].rp_count + commands[best_i].op_count)) {
|
||||
log_warn("Ignoring positional argument which is not used by this command: %s.", argv[count]);
|
||||
/* clear so it can't be used when processing. */
|
||||
log_error("Invalid positional argument for command (%s %d): %s.",
|
||||
commands[best_i].command_line_id, best_i, argv[count]);
|
||||
|
||||
/* FIXME: to warn/ignore, clear so it can't be used when processing. */
|
||||
/*
|
||||
argv[count] = NULL;
|
||||
(*argc)--;
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
out:
|
||||
@@ -1426,6 +1587,9 @@ static int _usage(const char *name, int help_count)
|
||||
if (strcmp(_cmdline.commands[i].name, name))
|
||||
continue;
|
||||
|
||||
if ((_cmdline.commands[i].cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && (help_count < 3))
|
||||
continue;
|
||||
|
||||
if (strlen(_cmdline.commands[i].desc))
|
||||
_print_description(i);
|
||||
|
||||
@@ -1455,11 +1619,18 @@ static int _usage(const char *name, int help_count)
|
||||
log_print(". --size Number can be replaced with --extents NumberExtents.");
|
||||
log_print(". When --name is omitted from lvcreate, a new LV name is");
|
||||
log_print(" generated with the \"lvol\" prefix and a unique numeral suffix.");
|
||||
log_print(". The required VG parameter in lvcreate may be omitted when");
|
||||
log_print(" the VG name is included in another option, e.g. --name VG/LV.");
|
||||
log_print(". For required options listed in parentheses, e.g. (--A, --B),");
|
||||
log_print(" any one is required, after which the others are optional.");
|
||||
log_print(". The _new suffix indicates the VG or LV must not yet exist.");
|
||||
log_print(". LV followed by _<type> indicates that an LV of the given type");
|
||||
log_print(" is required. (raid represents any raid<N> type.)");
|
||||
log_print(". The default output unit is specified by letter, followed by |unit");
|
||||
log_print(" which represents other possible units: hHbBsSkKmMgGtTpPeE.");
|
||||
log_print(". Output units are 1024 SI base, regardless of unit capitalization.");
|
||||
log_print(". Use --help --help --help to print secondary command syntax");
|
||||
log_print(" formats that are recognized, e.g. for compatibility.");
|
||||
log_print(". See man pages for short option equivalents of long option names,");
|
||||
log_print(" and for more detailed descriptions of variable parameters.");
|
||||
}
|
||||
|
@@ -801,10 +801,7 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, metadatacopies_ARG))
|
||||
vp_new->vgmetadatacopies = arg_int_value(cmd, metadatacopies_ARG,
|
||||
DEFAULT_VGMETADATACOPIES);
|
||||
else if (arg_is_set(cmd, vgmetadatacopies_ARG))
|
||||
if (arg_is_set(cmd, vgmetadatacopies_ARG))
|
||||
vp_new->vgmetadatacopies = arg_int_value(cmd, vgmetadatacopies_ARG,
|
||||
DEFAULT_VGMETADATACOPIES);
|
||||
else
|
||||
@@ -2555,10 +2552,14 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
|
||||
* the LV is skipped and doesn't cause the command to fail.
|
||||
*/
|
||||
if (str_list_match_item(&found_arg_lvnames, lv->name)) {
|
||||
log_error("Operation not permitted on LV %s with type %s.", display_lvname(lv), seg->segtype->name);
|
||||
log_error("Operation not permitted (%s %d) on LV %s with type %s.",
|
||||
cmd->command->command_line_id, cmd->command->command_line_enum,
|
||||
display_lvname(lv), seg->segtype->name);
|
||||
ret_max = ECMD_FAILED;
|
||||
} else {
|
||||
log_warn("Operation not permitted on LV %s with type %s.", display_lvname(lv), seg->segtype->name);
|
||||
log_warn("Operation not permitted (%s %d) on LV %s with type %s.",
|
||||
cmd->command->command_line_id, cmd->command->command_line_enum,
|
||||
display_lvname(lv), seg->segtype->name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -4000,11 +4001,6 @@ int pvcreate_params_from_args(struct cmd_context *cmd, struct pvcreate_params *p
|
||||
if (pp->pva.pvmetadatacopies < 0)
|
||||
pp->pva.pvmetadatacopies = find_config_tree_int(cmd, metadata_pvmetadatacopies_CFG, NULL);
|
||||
|
||||
if (pp->pva.pvmetadatacopies > 2) {
|
||||
log_error("Metadatacopies may only be 0, 1 or 2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pp->pva.ba_size = arg_uint64_value(cmd, bootloaderareasize_ARG, pp->pva.ba_size);
|
||||
|
||||
return 1;
|
||||
|
@@ -159,6 +159,8 @@ int segtype_arg(struct cmd_context *cmd, struct arg_values *av);
|
||||
int alloc_arg(struct cmd_context *cmd, struct arg_values *av);
|
||||
int locktype_arg(struct cmd_context *cmd, struct arg_values *av);
|
||||
int readahead_arg(struct cmd_context *cmd, struct arg_values *av);
|
||||
int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
|
||||
int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
|
||||
int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
|
||||
|
||||
/* we use the enums to access the switches */
|
||||
|
11
tools/vals.h
11
tools/vals.h
@@ -116,18 +116,19 @@ val(permission_VAL, permission_arg, "Permission", "rw|r")
|
||||
val(metadatatype_VAL, metadatatype_arg, "MetadataType", "lvm2|lvm1")
|
||||
val(units_VAL, string_arg, "Units", "hHbBsSkKmMgGtTpPeE")
|
||||
val(segtype_VAL, segtype_arg, "SegType", "linear|striped|snapshot|mirror|raid*|thin|cache|thin-pool|cache-pool")
|
||||
/* FIXME: cling_by_tags is left out of help text because it makes the line wrap */
|
||||
val(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|normal|anywhere|inherit")
|
||||
val(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|cling_by_tags|normal|anywhere|inherit")
|
||||
val(locktype_VAL, locktype_arg, "LockType", "sanlock|dlm|none")
|
||||
val(readahead_VAL, readahead_arg, "Readahead", "auto|none|NumberSectors")
|
||||
val(metadatacopies_VAL, metadatacopies_arg, "MetadataCopies", "all|unmanaged|Number")
|
||||
val(vgmetadatacopies_VAL, vgmetadatacopies_arg, "MetadataCopiesVG", "all|unmanaged|Number")
|
||||
val(pvmetadatacopies_VAL, pvmetadatacopies_arg, "MetadataCopiesPV", "0|1|2")
|
||||
val(metadatacopies_VAL, metadatacopies_arg, "unused", "unused")
|
||||
|
||||
/* this should always be last */
|
||||
val(VAL_COUNT, NULL, NULL, NULL)
|
||||
|
||||
/*
|
||||
* I suspect many of the following are good candidates for a custom VAL enum
|
||||
* for the benefit of custom parsing, or custom usage, or both:
|
||||
* FIXME: I suspect many of the following are good candidates for a custom VAL
|
||||
* enum for the benefit of custom parsing, or custom usage, or both:
|
||||
*
|
||||
* configreport_ARG, configtype_ARG, polloperation_ARG, raidrebuild_ARG,
|
||||
* raidsyncaction_ARG, raidwritemostly_ARG, reportformat_ARG, syncaction_ARG,
|
||||
|
@@ -482,6 +482,9 @@ static int _vgchange_metadata_copies(struct cmd_context *cmd,
|
||||
{
|
||||
uint32_t mda_copies = arg_uint_value(cmd, vgmetadatacopies_ARG, DEFAULT_VGMETADATACOPIES);
|
||||
|
||||
log_warn("vgchange_metadata_copies new %u vg_mda_copies %u D %u",
|
||||
mda_copies, vg_mda_copies(vg), DEFAULT_VGMETADATACOPIES);
|
||||
|
||||
if (mda_copies == vg_mda_copies(vg)) {
|
||||
if (vg_mda_copies(vg) == VGMETADATACOPIES_UNMANAGED)
|
||||
log_warn("Number of metadata copies for VG %s is already unmanaged.",
|
||||
|
@@ -157,24 +157,12 @@ int vgconvert(struct cmd_context *cmd, int argc, char **argv)
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, metadatacopies_ARG)) {
|
||||
log_error("Invalid option --metadatacopies, "
|
||||
"use --pvmetadatacopies instead.");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
if (!(cmd->fmt->features & FMT_MDAS) &&
|
||||
(arg_is_set(cmd, pvmetadatacopies_ARG) ||
|
||||
arg_is_set(cmd, metadatasize_ARG))) {
|
||||
arg_is_set(cmd, pvmetadatacopies_ARG)) {
|
||||
log_error("Metadata parameters only apply to text format");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, pvmetadatacopies_ARG) &&
|
||||
arg_int_value(cmd, pvmetadatacopies_ARG, -1) > 2) {
|
||||
log_error("Metadatacopies may only be 0, 1 or 2");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (!(cmd->fmt->features & FMT_BAS) &&
|
||||
arg_is_set(cmd, bootloaderareasize_ARG)) {
|
||||
log_error("Bootloader area parameters only apply to text format");
|
||||
|
@@ -136,12 +136,6 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, metadatacopies_ARG)) {
|
||||
log_error("Invalid option --metadatacopies, "
|
||||
"use --pvmetadatacopies instead.");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
vg_name = skip_dev_dir(cmd, argv[0], NULL);
|
||||
argc--;
|
||||
argv++;
|
||||
|
Reference in New Issue
Block a user