From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, stefanha@redhat.com, qemu-devel@nongnu.org
Subject: [PULL 36/57] qemu-img: factor out parse_output_format() and use it in the code
Date: Tue, 15 Jul 2025 21:03:09 +0200 [thread overview]
Message-ID: <20250715190330.378764-37-kwolf@redhat.com> (raw)
In-Reply-To: <20250715190330.378764-1-kwolf@redhat.com>
From: Michael Tokarev <mjt@tls.msk.ru>
Use common code and simplify error message
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Message-ID: <20250531171609.197078-7-mjt@tls.msk.ru>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img.c | 63 +++++++++-----------------------
tests/qemu-iotests/178 | 2 +-
tests/qemu-iotests/178.out.qcow2 | 3 +-
tests/qemu-iotests/178.out.raw | 3 +-
tests/qemu-iotests/common.filter | 6 +++
5 files changed, 29 insertions(+), 48 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 6569efd310..b60b4d38df 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -158,6 +158,17 @@ void cmd_help(const img_cmd_t *ccmd,
exit(EXIT_SUCCESS);
}
+static OutputFormat parse_output_format(const char *argv0, const char *arg)
+{
+ if (!strcmp(arg, "json")) {
+ return OFORMAT_JSON;
+ } else if (!strcmp(arg, "human")) {
+ return OFORMAT_HUMAN;
+ } else {
+ error_exit(argv0, "--output expects 'human' or 'json', not '%s'", arg);
+ }
+}
+
/* Please keep in synch with docs/tools/qemu-img.rst */
static G_NORETURN
void help(void)
@@ -775,7 +786,7 @@ static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
{
int c, ret;
OutputFormat output_format = OFORMAT_HUMAN;
- const char *filename, *fmt, *output, *cache;
+ const char *filename, *fmt, *cache;
BlockBackend *blk;
BlockDriverState *bs;
int fix = 0;
@@ -787,7 +798,6 @@ static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
bool force_share = false;
fmt = NULL;
- output = NULL;
cache = BDRV_DEFAULT_CACHE;
for(;;) {
@@ -833,7 +843,7 @@ static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
}
break;
case OPTION_OUTPUT:
- output = optarg;
+ output_format = parse_output_format(argv[0], optarg);
break;
case 'T':
cache = optarg;
@@ -857,15 +867,6 @@ static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
}
filename = argv[optind++];
- if (output && !strcmp(output, "json")) {
- output_format = OFORMAT_JSON;
- } else if (output && !strcmp(output, "human")) {
- output_format = OFORMAT_HUMAN;
- } else if (output) {
- error_report("--output must be used with human or json as argument.");
- return 1;
- }
-
ret = bdrv_parse_cache_mode(cache, &flags, &writethrough);
if (ret < 0) {
error_report("Invalid source cache option: %s", cache);
@@ -3059,13 +3060,12 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
int c;
OutputFormat output_format = OFORMAT_HUMAN;
bool chain = false;
- const char *filename, *fmt, *output;
+ const char *filename, *fmt;
BlockGraphInfoList *list;
bool image_opts = false;
bool force_share = false;
fmt = NULL;
- output = NULL;
for(;;) {
int option_index = 0;
static const struct option long_options[] = {
@@ -3100,7 +3100,7 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
force_share = true;
break;
case OPTION_OUTPUT:
- output = optarg;
+ output_format = parse_output_format(argv[0], optarg);
break;
case OPTION_BACKING_CHAIN:
chain = true;
@@ -3118,15 +3118,6 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
}
filename = argv[optind++];
- if (output && !strcmp(output, "json")) {
- output_format = OFORMAT_JSON;
- } else if (output && !strcmp(output, "human")) {
- output_format = OFORMAT_HUMAN;
- } else if (output) {
- error_report("--output must be used with human or json as argument.");
- return 1;
- }
-
list = collect_image_info_list(image_opts, filename, fmt, chain,
force_share);
if (!list) {
@@ -3285,7 +3276,7 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
OutputFormat output_format = OFORMAT_HUMAN;
BlockBackend *blk;
BlockDriverState *bs;
- const char *filename, *fmt, *output;
+ const char *filename, *fmt;
int64_t length;
MapEntry curr = { .length = 0 }, next;
int ret = 0;
@@ -3295,7 +3286,6 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
int64_t max_length = -1;
fmt = NULL;
- output = NULL;
for (;;) {
int option_index = 0;
static const struct option long_options[] = {
@@ -3331,7 +3321,7 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
force_share = true;
break;
case OPTION_OUTPUT:
- output = optarg;
+ output_format = parse_output_format(argv[0], optarg);
break;
case 's':
start_offset = cvtnum("start offset", optarg);
@@ -3358,15 +3348,6 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
}
filename = argv[optind];
- if (output && !strcmp(output, "json")) {
- output_format = OFORMAT_JSON;
- } else if (output && !strcmp(output, "human")) {
- output_format = OFORMAT_HUMAN;
- } else if (output) {
- error_report("--output must be used with human or json as argument.");
- return 1;
- }
-
blk = img_open(image_opts, filename, fmt, 0, false, false, force_share);
if (!blk) {
return 1;
@@ -5473,15 +5454,7 @@ static int img_measure(const img_cmd_t *ccmd, int argc, char **argv)
image_opts = true;
break;
case OPTION_OUTPUT:
- if (!strcmp(optarg, "json")) {
- output_format = OFORMAT_JSON;
- } else if (!strcmp(optarg, "human")) {
- output_format = OFORMAT_HUMAN;
- } else {
- error_report("--output must be used with human or json "
- "as argument.");
- goto out;
- }
+ output_format = parse_output_format(argv[0], optarg);
break;
case OPTION_SIZE:
img_size = cvtnum("image size", optarg);
diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178
index 8df241ead8..463c59a77f 100755
--- a/tests/qemu-iotests/178
+++ b/tests/qemu-iotests/178
@@ -58,7 +58,7 @@ $QEMU_IMG measure -f qcow2 # missing filename
$QEMU_IMG measure -l snap1 # missing filename
$QEMU_IMG measure -o , # invalid option list
$QEMU_IMG measure -l snapshot.foo=bar # invalid snapshot option
-$QEMU_IMG measure --output foo # invalid output format
+$QEMU_IMG measure --output foo 2>&1 | _filter_qemu_img # invalid output format
$QEMU_IMG measure --size -1 # invalid image size
$QEMU_IMG measure -O foo "$TEST_IMG" # unknown image file format
diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2
index fe193fd5f4..61506b519f 100644
--- a/tests/qemu-iotests/178.out.qcow2
+++ b/tests/qemu-iotests/178.out.qcow2
@@ -12,7 +12,8 @@ qemu-img: --image-opts, -f, and -l require a filename argument.
qemu-img: Invalid option list: ,
qemu-img: Invalid parameter 'snapshot.foo'
qemu-img: Failed in parsing snapshot param 'snapshot.foo=bar'
-qemu-img: --output must be used with human or json as argument.
+qemu-img: --output expects 'human' or 'json', not 'foo'
+Try 'qemu-img measure --help' for more information
qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
qemu-img: Unknown file format 'foo'
diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw
index 445e460fad..6d994a433a 100644
--- a/tests/qemu-iotests/178.out.raw
+++ b/tests/qemu-iotests/178.out.raw
@@ -12,7 +12,8 @@ qemu-img: --image-opts, -f, and -l require a filename argument.
qemu-img: Invalid option list: ,
qemu-img: Invalid parameter 'snapshot.foo'
qemu-img: Failed in parsing snapshot param 'snapshot.foo=bar'
-qemu-img: --output must be used with human or json as argument.
+qemu-img: --output expects 'human' or 'json', not 'foo'
+Try 'qemu-img measure --help' for more information
qemu-img: Invalid image size specified. Must be between 0 and 9223372036854775807.
qemu-img: Unknown file format 'foo'
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index fc3c64bcb8..67f819d866 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -86,6 +86,12 @@ _filter_qemu()
-e $'s#\r##' # QEMU monitor uses \r\n line endings
}
+# replace occurrences of QEMU_IMG_PROG with "qemu-img"
+_filter_qemu_img()
+{
+ sed -e "s#$QEMU_IMG_PROG#qemu-img#g"
+}
+
# replace problematic QMP output like timestamps
_filter_qmp()
{
--
2.50.1
next prev parent reply other threads:[~2025-07-15 19:33 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-15 19:02 [PULL 00/57] Block layer patches Kevin Wolf
2025-07-15 19:02 ` [PULL 01/57] block: never use atomics to access bs->quiesce_counter Kevin Wolf
2025-07-15 19:02 ` [PULL 02/57] block: add bdrv_graph_wrlock_drained() convenience wrapper Kevin Wolf
2025-07-15 19:02 ` [PULL 03/57] block/mirror: switch to bdrv_set_backing_hd_drained() variant Kevin Wolf
2025-07-15 19:02 ` [PULL 04/57] block/commit: " Kevin Wolf
2025-07-15 19:02 ` [PULL 05/57] block: call bdrv_set_backing_hd() while unlocked in bdrv_open_backing_file() Kevin Wolf
2025-07-15 19:02 ` [PULL 06/57] block: mark bdrv_set_backing_hd() as GRAPH_UNLOCKED Kevin Wolf
2025-07-15 19:02 ` [PULL 07/57] blockdev: avoid locking and draining multiple times in external_snapshot_abort() Kevin Wolf
2025-07-15 19:02 ` [PULL 08/57] block: drop wrapper for bdrv_set_backing_hd_drained() Kevin Wolf
2025-07-15 19:02 ` [PULL 09/57] block-backend: mark blk_drain_all() as GRAPH_UNLOCKED Kevin Wolf
2025-07-15 19:02 ` [PULL 10/57] block/snapshot: mark bdrv_all_delete_snapshot() " Kevin Wolf
2025-07-15 19:02 ` [PULL 11/57] block/stream: mark stream_prepare() " Kevin Wolf
2025-07-15 19:02 ` [PULL 12/57] block: mark bdrv_reopen_queue() and bdrv_reopen_multiple() " Kevin Wolf
2025-07-15 19:02 ` [PULL 13/57] block: mark bdrv_inactivate() as GRAPH_RDLOCK and move drain to callers Kevin Wolf
2025-07-15 19:02 ` [PULL 14/57] block: mark bdrv_inactivate_all() as GRAPH_UNLOCKED Kevin Wolf
2025-07-15 19:02 ` [PULL 15/57] block: mark blk_remove_bs() " Kevin Wolf
2025-07-15 19:02 ` [PULL 16/57] block: mark blk_drain() " Kevin Wolf
2025-07-15 19:02 ` [PULL 17/57] block-backend: mark blk_io_limits_disable() " Kevin Wolf
2025-07-15 19:02 ` [PULL 18/57] block/commit: mark commit_abort() " Kevin Wolf
2025-07-15 19:02 ` [PULL 19/57] block: Allow bdrv_new() with and without graph lock Kevin Wolf
2025-07-15 19:02 ` [PULL 20/57] block: mark bdrv_replace_child_bs() as GRAPH_UNLOCKED Kevin Wolf
2025-07-15 19:02 ` [PULL 21/57] block: mark bdrv_insert_node() " Kevin Wolf
2025-07-15 19:02 ` [PULL 22/57] block: mark bdrv_drop_intermediate() " Kevin Wolf
2025-07-15 19:02 ` [PULL 23/57] block: mark bdrv_close_all() " Kevin Wolf
2025-07-15 19:02 ` [PULL 24/57] block: mark bdrv_close() " Kevin Wolf
2025-07-15 19:02 ` [PULL 25/57] block: mark bdrv_open_child_common() and its callers GRAPH_UNLOCKED Kevin Wolf
2025-07-15 19:02 ` [PULL 26/57] blockjob: mark block_job_remove_all_bdrv() as GRAPH_UNLOCKED Kevin Wolf
2025-07-15 19:03 ` [PULL 27/57] block/qapi: include child references in block device info Kevin Wolf
2025-07-15 19:03 ` [PULL 28/57] block/qapi: make @node-name in @BlockDeviceInfo non-optional Kevin Wolf
2025-07-15 19:03 ` [PULL 29/57] file-posix: Fix aio=threads performance regression after enablign FUA Kevin Wolf
2025-07-15 19:03 ` [PULL 30/57] iotests: add test for changing the 'drive' property via 'qom-set' Kevin Wolf
2025-07-15 19:03 ` [PULL 31/57] qemu-img: measure: convert img_size to signed, simplify handling Kevin Wolf
2025-07-15 19:03 ` [PULL 32/57] qemu-img: create: " Kevin Wolf
2025-07-15 19:03 ` [PULL 33/57] qemu-img: global option processing and error printing Kevin Wolf
2025-07-15 19:03 ` [PULL 34/57] qemu-img: pass current cmd info into command handlers Kevin Wolf
2025-07-15 19:03 ` [PULL 35/57] qemu-img: create: refresh options/--help (short option change) Kevin Wolf
2025-07-15 19:03 ` Kevin Wolf [this message]
2025-07-15 19:03 ` [PULL 37/57] qemu-img: check: refresh options/--help Kevin Wolf
2025-07-15 19:03 ` [PULL 38/57] qemu-img: simplify --repair error message Kevin Wolf
2025-07-15 19:03 ` [PULL 39/57] qemu-img: commit: refresh options/--help Kevin Wolf
2025-07-15 19:03 ` [PULL 40/57] qemu-img: compare: use helper function for --object Kevin Wolf
2025-07-15 19:03 ` [PULL 41/57] qemu-img: compare: refresh options/--help Kevin Wolf
2025-07-15 19:03 ` [PULL 42/57] qemu-img: convert: refresh options/--help (short option change) Kevin Wolf
2025-07-15 19:03 ` [PULL 43/57] qemu-img: info: refresh options/--help Kevin Wolf
2025-07-15 19:03 ` [PULL 44/57] qemu-img: map: " Kevin Wolf
2025-07-15 19:03 ` [PULL 45/57] qemu-img: snapshot: allow specifying -f fmt Kevin Wolf
2025-07-15 19:03 ` [PULL 46/57] qemu-img: snapshot: make -l (list) the default, simplify option handling Kevin Wolf
2025-07-15 19:03 ` [PULL 47/57] qemu-img: snapshot: refresh options/--help Kevin Wolf
2025-07-15 19:03 ` [PULL 48/57] qemu-img: rebase: refresh options/--help (short option change) Kevin Wolf
2025-07-15 19:03 ` [PULL 49/57] qemu-img: resize: do not always eat last argument Kevin Wolf
2025-07-15 19:03 ` [PULL 50/57] qemu-img: resize: refresh options/--help Kevin Wolf
2025-07-15 19:03 ` [PULL 51/57] qemu-img: amend: " Kevin Wolf
2025-07-15 19:03 ` [PULL 52/57] qemu-img: bench: " Kevin Wolf
2025-07-15 19:03 ` [PULL 53/57] qemu-img: bitmap: " Kevin Wolf
2025-07-15 19:03 ` [PULL 54/57] qemu-img: dd: " Kevin Wolf
2025-07-15 19:03 ` [PULL 55/57] qemu-img: measure: " Kevin Wolf
2025-07-15 19:03 ` [PULL 56/57] qemu-img: implement short --help, remove global help() function Kevin Wolf
2025-07-15 19:03 ` [PULL 57/57] qemu-img: extend cvtnum() and use it in more places Kevin Wolf
2025-07-16 12:41 ` [PULL 00/57] Block layer patches Stefan Hajnoczi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250715190330.378764-37-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).