qemu-img: Use user_creatable_process_cmdline() for --object
This switches qemu-img from a QemuOpts-based parser for --object to
user_creatable_process_cmdline() which uses a keyval parser and enforces
the QAPI schema.
Apart from being a cleanup, this makes non-scalar properties accessible.
As a side effect, fix wrong exit codes in the object parsing error path
of 'qemu-img compare'. This was broken in commit 334c43e2c3
because
&error_fatal exits with an exit code of 1, while it should have been 2.
Document that exit code 0 is also returned when just requested help was
printed instead of comparing images. This is preexisting behaviour that
isn't changed by this patch, though another instance of it is added with
'--object help'.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
ffd58ef88c
commit
99b1e64688
@ -404,7 +404,7 @@ Command description:
|
||||
The following table sumarizes all exit codes of the compare subcommand:
|
||||
|
||||
0
|
||||
Images are identical
|
||||
Images are identical (or requested help was printed)
|
||||
1
|
||||
Images differ
|
||||
2
|
||||
|
251
qemu-img.c
251
qemu-img.c
@ -226,23 +226,6 @@ static void QEMU_NORETURN help(void)
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static QemuOptsList qemu_object_opts = {
|
||||
.name = "object",
|
||||
.implied_opt_name = "qom-type",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
|
||||
.desc = {
|
||||
{ }
|
||||
},
|
||||
};
|
||||
|
||||
static bool qemu_img_object_print_help(const char *type, QemuOpts *opts)
|
||||
{
|
||||
if (user_creatable_print_help(type, opts)) {
|
||||
exit(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is @optarg safe for accumulate_options()?
|
||||
* It is when multiple of them can be joined together separated by ','.
|
||||
@ -566,14 +549,9 @@ static int img_create(int argc, char **argv)
|
||||
case 'u':
|
||||
flags |= BDRV_O_NO_BACKING;
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
goto fail;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -589,12 +567,6 @@ static int img_create(int argc, char **argv)
|
||||
}
|
||||
optind++;
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Get image size, if specified */
|
||||
if (optind < argc) {
|
||||
int64_t sval;
|
||||
@ -804,14 +776,9 @@ static int img_check(int argc, char **argv)
|
||||
case 'U':
|
||||
force_share = true;
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -831,12 +798,6 @@ static int img_check(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
|
||||
if (ret < 0) {
|
||||
error_report("Invalid source cache option: %s", cache);
|
||||
@ -1034,14 +995,9 @@ static int img_commit(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -1058,12 +1014,6 @@ static int img_commit(int argc, char **argv)
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
flags = BDRV_O_RDWR | BDRV_O_UNMAP;
|
||||
ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
|
||||
if (ret < 0) {
|
||||
@ -1353,7 +1303,7 @@ static int check_empty_sectors(BlockBackend *blk, int64_t offset,
|
||||
/*
|
||||
* Compares two images. Exit codes:
|
||||
*
|
||||
* 0 - Images are identical
|
||||
* 0 - Images are identical or the requested help was printed
|
||||
* 1 - Images differ
|
||||
* >1 - Error occurred
|
||||
*/
|
||||
@ -1423,15 +1373,21 @@ static int img_compare(int argc, char **argv)
|
||||
case 'U':
|
||||
force_share = true;
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
ret = 2;
|
||||
goto out4;
|
||||
case OPTION_OBJECT:
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!user_creatable_add_from_str(optarg, &local_err)) {
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
exit(2);
|
||||
} else {
|
||||
/* Help was printed */
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -1450,13 +1406,6 @@ static int img_compare(int argc, char **argv)
|
||||
filename1 = argv[optind++];
|
||||
filename2 = argv[optind++];
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
ret = 2;
|
||||
goto out4;
|
||||
}
|
||||
|
||||
/* Initialize before goto out */
|
||||
qemu_progress_init(progress, 2.0);
|
||||
|
||||
@ -1641,7 +1590,6 @@ out2:
|
||||
blk_unref(blk1);
|
||||
out3:
|
||||
qemu_progress_end();
|
||||
out4:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2342,15 +2290,9 @@ static int img_convert(int argc, char **argv)
|
||||
goto fail_getopt;
|
||||
}
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *object_opts;
|
||||
object_opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!object_opts) {
|
||||
goto fail_getopt;
|
||||
}
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
}
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -2378,12 +2320,6 @@ static int img_convert(int argc, char **argv)
|
||||
out_fmt = "raw";
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
goto fail_getopt;
|
||||
}
|
||||
|
||||
if (s.compressed && s.copy_range) {
|
||||
error_report("Cannot enable copy offloading when -c is used");
|
||||
goto fail_getopt;
|
||||
@ -2971,14 +2907,9 @@ static int img_info(int argc, char **argv)
|
||||
case OPTION_BACKING_CHAIN:
|
||||
chain = true;
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -2998,12 +2929,6 @@ static int img_info(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
list = collect_image_info_list(image_opts, filename, fmt, chain,
|
||||
force_share);
|
||||
if (!list) {
|
||||
@ -3213,14 +3138,9 @@ static int img_map(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -3240,12 +3160,6 @@ static int img_map(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
blk = img_open(image_opts, filename, fmt, 0, false, false, force_share);
|
||||
if (!blk) {
|
||||
return 1;
|
||||
@ -3384,14 +3298,9 @@ static int img_snapshot(int argc, char **argv)
|
||||
case 'U':
|
||||
force_share = true;
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -3403,12 +3312,6 @@ static int img_snapshot(int argc, char **argv)
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Open the image */
|
||||
blk = img_open(image_opts, filename, NULL, bdrv_oflags, false, quiet,
|
||||
force_share);
|
||||
@ -3542,14 +3445,9 @@ static int img_rebase(int argc, char **argv)
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -3571,12 +3469,6 @@ static int img_rebase(int argc, char **argv)
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
qemu_progress_init(progress, 2.0);
|
||||
qemu_progress_print(0, 100);
|
||||
|
||||
@ -3967,14 +3859,9 @@ static int img_resize(int argc, char **argv)
|
||||
case 'q':
|
||||
quiet = true;
|
||||
break;
|
||||
case OPTION_OBJECT: {
|
||||
QemuOpts *opts;
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
return 1;
|
||||
}
|
||||
} break;
|
||||
case OPTION_OBJECT:
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
break;
|
||||
@ -3996,12 +3883,6 @@ static int img_resize(int argc, char **argv)
|
||||
}
|
||||
filename = argv[optind++];
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Choose grow, shrink, or absolute resize mode */
|
||||
switch (size[0]) {
|
||||
case '+':
|
||||
@ -4181,12 +4062,7 @@ static int img_amend(int argc, char **argv)
|
||||
quiet = true;
|
||||
break;
|
||||
case OPTION_OBJECT:
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!opts) {
|
||||
ret = -1;
|
||||
goto out_no_progress;
|
||||
}
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
@ -4201,13 +4077,6 @@ static int img_amend(int argc, char **argv)
|
||||
error_exit("Must specify options (-o)");
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
ret = -1;
|
||||
goto out_no_progress;
|
||||
}
|
||||
|
||||
if (quiet) {
|
||||
progress = false;
|
||||
}
|
||||
@ -4760,10 +4629,7 @@ static int img_bitmap(int argc, char **argv)
|
||||
merge = true;
|
||||
break;
|
||||
case OPTION_OBJECT:
|
||||
opts = qemu_opts_parse_noisily(&qemu_object_opts, optarg, true);
|
||||
if (!opts) {
|
||||
goto out;
|
||||
}
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
@ -4771,12 +4637,6 @@ static int img_bitmap(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (QSIMPLEQ_EMPTY(&actions)) {
|
||||
error_report("Need at least one of --add, --remove, --clear, "
|
||||
"--enable, --disable, or --merge");
|
||||
@ -5034,10 +4894,7 @@ static int img_dd(int argc, char **argv)
|
||||
force_share = true;
|
||||
break;
|
||||
case OPTION_OBJECT:
|
||||
if (!qemu_opts_parse_noisily(&qemu_object_opts, optarg, true)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
@ -5084,13 +4941,6 @@ static int img_dd(int argc, char **argv)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
blk1 = img_open(image_opts, in.filename, fmt, 0, false, false,
|
||||
force_share);
|
||||
|
||||
@ -5311,11 +5161,7 @@ static int img_measure(int argc, char **argv)
|
||||
force_share = true;
|
||||
break;
|
||||
case OPTION_OBJECT:
|
||||
object_opts = qemu_opts_parse_noisily(&qemu_object_opts,
|
||||
optarg, true);
|
||||
if (!object_opts) {
|
||||
goto out;
|
||||
}
|
||||
user_creatable_process_cmdline(optarg);
|
||||
break;
|
||||
case OPTION_IMAGE_OPTS:
|
||||
image_opts = true;
|
||||
@ -5345,12 +5191,6 @@ static int img_measure(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (qemu_opts_foreach(&qemu_object_opts,
|
||||
user_creatable_add_opts_foreach,
|
||||
qemu_img_object_print_help, &error_fatal)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (argc - optind > 1) {
|
||||
error_report("At most one filename argument is allowed.");
|
||||
goto out;
|
||||
@ -5490,7 +5330,6 @@ int main(int argc, char **argv)
|
||||
error_exit("Not enough arguments");
|
||||
}
|
||||
|
||||
qemu_add_opts(&qemu_object_opts);
|
||||
qemu_add_opts(&qemu_source_opts);
|
||||
qemu_add_opts(&qemu_trace_opts);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user