提交 466f9024 编写于 作者: E Eric Blake 提交者: Daniel Veillard

virsh: fix regression in argv parsing

Prior to commit 85d28108, we had an issue where:

snapshot-create-as dom name --diskspec spec --diskspec spec

failed to parse the second spec, because the first spec had marked
that option as no longer requiring an argument.

In commit 85d28108, I fixed it by making argv options no longer mark
the option as seen.  But this in turn breaks mandatory argv options,
which now complain that the argv option is missing.

This patch reverts that part of 85d28108, and instead replaces it with
fixes to no longer clear opts_need_arg of an argv argument.

* tools/virsh.c (vshCmddefGetOption, vshCmddefGetData)
(vshCommandParse): Fix option parsing for required argv option.
(vshCmddefOptParse): Check that argv option is last.
* tests/virsh-optparse: Enhance test.
上级 2f059524
......@@ -118,6 +118,7 @@ for args in \
'test name desc vda vdb' \
'test --diskspec vda name --diskspec vdb desc' \
'--description desc --name name --domain test vda vdb' \
'--description desc --diskspec vda --name name --domain test vdb' \
; do
virsh -q -c $test_url snapshot-create-as --print-xml $args \
>out 2>>err || fail=1
......@@ -126,4 +127,12 @@ done
test -s err && fail=1
# Test a required argv
cat <<\EOF > exp-err || framework_failure
error: this function is not supported by the connection driver: virDomainQemuMonitorCommand
EOF
virsh -q -c $test_url qemu-monitor-command test a >out 2>err && fail=1
test -s out && fail=1
compare err exp-err || fail=1
(exit $fail); exit $fail
......@@ -13834,6 +13834,7 @@ vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
return NULL;
}
/* Validate that the options associated with cmd can be parsed. */
static int
vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
uint32_t *opts_required)
......@@ -13871,13 +13872,16 @@ vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
} else {
optional = true;
}
if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name)
return -1; /* argv option must be listed last */
}
return 0;
}
static const vshCmdOptDef *
vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
uint32_t *opts_seen)
uint32_t *opts_seen, int *opt_index)
{
int i;
......@@ -13885,12 +13889,12 @@ vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
const vshCmdOptDef *opt = &cmd->opts[i];
if (STREQ(opt->name, name)) {
if (*opts_seen & (1 << i)) {
if ((*opts_seen & (1 << i)) && opt->type != VSH_OT_ARGV) {
vshError(ctl, _("option --%s already seen"), name);
return NULL;
}
if (opt->type != VSH_OT_ARGV)
*opts_seen |= 1 << i;
*opts_seen |= 1 << i;
*opt_index = i;
return opt;
}
}
......@@ -13913,10 +13917,9 @@ vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg,
/* Grab least-significant set bit */
i = ffs(*opts_need_arg) - 1;
opt = &cmd->opts[i];
if (opt->type != VSH_OT_ARGV) {
if (opt->type != VSH_OT_ARGV)
*opts_need_arg &= ~(1 << i);
*opts_seen |= 1 << i;
}
*opts_seen |= 1 << i;
return opt;
}
......@@ -14883,12 +14886,14 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser)
} else if (tkdata[0] == '-' && tkdata[1] == '-' &&
c_isalnum(tkdata[2])) {
char *optstr = strchr(tkdata + 2, '=');
int opt_index;
if (optstr) {
*optstr = '\0'; /* convert the '=' to '\0' */
optstr = vshStrdup(ctl, optstr + 1);
}
if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
&opts_seen))) {
&opts_seen, &opt_index))) {
VIR_FREE(optstr);
goto syntaxError;
}
......@@ -14910,7 +14915,8 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser)
VSH_OT_INT ? _("number") : _("string"));
goto syntaxError;
}
opts_need_arg &= ~opts_seen;
if (opt->type != VSH_OT_ARGV)
opts_need_arg &= ~(1 << opt_index);
} else {
tkdata = NULL;
if (optstr) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册