mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
virsh: fix regression in argv parsing
Prior to commit85d2810
, 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 commit85d2810
, 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 of85d2810
, 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.
This commit is contained in:
parent
2f0595244b
commit
466f902446
@ -118,6 +118,7 @@ for args in \
|
|||||||
'test name desc vda vdb' \
|
'test name desc vda vdb' \
|
||||||
'test --diskspec vda name --diskspec vdb desc' \
|
'test --diskspec vda name --diskspec vdb desc' \
|
||||||
'--description desc --name name --domain test vda vdb' \
|
'--description desc --name name --domain test vda vdb' \
|
||||||
|
'--description desc --diskspec vda --name name --domain test vdb' \
|
||||||
; do
|
; do
|
||||||
virsh -q -c $test_url snapshot-create-as --print-xml $args \
|
virsh -q -c $test_url snapshot-create-as --print-xml $args \
|
||||||
>out 2>>err || fail=1
|
>out 2>>err || fail=1
|
||||||
@ -126,4 +127,12 @@ done
|
|||||||
|
|
||||||
test -s err && fail=1
|
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
|
(exit $fail); exit $fail
|
||||||
|
@ -13834,6 +13834,7 @@ vshCmddefGetInfo(const vshCmdDef * cmd, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Validate that the options associated with cmd can be parsed. */
|
||||||
static int
|
static int
|
||||||
vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
|
vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
|
||||||
uint32_t *opts_required)
|
uint32_t *opts_required)
|
||||||
@ -13871,13 +13872,16 @@ vshCmddefOptParse(const vshCmdDef *cmd, uint32_t *opts_need_arg,
|
|||||||
} else {
|
} else {
|
||||||
optional = true;
|
optional = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt->type == VSH_OT_ARGV && cmd->opts[i + 1].name)
|
||||||
|
return -1; /* argv option must be listed last */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const vshCmdOptDef *
|
static const vshCmdOptDef *
|
||||||
vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
|
vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
|
||||||
uint32_t *opts_seen)
|
uint32_t *opts_seen, int *opt_index)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -13885,12 +13889,12 @@ vshCmddefGetOption(vshControl *ctl, const vshCmdDef *cmd, const char *name,
|
|||||||
const vshCmdOptDef *opt = &cmd->opts[i];
|
const vshCmdOptDef *opt = &cmd->opts[i];
|
||||||
|
|
||||||
if (STREQ(opt->name, name)) {
|
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);
|
vshError(ctl, _("option --%s already seen"), name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (opt->type != VSH_OT_ARGV)
|
*opts_seen |= 1 << i;
|
||||||
*opts_seen |= 1 << i;
|
*opt_index = i;
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13913,10 +13917,9 @@ vshCmddefGetData(const vshCmdDef *cmd, uint32_t *opts_need_arg,
|
|||||||
/* Grab least-significant set bit */
|
/* Grab least-significant set bit */
|
||||||
i = ffs(*opts_need_arg) - 1;
|
i = ffs(*opts_need_arg) - 1;
|
||||||
opt = &cmd->opts[i];
|
opt = &cmd->opts[i];
|
||||||
if (opt->type != VSH_OT_ARGV) {
|
if (opt->type != VSH_OT_ARGV)
|
||||||
*opts_need_arg &= ~(1 << i);
|
*opts_need_arg &= ~(1 << i);
|
||||||
*opts_seen |= 1 << i;
|
*opts_seen |= 1 << i;
|
||||||
}
|
|
||||||
return opt;
|
return opt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14883,12 +14886,14 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser)
|
|||||||
} else if (tkdata[0] == '-' && tkdata[1] == '-' &&
|
} else if (tkdata[0] == '-' && tkdata[1] == '-' &&
|
||||||
c_isalnum(tkdata[2])) {
|
c_isalnum(tkdata[2])) {
|
||||||
char *optstr = strchr(tkdata + 2, '=');
|
char *optstr = strchr(tkdata + 2, '=');
|
||||||
|
int opt_index;
|
||||||
|
|
||||||
if (optstr) {
|
if (optstr) {
|
||||||
*optstr = '\0'; /* convert the '=' to '\0' */
|
*optstr = '\0'; /* convert the '=' to '\0' */
|
||||||
optstr = vshStrdup(ctl, optstr + 1);
|
optstr = vshStrdup(ctl, optstr + 1);
|
||||||
}
|
}
|
||||||
if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
|
if (!(opt = vshCmddefGetOption(ctl, cmd, tkdata + 2,
|
||||||
&opts_seen))) {
|
&opts_seen, &opt_index))) {
|
||||||
VIR_FREE(optstr);
|
VIR_FREE(optstr);
|
||||||
goto syntaxError;
|
goto syntaxError;
|
||||||
}
|
}
|
||||||
@ -14910,7 +14915,8 @@ vshCommandParse(vshControl *ctl, vshCommandParser *parser)
|
|||||||
VSH_OT_INT ? _("number") : _("string"));
|
VSH_OT_INT ? _("number") : _("string"));
|
||||||
goto syntaxError;
|
goto syntaxError;
|
||||||
}
|
}
|
||||||
opts_need_arg &= ~opts_seen;
|
if (opt->type != VSH_OT_ARGV)
|
||||||
|
opts_need_arg &= ~(1 << opt_index);
|
||||||
} else {
|
} else {
|
||||||
tkdata = NULL;
|
tkdata = NULL;
|
||||||
if (optstr) {
|
if (optstr) {
|
||||||
|
Loading…
Reference in New Issue
Block a user