[lvm-devel] master - commands: check required option value when matching command

David Teigland teigland at sourceware.org
Tue Apr 11 15:22:05 UTC 2017


Gitweb:        https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=a4f07b701a009aba2ceca7fdb4ef880505ad54c3
Commit:        a4f07b701a009aba2ceca7fdb4ef880505ad54c3
Parent:        a14a8cef2ff1ae5c9c946bde5a885667288e24d3
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Mon Apr 10 13:41:47 2017 -0500
Committer:     David Teigland <teigland at redhat.com>
CommitterDate: Mon Apr 10 13:41:47 2017 -0500

commands: check required option value when matching command

A command def can include a specific constant option value,
but the value was not being checked for optional opts.

e.g. this is an incorrect command and does not match any
command defs:

lvconvert --type cache --cachepool vg/lv

However, it was mistakely being matched to this cmd def,
where the required options match, but the optional options
do not:

lonvert --cachepool LV_linear_striped_raid_cachepool
OO: --type cache-pool, ...

The optional options were mistakely considered matching
because 'cache' and 'cache-pool' were not being compared.
---
 tools/lvmcmdline.c |   31 ++++++++++++++++++++++++++++---
 1 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 280a052..3626b1b 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -1338,6 +1338,25 @@ static int _opt_synonym_is_set(struct cmd_context *cmd, int opt_std)
 	return opt_syn && arg_is_set(cmd, opt_syn);
 }
 
+static int _command_optional_opt_matches(struct cmd_context *cmd, int ci, int oo)
+{
+	int opt_enum = commands[ci].optional_opt_args[oo].opt;
+
+	if (val_bit_is_set(commands[ci].optional_opt_args[oo].def.val_bits, conststr_VAL)) {
+		if (!strcmp(commands[ci].optional_opt_args[oo].def.str, arg_str_value(cmd, opt_enum, "")))
+			return 1;
+		return 0;
+	}
+
+	if (val_bit_is_set(commands[ci].optional_opt_args[oo].def.val_bits, constnum_VAL)) {
+		if (commands[ci].optional_opt_args[oo].def.num == arg_int_value(cmd, opt_enum, 0))
+			return 1;
+		return 0;
+	}
+
+	return 1;
+}
+
 static int _command_ignore_opt_matches(struct cmd_context *cmd, int ci, int io)
 {
 	int opt_enum = commands[ci].ignore_opt_args[io].opt;
@@ -1625,7 +1644,8 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
 				continue;
 
 			for (j = 0; j < commands[i].oo_count; j++) {
-				if (commands[i].optional_opt_args[j].opt == opt_enum) {
+				if ((commands[i].optional_opt_args[j].opt == opt_enum) &&
+				    _command_optional_opt_matches(cmd, i, j)) {
 					accepted = 1;
 					break;
 				}
@@ -1695,8 +1715,13 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
 
 	if (best_unused_count) {
 		for (i = 0; i < best_unused_count; i++) {
-			log_error("Invalid option for command: %s.",
-				  arg_long_option_name(best_unused_options[i]));
+			const char *opt_val = NULL;
+			opt_enum = best_unused_options[i];
+			opt_val = arg_value(cmd, opt_enum);
+
+			log_error("Invalid option for command: %s%s%s.",
+				  arg_long_option_name(opt_enum),
+				  opt_val ? " " : "", opt_val ?: "");
 		}
 		return NULL;
 	}




More information about the lvm-devel mailing list