* [PATCH v4 00/27] refresh qemu-img options handling
@ 2025-05-31 17:15 Michael Tokarev
2025-05-31 17:15 ` [PATCH 01/27] qemu-img: measure: convert img_size to signed, simplify handling Michael Tokarev
` (30 more replies)
0 siblings, 31 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
This is another iteration of this patch series, which tries
to add missing command-line options, --help output, make it
all more or less consistent, etc.
I addressed (hopefully) all comments so far, mostly by Kevin.
I ended up (so far) with a bit different wording somewhere.
The manpage (and the separate documentation) hasn't changed
much, but I intend to use the same wording there as in --help
output. An example of the separate documentation change is
provided with "create" subcommand only, as a PoC.
I tried to rename a few existing options to make them more
consistent. This is an RFC, so to say, - I'd love to make
more changes but it isn't really possible because the names
I want to use are already used for different purpose. All
such changes (3 in total) are marked with "(short option change)"
suffix in the patch subject. In particular, I tried to use
-b for backing-file, and -B for backing-format, in all places.
Maybe it's too late to change that though.
All subcommands now have --object option. I wonder why we
haven't done it in common place, before a subcommand. Maybe
it's a good idea (and I think it is) to add it to the common
(before-subcomman) place, document it there, and remove the
--object mentions from individual commands --help output.
Thanks,
/mjt
Michael Tokarev (27):
qemu-img: measure: convert img_size to signed, simplify handling
qemu-img: create: convert img_size to signed, simplify handling
qemu-img: global option processing and error printing
qemu-img: pass current cmd info into command handlers
qemu-img: create: refresh options/--help (short option change)
qemu-img: factor out parse_output_format() and use it in the code
qemu-img: check: refresh options/--help
qemu-img: simplify --repair error message
qemu-img: commit: refresh options/--help
qemu-img: compare: use helper function for --object
qemu-img: compare: refresh options/--help
qemu-img: convert: refresh options/--help (short option change)
qemu-img: info: refresh options/--help
qemu-img: map: refresh options/--help
qemu-img: snapshot: allow specifying -f fmt
qemu-img: snapshot: make -l (list) the default, simplify option handling
qemu-img: snapshot: refresh options/--help
qemu-img: rebase: refresh options/--help (short option change)
qemu-img: resize: do not always eat last argument
qemu-img: resize: refresh options/--help
qemu-img: amend: refresh options/--help
qemu-img: bench: refresh options/--help
qemu-img: bitmap: refresh options/--help
qemu-img: dd: refresh options/--help
qemu-img: measure: refresh options/--help
qemu-img: implement short --help, remove global help() function
qemu-img: extend cvtnum() and use it in more places
docs/tools/qemu-img.rst | 18 +-
qemu-img-cmds.hx | 4 +-
qemu-img.c | 1782 +++++++++++++++++++++---------------
tests/qemu-iotests/049.out | 9 +-
4 files changed, 1082 insertions(+), 731 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH 01/27] qemu-img: measure: convert img_size to signed, simplify handling
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 02/27] qemu-img: create: " Michael Tokarev
` (29 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
qemu_opt_set_number() expects signed int64_t.
Use int64_t instead of uint64_t for img_size, use -1 as "unset"
value instead of UINT64_MAX, and do not require temporary sval
for conversion from string.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img.c | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 139eeb5039..ec0f1152df 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -5368,7 +5368,7 @@ static int img_measure(int argc, char **argv)
QemuOpts *sn_opts = NULL;
QemuOptsList *create_opts = NULL;
bool image_opts = false;
- uint64_t img_size = UINT64_MAX;
+ int64_t img_size = -1;
BlockMeasureInfo *info = NULL;
Error *local_err = NULL;
int ret = 1;
@@ -5426,16 +5426,11 @@ static int img_measure(int argc, char **argv)
}
break;
case OPTION_SIZE:
- {
- int64_t sval;
-
- sval = cvtnum("image size", optarg);
- if (sval < 0) {
+ img_size = cvtnum("image size", optarg);
+ if (img_size < 0) {
goto out;
}
- img_size = (uint64_t)sval;
- }
- break;
+ break;
}
}
@@ -5450,11 +5445,11 @@ static int img_measure(int argc, char **argv)
error_report("--image-opts, -f, and -l require a filename argument.");
goto out;
}
- if (filename && img_size != UINT64_MAX) {
+ if (filename && img_size != -1) {
error_report("--size N cannot be used together with a filename.");
goto out;
}
- if (!filename && img_size == UINT64_MAX) {
+ if (!filename && img_size == -1) {
error_report("Either --size N or one filename must be specified.");
goto out;
}
@@ -5502,7 +5497,7 @@ static int img_measure(int argc, char **argv)
goto out;
}
}
- if (img_size != UINT64_MAX) {
+ if (img_size != -1) {
qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort);
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 02/27] qemu-img: create: convert img_size to signed, simplify handling
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
2025-05-31 17:15 ` [PATCH 01/27] qemu-img: measure: convert img_size to signed, simplify handling Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 03/27] qemu-img: global option processing and error printing Michael Tokarev
` (28 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Initializing an unsigned as -1, or using temporary
sval for conversion is awkward. Since we don't allow
other "negative" values anyway, use signed value and
pass it to bdrv_img_create() (where it is properly
converted to unsigned), simplifying code.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index ec0f1152df..974d31a4b3 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -511,7 +511,7 @@ static int64_t cvtnum(const char *name, const char *value)
static int img_create(int argc, char **argv)
{
int c;
- uint64_t img_size = -1;
+ int64_t img_size = -1;
const char *fmt = "raw";
const char *base_fmt = NULL;
const char *filename;
@@ -582,13 +582,10 @@ static int img_create(int argc, char **argv)
/* Get image size, if specified */
if (optind < argc) {
- int64_t sval;
-
- sval = cvtnum("image size", argv[optind++]);
- if (sval < 0) {
+ img_size = cvtnum("image size", argv[optind++]);
+ if (img_size < 0) {
goto fail;
}
- img_size = (uint64_t)sval;
}
if (optind != argc) {
error_exit("Unexpected argument: %s", argv[optind]);
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 03/27] qemu-img: global option processing and error printing
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
2025-05-31 17:15 ` [PATCH 01/27] qemu-img: measure: convert img_size to signed, simplify handling Michael Tokarev
2025-05-31 17:15 ` [PATCH 02/27] qemu-img: create: " Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 04/27] qemu-img: pass current cmd info into command handlers Michael Tokarev
` (27 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
In order to correctly print executable name in various
error messages, pass argv[0] to error_exit() function.
This way, error messages will refer to actual executable
name, which may be different from 'qemu-img'.
For subcommands, pass original command name from the
qemu-img argv[0], plus the subcommand name, as its own
argv[0] element, so error messages can be more useful.
Also don't require at least 3 options on the command
line: it makes no sense with options before subcommand.
Introduce tryhelp() function which just prints
try 'command-name --help' for more info
and exits. When tryhelp() is called from within a subcommand
handler, the message will look like:
try 'command-name subcommand --help' for more information
qemu-img uses getopt_long() with ':' as the first char in
optstring parameter, which means it doesn't print error
messages but return ':' or '?' instead, and qemu-img uses
unrecognized_option() or missing_argument() function to
print error messages. But it doesn't quite work:
$ ./qemu-img -xx
qemu-img: unrecognized option './qemu-img'
so the aim is to let getopt_long() to print regular error
messages instead (removing ':' prefix from optstring) and
remove handling of '?' and ':' "options" entirely. With
concatenated argv[0] and the subcommand, it all finally
does the right thing in all cases. This will be done in
subsequent changes command by command, with main() done
last.
unrecognized_option() and missing_argument() functions
prototypes aren't changed by this patch, since they're
called from many places and will be removed a few patches
later. Only artifical "qemu-img" argv0 is provided in
there for now.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img.c | 80 +++++++++++++++++++++++++++++-------------------------
1 file changed, 43 insertions(+), 37 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 974d31a4b3..4ece594360 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -101,8 +101,15 @@ static void format_print(void *opaque, const char *name)
printf(" %s", name);
}
-static G_NORETURN G_GNUC_PRINTF(1, 2)
-void error_exit(const char *fmt, ...)
+static G_NORETURN
+void tryhelp(const char *argv0)
+{
+ error_printf("Try '%s --help' for more information\n", argv0);
+ exit(EXIT_FAILURE);
+}
+
+static G_NORETURN G_GNUC_PRINTF(2, 3)
+void error_exit(const char *argv0, const char *fmt, ...)
{
va_list ap;
@@ -110,20 +117,19 @@ void error_exit(const char *fmt, ...)
error_vreport(fmt, ap);
va_end(ap);
- error_printf("Try 'qemu-img --help' for more information\n");
- exit(EXIT_FAILURE);
+ tryhelp(argv0);
}
static G_NORETURN
void missing_argument(const char *option)
{
- error_exit("missing argument for option '%s'", option);
+ error_exit("qemu-img", "missing argument for option '%s'", option);
}
static G_NORETURN
void unrecognized_option(const char *option)
{
- error_exit("unrecognized option '%s'", option);
+ error_exit("qemu-img", "unrecognized option '%s'", option);
}
/* Please keep in synch with docs/tools/qemu-img.rst */
@@ -576,7 +582,7 @@ static int img_create(int argc, char **argv)
}
if (optind >= argc) {
- error_exit("Expecting image file name");
+ error_exit(argv[0], "Expecting image file name");
}
optind++;
@@ -588,7 +594,7 @@ static int img_create(int argc, char **argv)
}
}
if (optind != argc) {
- error_exit("Unexpected argument: %s", argv[optind]);
+ error_exit(argv[0], "Unexpected argument: %s", argv[optind]);
}
bdrv_img_create(filename, fmt, base_filename, base_fmt,
@@ -770,7 +776,7 @@ static int img_check(int argc, char **argv)
} else if (!strcmp(optarg, "all")) {
fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
} else {
- error_exit("Unknown option value for -r "
+ error_exit(argv[0], "Unknown option value for -r "
"(expecting 'leaks' or 'all'): %s", optarg);
}
break;
@@ -795,7 +801,7 @@ static int img_check(int argc, char **argv)
}
}
if (optind != argc - 1) {
- error_exit("Expecting one image file name");
+ error_exit(argv[0], "Expecting one image file name");
}
filename = argv[optind++];
@@ -1025,7 +1031,7 @@ static int img_commit(int argc, char **argv)
}
if (optind != argc - 1) {
- error_exit("Expecting one image file name");
+ error_exit(argv[0], "Expecting one image file name");
}
filename = argv[optind++];
@@ -1446,7 +1452,7 @@ static int img_compare(int argc, char **argv)
if (optind != argc - 2) {
- error_exit("Expecting two image file names");
+ error_exit(argv[0], "Expecting two image file names");
}
filename1 = argv[optind++];
filename2 = argv[optind++];
@@ -3056,7 +3062,7 @@ static int img_info(int argc, char **argv)
}
}
if (optind != argc - 1) {
- error_exit("Expecting one image file name");
+ error_exit(argv[0], "Expecting one image file name");
}
filename = argv[optind++];
@@ -3296,7 +3302,7 @@ static int img_map(int argc, char **argv)
}
}
if (optind != argc - 1) {
- error_exit("Expecting one image file name");
+ error_exit(argv[0], "Expecting one image file name");
}
filename = argv[optind];
@@ -3411,7 +3417,7 @@ static int img_snapshot(int argc, char **argv)
return 0;
case 'l':
if (action) {
- error_exit("Cannot mix '-l', '-a', '-c', '-d'");
+ error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_LIST;
@@ -3419,7 +3425,7 @@ static int img_snapshot(int argc, char **argv)
break;
case 'a':
if (action) {
- error_exit("Cannot mix '-l', '-a', '-c', '-d'");
+ error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_APPLY;
@@ -3427,7 +3433,7 @@ static int img_snapshot(int argc, char **argv)
break;
case 'c':
if (action) {
- error_exit("Cannot mix '-l', '-a', '-c', '-d'");
+ error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_CREATE;
@@ -3435,7 +3441,7 @@ static int img_snapshot(int argc, char **argv)
break;
case 'd':
if (action) {
- error_exit("Cannot mix '-l', '-a', '-c', '-d'");
+ error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
action = SNAPSHOT_DELETE;
@@ -3457,7 +3463,7 @@ static int img_snapshot(int argc, char **argv)
}
if (optind != argc - 1) {
- error_exit("Expecting one image file name");
+ error_exit(argv[0], "Expecting one image file name");
}
filename = argv[optind++];
@@ -3624,10 +3630,11 @@ static int img_rebase(int argc, char **argv)
}
if (optind != argc - 1) {
- error_exit("Expecting one image file name");
+ error_exit(argv[0], "Expecting one image file name");
}
if (!unsafe && !out_baseimg) {
- error_exit("Must specify backing file (-b) or use unsafe mode (-u)");
+ error_exit(argv[0],
+ "Must specify backing file (-b) or use unsafe mode (-u)");
}
filename = argv[optind++];
@@ -4051,7 +4058,7 @@ static int img_resize(int argc, char **argv)
/* Remove size from argv manually so that negative numbers are not treated
* as options by getopt. */
if (argc < 3) {
- error_exit("Not enough arguments");
+ error_exit(argv[0], "Not enough arguments");
return 1;
}
@@ -4109,7 +4116,7 @@ static int img_resize(int argc, char **argv)
}
}
if (optind != argc - 1) {
- error_exit("Expecting image file name and size");
+ error_exit(argv[0], "Expecting image file name and size");
}
filename = argv[optind++];
@@ -4306,7 +4313,7 @@ static int img_amend(int argc, char **argv)
}
if (!options) {
- error_exit("Must specify options (-o)");
+ error_exit(argv[0], "Must specify options (-o)");
}
if (quiet) {
@@ -4672,7 +4679,7 @@ static int img_bench(int argc, char **argv)
}
if (optind != argc - 1) {
- error_exit("Expecting one image file name");
+ error_exit(argv[0], "Expecting one image file name");
}
filename = argv[argc - 1];
@@ -5562,9 +5569,6 @@ int main(int argc, char **argv)
module_call_init(MODULE_INIT_QOM);
bdrv_init();
- if (argc < 2) {
- error_exit("Not enough arguments");
- }
qemu_add_opts(&qemu_source_opts);
qemu_add_opts(&qemu_trace_opts);
@@ -5589,15 +5593,11 @@ int main(int argc, char **argv)
}
}
- cmdname = argv[optind];
-
- /* reset getopt_long scanning */
- argc -= optind;
- if (argc < 1) {
- return 0;
+ if (optind >= argc) {
+ error_exit(argv[0], "Not enough arguments");
}
- argv += optind;
- qemu_reset_optind();
+
+ cmdname = argv[optind];
if (!trace_init_backends()) {
exit(1);
@@ -5608,10 +5608,16 @@ int main(int argc, char **argv)
/* find the command */
for (cmd = img_cmds; cmd->name != NULL; cmd++) {
if (!strcmp(cmdname, cmd->name)) {
+ g_autofree char *argv0 = g_strdup_printf("%s %s", argv[0], cmdname);
+ /* reset options and getopt processing (incl return order) */
+ argv += optind;
+ argc -= optind;
+ qemu_reset_optind();
+ argv[0] = argv0;
return cmd->handler(argc, argv);
}
}
/* not found */
- error_exit("Command not found: %s", cmdname);
+ error_exit(argv[0], "Command not found: %s", cmdname);
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 04/27] qemu-img: pass current cmd info into command handlers
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (2 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 03/27] qemu-img: global option processing and error printing Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 05/27] qemu-img: create: refresh options/--help (short option change) Michael Tokarev
` (26 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
This info will be used to generate --help output.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
---
qemu-img.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 4ece594360..7e3350bb38 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -60,7 +60,7 @@
typedef struct img_cmd_t {
const char *name;
- int (*handler)(int argc, char **argv);
+ int (*handler)(const struct img_cmd_t *ccmd, int argc, char **argv);
} img_cmd_t;
enum {
@@ -514,7 +514,7 @@ static int64_t cvtnum(const char *name, const char *value)
return cvtnum_full(name, value, 0, INT64_MAX);
}
-static int img_create(int argc, char **argv)
+static int img_create(const img_cmd_t *ccmd, int argc, char **argv)
{
int c;
int64_t img_size = -1;
@@ -719,7 +719,7 @@ static int collect_image_check(BlockDriverState *bs,
* 3 - Check completed, image has leaked clusters, but is good otherwise
* 63 - Checks are not supported by the image format
*/
-static int img_check(int argc, char **argv)
+static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
{
int c, ret;
OutputFormat output_format = OFORMAT_HUMAN;
@@ -951,7 +951,7 @@ static void run_block_job(BlockJob *job, Error **errp)
}
}
-static int img_commit(int argc, char **argv)
+static int img_commit(const img_cmd_t *ccmd, int argc, char **argv)
{
int c, ret, flags;
const char *filename, *fmt, *cache, *base;
@@ -1358,7 +1358,7 @@ static int check_empty_sectors(BlockBackend *blk, int64_t offset,
* 1 - Images differ
* >1 - Error occurred
*/
-static int img_compare(int argc, char **argv)
+static int img_compare(const img_cmd_t *ccmd, int argc, char **argv)
{
const char *fmt1 = NULL, *fmt2 = NULL, *cache, *filename1, *filename2;
BlockBackend *blk1, *blk2;
@@ -2234,7 +2234,7 @@ static void set_rate_limit(BlockBackend *blk, int64_t rate_limit)
blk_set_io_limits(blk, &cfg);
}
-static int img_convert(int argc, char **argv)
+static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
{
int c, bs_i, flags, src_flags = BDRV_O_NO_SHARE;
const char *fmt = NULL, *out_fmt = NULL, *cache = "unsafe",
@@ -3002,7 +3002,7 @@ err:
return NULL;
}
-static int img_info(int argc, char **argv)
+static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
{
int c;
OutputFormat output_format = OFORMAT_HUMAN;
@@ -3227,7 +3227,7 @@ static inline bool entry_mergeable(const MapEntry *curr, const MapEntry *next)
return true;
}
-static int img_map(int argc, char **argv)
+static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
{
int c;
OutputFormat output_format = OFORMAT_HUMAN;
@@ -3376,7 +3376,7 @@ out:
#define SNAPSHOT_APPLY 3
#define SNAPSHOT_DELETE 4
-static int img_snapshot(int argc, char **argv)
+static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
{
BlockBackend *blk;
BlockDriverState *bs;
@@ -3534,7 +3534,7 @@ static int img_snapshot(int argc, char **argv)
return 0;
}
-static int img_rebase(int argc, char **argv)
+static int img_rebase(const img_cmd_t *ccmd, int argc, char **argv)
{
BlockBackend *blk = NULL, *blk_old_backing = NULL, *blk_new_backing = NULL;
uint8_t *buf_old = NULL;
@@ -4028,7 +4028,7 @@ out:
return 0;
}
-static int img_resize(int argc, char **argv)
+static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
{
Error *err = NULL;
int c, ret, relative;
@@ -4241,7 +4241,7 @@ static int print_amend_option_help(const char *format)
return 0;
}
-static int img_amend(int argc, char **argv)
+static int img_amend(const img_cmd_t *ccmd, int argc, char **argv)
{
Error *err = NULL;
int c, ret = 0;
@@ -4509,7 +4509,7 @@ static void bench_cb(void *opaque, int ret)
}
}
-static int img_bench(int argc, char **argv)
+static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
{
int c, ret = 0;
const char *fmt = NULL, *filename;
@@ -4779,7 +4779,7 @@ typedef struct ImgBitmapAction {
QSIMPLEQ_ENTRY(ImgBitmapAction) next;
} ImgBitmapAction;
-static int img_bitmap(int argc, char **argv)
+static int img_bitmap(const img_cmd_t *ccmd, int argc, char **argv)
{
Error *err = NULL;
int c, ret = 1;
@@ -5079,7 +5079,7 @@ static int img_dd_skip(const char *arg,
return 0;
}
-static int img_dd(int argc, char **argv)
+static int img_dd(const img_cmd_t *ccmd, int argc, char **argv)
{
int ret = 0;
char *arg = NULL;
@@ -5347,7 +5347,7 @@ static void dump_json_block_measure_info(BlockMeasureInfo *info)
g_string_free(str, true);
}
-static int img_measure(int argc, char **argv)
+static int img_measure(const img_cmd_t *ccmd, int argc, char **argv)
{
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
@@ -5614,7 +5614,7 @@ int main(int argc, char **argv)
argc -= optind;
qemu_reset_optind();
argv[0] = argv0;
- return cmd->handler(argc, argv);
+ return cmd->handler(cmd, argc, argv);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 05/27] qemu-img: create: refresh options/--help (short option change)
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (3 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 04/27] qemu-img: pass current cmd info into command handlers Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 06/27] qemu-img: factor out parse_output_format() and use it in the code Michael Tokarev
` (25 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Create helper function cmd_help() to display command-specific
help text, and use it to print --help for 'create' subcommand.
Add missing long options (eg --format) in img_create().
Recognize -B option for --backing-format, keep -F for
backward compatibility,
Reorder options for consistency.
Remove usage of missing_argument()/unrecognized_option() in
img_create().
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
docs/tools/qemu-img.rst | 10 ++---
qemu-img.c | 84 +++++++++++++++++++++++++++++++++--------
2 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 3653adb963..a21e439082 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -467,11 +467,11 @@ Command description:
``--skip-broken-bitmaps`` is also specified to copy only the
consistent bitmaps.
-.. option:: create [--object OBJECTDEF] [-q] [-f FMT] [-b BACKING_FILE [-F BACKING_FMT]] [-u] [-o OPTIONS] FILENAME [SIZE]
+.. option:: create [-f FMT] [-o FMT_OPTS] [-b BACKING_FILE [-B BACKING_FMT]] [-u] [-q] [--object OBJDEF] FILE [SIZE]
- Create the new disk image *FILENAME* of size *SIZE* and format
- *FMT*. Depending on the file format, you can add one or more *OPTIONS*
- that enable additional features of this format.
+ Create the new disk image *FILE* of size *SIZE* and format
+ *FMT*. Depending on the file format, you can add one or more *FMT_OPTS*
+ options that enable additional features of this format.
If the option *BACKING_FILE* is specified, then the image will record
only the differences from *BACKING_FILE*. No size needs to be specified in
@@ -479,7 +479,7 @@ Command description:
``commit`` monitor command (or ``qemu-img commit``).
If a relative path name is given, the backing file is looked up relative to
- the directory containing *FILENAME*.
+ the directory containing *FILE*.
Note that a given backing file will be opened to check that it is valid. Use
the ``-u`` option to enable unsafe backing file mode, which means that the
diff --git a/qemu-img.c b/qemu-img.c
index 7e3350bb38..cfc69e2503 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -132,6 +132,32 @@ void unrecognized_option(const char *option)
error_exit("qemu-img", "unrecognized option '%s'", option);
}
+/*
+ * Print --help output for a command and exit.
+ * @syntax and @description are multi-line with trailing EOL
+ * (to allow easy extending of the text)
+ * @syntax has each subsequent line indented by 8 chars.
+ * @description is indented by 2 chars for argument on each own line,
+ * and with 5 chars for argument description (like -h arg below).
+ */
+static G_NORETURN
+void cmd_help(const img_cmd_t *ccmd,
+ const char *syntax, const char *arguments)
+{
+ printf(
+"Usage:\n"
+"\n"
+" %s %s %s"
+"\n"
+"Arguments:\n"
+" -h, --help\n"
+" print this help and exit\n"
+"%s\n",
+ "qemu-img", ccmd->name,
+ syntax, arguments);
+ exit(EXIT_SUCCESS);
+}
+
/* Please keep in synch with docs/tools/qemu-img.rst */
static G_NORETURN
void help(void)
@@ -530,29 +556,46 @@ static int img_create(const img_cmd_t *ccmd, int argc, char **argv)
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
+ {"format", required_argument, 0, 'f'},
+ {"options", required_argument, 0, 'o'},
+ {"backing", required_argument, 0, 'b'},
+ {"backing-format", required_argument, 0, 'B'}, /* was -F in 10.0 */
+ {"backing-unsafe", no_argument, 0, 'u'},
+ {"quiet", no_argument, 0, 'q'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":F:b:f:ho:qu",
+ c = getopt_long(argc, argv, "hf:o:b:F:B:uq",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
- break;
- case 'F':
- base_fmt = optarg;
- break;
- case 'b':
- base_filename = optarg;
+ cmd_help(ccmd, "[-f FMT] [-o FMT_OPTS]\n"
+" [-b BACKING_FILE [-B BACKING_FMT]] [-u]\n"
+" [-q] [--object OBJDEF] FILE [SIZE]\n"
+,
+" -f, --format FMT\n"
+" specifies the format of the new image (default: raw)\n"
+" -o, --options FMT_OPTS\n"
+" format-specific options (specify '-o help' for help)\n"
+" -b, --backing BACKING_FILE\n"
+" create target image to be a CoW on top of BACKING_FILE\n"
+" -B, --backing-format BACKING_FMT (was -F in <= 10.0)\n"
+" specifies the format of BACKING_FILE (default: probing is used)\n"
+" -u, --backing-unsafe\n"
+" do not fail if BACKING_FILE can not be read\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file to create (will be overritten if already exists)\n"
+" SIZE[bKMGTPE]\n"
+" image size with optional multiplier suffix (powers of 1024)\n"
+" (required unless BACKING_FILE is specified)\n"
+);
break;
case 'f':
fmt = optarg;
@@ -562,15 +605,24 @@ static int img_create(const img_cmd_t *ccmd, int argc, char **argv)
goto fail;
}
break;
- case 'q':
- quiet = true;
+ case 'b':
+ base_filename = optarg;
+ break;
+ case 'F': /* <=10.0 */
+ case 'B':
+ base_fmt = optarg;
break;
case 'u':
flags |= BDRV_O_NO_BACKING;
break;
+ case 'q':
+ quiet = true;
+ break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 06/27] qemu-img: factor out parse_output_format() and use it in the code
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (4 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 05/27] qemu-img: create: refresh options/--help (short option change) Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 07/27] qemu-img: check: refresh options/--help Michael Tokarev
` (24 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
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>
---
qemu-img.c | 63 ++++++++++++++++--------------------------------------
1 file changed, 18 insertions(+), 45 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index cfc69e2503..a26498a4e8 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;
@@ -5471,15 +5452,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);
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 07/27] qemu-img: check: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (5 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 06/27] qemu-img: factor out parse_output_format() and use it in the code Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 08/27] qemu-img: simplify --repair error message Michael Tokarev
` (23 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 60 +++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 41 insertions(+), 19 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index a26498a4e8..2129158c13 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -805,31 +805,57 @@ static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"cache", required_argument, 0, 'T'},
{"repair", required_argument, 0, 'r'},
+ {"force-share", no_argument, 0, 'U'},
{"output", required_argument, 0, OPTION_OUTPUT},
+ {"quiet", no_argument, 0, 'q'},
{"object", required_argument, 0, OPTION_OBJECT},
- {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
- {"force-share", no_argument, 0, 'U'},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":hf:r:T:qU",
+ c = getopt_long(argc, argv, "hf:T:r:Uq",
long_options, &option_index);
if (c == -1) {
break;
}
switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
+ cmd_help(ccmd, "[-f FMT | --image-opts] [-T CACHE_MODE] [-r leaks|all]\n"
+" [-U] [--output human|json] [-q] [--object OBJDEF] FILE\n"
+,
+" -f, --format FMT\n"
+" specifies the format of the image explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -T, --cache CACHE_MODE\n" /* why not -t ? */
+" cache mode (default: " BDRV_DEFAULT_CACHE ")\n"
+" -r, --repair leaks|all\n"
+" repair errors of the given category in the image (image will be\n"
+" opened in read-write mode, incompatible with -U|--force-share)\n"
+" -U, --force-share\n"
+" open image in shared mode for concurrent access\n"
+" --output human|json\n"
+" output format (default: human)\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or an option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
break;
case 'f':
fmt = optarg;
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
+ case 'T':
+ cache = optarg;
+ break;
case 'r':
flags |= BDRV_O_RDWR;
@@ -842,24 +868,20 @@ static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
"(expecting 'leaks' or 'all'): %s", optarg);
}
break;
+ case 'U':
+ force_share = true;
+ break;
case OPTION_OUTPUT:
output_format = parse_output_format(argv[0], optarg);
break;
- case 'T':
- cache = optarg;
- break;
case 'q':
quiet = true;
break;
- case 'U':
- force_share = true;
- break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
if (optind != argc - 1) {
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 08/27] qemu-img: simplify --repair error message
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (6 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 07/27] qemu-img: check: refresh options/--help Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 09/27] qemu-img: commit: refresh options/--help Michael Tokarev
` (22 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
qemu-img.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 2129158c13..c8ce206b73 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -864,8 +864,9 @@ static int img_check(const img_cmd_t *ccmd, int argc, char **argv)
} else if (!strcmp(optarg, "all")) {
fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
} else {
- error_exit(argv[0], "Unknown option value for -r "
- "(expecting 'leaks' or 'all'): %s", optarg);
+ error_exit(argv[0],
+ "--repair (-r) expects 'leaks' or 'all' not '%s'",
+ optarg);
}
break;
case 'U':
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 09/27] qemu-img: commit: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (7 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 08/27] qemu-img: simplify --repair error message Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 10/27] qemu-img: compare: use helper function for --object Michael Tokarev
` (21 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 68 ++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 48 insertions(+), 20 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index c8ce206b73..5e651e8089 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1047,38 +1047,73 @@ static int img_commit(const img_cmd_t *ccmd, int argc, char **argv)
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"cache", required_argument, 0, 't'},
+ {"drop", no_argument, 0, 'd'},
+ {"base", required_argument, 0, 'b'},
+ {"rate-limit", required_argument, 0, 'r'},
+ {"progress", no_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":f:ht:b:dpqr:",
+ c = getopt_long(argc, argv, "hf:t:db:r:pq",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
+ cmd_help(ccmd, "[-f FMT | --image-opts] [-t CACHE_MODE] [-b BASE_IMG]\n"
+" [-d] [-r RATE] [-q] [--object OBJDEF] FILE\n"
+,
+" -f, --format FMT\n"
+" specify FILE image format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -t, --cache CACHE_MODE image cache mode (default: " BDRV_DEFAULT_CACHE ")\n"
+" -d, --drop\n"
+" skip emptying FILE on completion\n"
+" -b, --base BASE_IMG\n"
+" image in the backing chain to commit change to\n"
+" (default: immediate backing file; implies --drop)\n"
+" -r, --rate-limit RATE\n"
+" I/O rate limit, in bytes per second\n"
+" -p, --progress\n"
+" display progress information\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or an option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
break;
case 'f':
fmt = optarg;
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
case 't':
cache = optarg;
break;
+ case 'd':
+ drop = true;
+ break;
case 'b':
base = optarg;
/* -b implies -d */
drop = true;
break;
- case 'd':
- drop = true;
+ case 'r':
+ rate_limit = cvtnum("rate limit", optarg);
+ if (rate_limit < 0) {
+ return 1;
+ }
break;
case 'p':
progress = true;
@@ -1086,18 +1121,11 @@ static int img_commit(const img_cmd_t *ccmd, int argc, char **argv)
case 'q':
quiet = true;
break;
- case 'r':
- rate_limit = cvtnum("rate limit", optarg);
- if (rate_limit < 0) {
- return 1;
- }
- break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 10/27] qemu-img: compare: use helper function for --object
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (8 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 09/27] qemu-img: commit: refresh options/--help Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 11/27] qemu-img: compare: refresh options/--help Michael Tokarev
` (20 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Use the same function to parse --object as used by all
other qemu-img subcommands.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 16 ++--------------
1 file changed, 2 insertions(+), 14 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 5e651e8089..c24e1fb455 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1529,20 +1529,8 @@ static int img_compare(const img_cmd_t *ccmd, int argc, char **argv)
force_share = true;
break;
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;
- }
+ user_creatable_process_cmdline(optarg);
+ break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 11/27] qemu-img: compare: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (9 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 10/27] qemu-img: compare: use helper function for --object Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change) Michael Tokarev
` (19 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add long options, add help, reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 64 +++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 46 insertions(+), 18 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index c24e1fb455..70573b79b5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -1487,25 +1487,51 @@ static int img_compare(const img_cmd_t *ccmd, int argc, char **argv)
for (;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"a-format", required_argument, 0, 'f'},
+ {"b-format", required_argument, 0, 'F'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"strict", no_argument, 0, 's'},
+ {"cache", required_argument, 0, 'T'},
{"force-share", no_argument, 0, 'U'},
+ {"progress", no_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":hf:F:T:pqsU",
+ c = getopt_long(argc, argv, "hf:F:sT:Upq",
long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
+ cmd_help(ccmd,
+"[[-f FMT] [-F FMT] | --image-opts] [-s] [-T CACHE]\n"
+" [-U] [-p] [-q] [--object OBJDEF] FILE1 FILE2\n"
+,
+" -f, --a-format FMT\n"
+" specify FILE1 image format explicitly (default: probing is used)\n"
+" -F, --b-format FMT\n"
+" specify FILE2 image format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE1 and FILE2 as option strings (key=value,..), not file names\n"
+" (incompatible with -f|--a-format and -F|--b-format)\n"
+" -s, --strict\n"
+" strict mode, also check if sizes are equal\n"
+" -T, --cache CACHE_MODE\n"
+" images caching mode (default: " BDRV_DEFAULT_CACHE ")\n"
+" -U, --force-share\n"
+" open images in shared mode for concurrent access\n"
+" -p, --progress\n"
+" display progress information\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE1, FILE2\n"
+" names of the image files, or option strings (key=value,..)\n"
+" with --image-opts, to compare\n"
+);
break;
case 'f':
fmt1 = optarg;
@@ -1513,27 +1539,29 @@ static int img_compare(const img_cmd_t *ccmd, int argc, char **argv)
case 'F':
fmt2 = optarg;
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
+ case 's':
+ strict = true;
+ break;
case 'T':
cache = optarg;
break;
+ case 'U':
+ force_share = true;
+ break;
case 'p':
progress = true;
break;
case 'q':
quiet = true;
break;
- case 's':
- strict = true;
- break;
- case 'U':
- force_share = true;
- break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change)
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (10 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 11/27] qemu-img: compare: refresh options/--help Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 13/27] qemu-img: info: refresh options/--help Michael Tokarev
` (18 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output.
Reorder options for consistency.
Use -b for --backing, and recognize -B for backwards
compatibility. Unfortunately we can't use -B to
specify backing format.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
docs/tools/qemu-img.rst | 2 +-
qemu-img.c | 227 +++++++++++++++++++++++++++-------------
2 files changed, 156 insertions(+), 73 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index a21e439082..23715811e2 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -419,7 +419,7 @@ Command description:
4
Error on reading data
-.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps [--skip-broken-bitmaps]] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE [-F BACKING_FMT]] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
+.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps [--skip-broken-bitmaps]] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-b BACKING_FILE [-F BACKING_FMT]] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM*
to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can
diff --git a/qemu-img.c b/qemu-img.c
index 70573b79b5..5858304a62 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2390,53 +2390,119 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ /*XXX: use shorter --src-* and --tgt-*? or --out[put] not --target? */
+ {"source-format", required_argument, 0, 'f'},
+ /*XXX: make historic --image-opts to act on both source and target file? */
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
- {"force-share", no_argument, 0, 'U'},
- {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
- {"salvage", no_argument, 0, OPTION_SALVAGE},
- {"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO},
+ {"source-image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"source-cache", required_argument, 0, 'T'},
+ {"snapshot", required_argument, 0, 'l'},
{"bitmaps", no_argument, 0, OPTION_BITMAPS},
{"skip-broken-bitmaps", no_argument, 0, OPTION_SKIP_BROKEN},
+ {"salvage", no_argument, 0, OPTION_SALVAGE},
+ {"target-format", required_argument, 0, 'O'},
+ {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
+ {"target-format-options", required_argument, 0, 'o'},
+ {"target-cache", required_argument, 0, 't'},
+ {"backing", required_argument, 0, 'b'},
+ {"backing-format", required_argument, 0, 'F'},
+ {"sparse-size", required_argument, 0, 'S'},
+ {"no-create", no_argument, 0, 'n'},
+ {"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO},
+ {"force-share", no_argument, 0, 'U'},
+ {"rate-limit", required_argument, 0, 'r'},
+ {"parallel", required_argument, 0, 'm'},
+ {"oob-writes", no_argument, 0, 'W'},
+ {"copy-range-offloading", no_argument, 0, 'C'},
+ {"progress", no_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":hf:O:B:CcF:o:l:S:pt:T:qnm:WUr:",
+ c = getopt_long(argc, argv, "hf:O:b:B:CcF:o:l:S:pt:T:nm:WUr:q",
long_options, NULL);
if (c == -1) {
break;
}
- switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
+ switch (c) {
case 'h':
- help();
+ cmd_help(ccmd, "[-f SRC_FMT | --source-image-opts] [-T SRC_CACHE]\n"
+" [-l SNAPSHOT_PARAM] [--bitmaps [--skip-broken-bitmaps]] [--salvage]\n"
+" [-O TGT_FMT | --target-image-opts] [-o TGT_FMT_OPTS] [-t TGT_CACHE]\n"
+" [-b BACKING_FILE [-F BACKING_FMT]] [-S SPARSE_SIZE]\n"
+" [-n] [--target-is-zero] [-c]\n"
+" [-U] [-r RATE] [-m NUM_PARALLEL] [-W] [-C] [-p] [-q] [--object OBJDEF]\n"
+" SRC_FILE [SRC_FILE2...] TGT_FILE\n"
+,
+" -f, --source-format SRC_FMT\n"
+" specify format of all SRC_FILEs explicitly (default: probing is used)\n"
+" --source-image-opts (XXX was --image-opts, but it usually applies to both)\n"
+" treat each SRC_FILE as an option string (key=value,...), not a file name\n"
+" (incompatible with -f|--source-format)\n"
+" -T, --source-cache SRC_CACHE\n"
+" source image(s) cache mode (" BDRV_DEFAULT_CACHE ")\n"
+" -l, --snapshot SNAPSHOT_PARAMS\n"
+" specify source snapshot parameters\n"
+" --bitmaps\n"
+" also copy any persistent bitmaps present in source\n"
+" --skip-broken-bitmaps\n"
+" skip (do not error out) any broken bitmaps\n"
+" --salvage\n"
+" ignore errors on input (convert unreadable areas to zeros)\n"
+" -O, --target-format TGT_FMT\n"
+" specify TGT_FILE image format (default: raw)\n"
+" --target-image-opts\n"
+" treat TGT_FILE as an option string (key=value,...), not a file name\n"
+" (incompatible with -O|--target-format)\n"
+" -o, --target-format-options TGT_FMT_OPTS\n"
+" TGT_FMT-specific options\n"
+" -t, --target-cache TGT_CACHE\n"
+" cache mode when opening output image (default: unsafe)\n"
+" -b, --backing BACKING_FILE (was -B in <= 10.0)\n"
+" create target image to be a CoW on top of BACKING_FILE\n"
+" -F, --backing-format BACKING_FMT\n" /* -B used for -b in <=10.0 */
+" specify BACKING_FILE image format explicitly (default: probing is used)\n"
+" -S, --sparse-size SPARSE_SIZE[bkKMGTPE]\n"
+" specify number of consecutive zero bytes to treat as a gap on output\n"
+" (rounded down to nearest 512 bytes), with optional multiplier suffix\n"
+" -n, --no-create\n"
+" omit target volume creation (e.g. on rbd)\n"
+" --target-is-zero\n"
+" indicates that the target volume is pre-zeroed\n"
+" -c, --compress\n"
+" create compressed output image (qcow and qcow2 formats only)\n"
+" -U, --force-share\n"
+" open images in shared mode for concurrent access\n"
+" -r, --rate-limit RATE\n"
+" I/O rate limit, in bytes per second\n"
+" -m, --parallel NUM_PARALLEL\n"
+" specify parallelism (default: 8)\n"
+" -C, --copy-range-offloading\n"
+" try to use copy offloading\n"
+" -W, --oob-writes\n"
+" enable out-of-order writes to improve performance\n"
+" -p, --progress\n"
+" display progress information\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" SRC_FILE...\n"
+" one or more source image file names,\n"
+" or option strings (key=value,..) with --source-image-opts\n"
+" TGT_FILE\n"
+" target (output) image file name,\n"
+" or option string (key=value,..) with --target-image-opts\n"
+);
break;
case 'f':
fmt = optarg;
break;
- case 'O':
- out_fmt = optarg;
- break;
- case 'B':
- out_baseimg = optarg;
- break;
- case 'C':
- s.copy_range = true;
- break;
- case 'c':
- s.compressed = true;
- break;
- case 'F':
- backing_fmt = optarg;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
break;
- case 'o':
- if (accumulate_options(&options, optarg) < 0) {
- goto fail_getopt;
- }
+ case 'T':
+ src_cache = optarg;
break;
case 'l':
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
@@ -2451,6 +2517,36 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
snapshot_name = optarg;
}
break;
+ case OPTION_BITMAPS:
+ bitmaps = true;
+ break;
+ case OPTION_SKIP_BROKEN:
+ skip_broken = true;
+ break;
+ case OPTION_SALVAGE:
+ s.salvage = true;
+ break;
+ case 'O':
+ out_fmt = optarg;
+ break;
+ case OPTION_TARGET_IMAGE_OPTS:
+ tgt_image_opts = true;
+ break;
+ case 'o':
+ if (accumulate_options(&options, optarg) < 0) {
+ goto fail_getopt;
+ }
+ break;
+ case 't':
+ cache = optarg;
+ break;
+ case 'B': /* <=10.0 */
+ case 'b':
+ out_baseimg = optarg;
+ break;
+ case 'F': /* can't use -B as it used as -b in <=10.0 */
+ backing_fmt = optarg;
+ break;
case 'S':
{
int64_t sval;
@@ -2471,20 +2567,28 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
explict_min_sparse = true;
break;
}
- case 'p':
- progress = true;
+ case 'n':
+ skip_create = true;
break;
- case 't':
- cache = optarg;
+ case OPTION_TARGET_IS_ZERO:
+ /*
+ * The user asserting that the target is blank has the
+ * same effect as the target driver supporting zero
+ * initialisation.
+ */
+ s.has_zero_init = true;
break;
- case 'T':
- src_cache = optarg;
+ case 'c':
+ s.compressed = true;
break;
- case 'q':
- s.quiet = true;
+ case 'U':
+ force_share = true;
break;
- case 'n':
- skip_create = true;
+ case 'r':
+ rate_limit = cvtnum("rate limit", optarg);
+ if (rate_limit < 0) {
+ goto fail_getopt;
+ }
break;
case 'm':
if (qemu_strtol(optarg, NULL, 0, &s.num_coroutines) ||
@@ -2497,41 +2601,20 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
case 'W':
s.wr_in_order = false;
break;
- case 'U':
- force_share = true;
+ case 'C':
+ s.copy_range = true;
break;
- case 'r':
- rate_limit = cvtnum("rate limit", optarg);
- if (rate_limit < 0) {
- goto fail_getopt;
- }
+ case 'p':
+ progress = true;
+ break;
+ case 'q':
+ s.quiet = true;
break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
- case OPTION_SALVAGE:
- s.salvage = true;
- break;
- case OPTION_TARGET_IMAGE_OPTS:
- tgt_image_opts = true;
- break;
- case OPTION_TARGET_IS_ZERO:
- /*
- * The user asserting that the target is blank has the
- * same effect as the target driver supporting zero
- * initialisation.
- */
- s.has_zero_init = true;
- break;
- case OPTION_BITMAPS:
- bitmaps = true;
- break;
- case OPTION_SKIP_BROKEN:
- skip_broken = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 13/27] qemu-img: info: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (11 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change) Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-07-15 13:04 ` Kevin Wolf
2025-05-31 17:15 ` [PATCH 14/27] qemu-img: map: " Michael Tokarev
` (17 subsequent siblings)
30 siblings, 1 reply; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output.
Also add -b short option for --backing-chain, and remove
now-unused OPTION_BACKING_CHAIN.
Reorder options for consistency.
While at it, remove unused option_index variable.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 54 ++++++++++++++++++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 20 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 5858304a62..f0d04a874d 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -65,7 +65,6 @@ typedef struct img_cmd_t {
enum {
OPTION_OUTPUT = 256,
- OPTION_BACKING_CHAIN = 257,
OPTION_OBJECT = 258,
OPTION_IMAGE_OPTS = 259,
OPTION_PATTERN = 260,
@@ -3217,50 +3216,65 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
fmt = NULL;
for(;;) {
- int option_index = 0;
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
- {"output", required_argument, 0, OPTION_OUTPUT},
- {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
- {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"backing-chain", no_argument, 0, 'b'},
{"force-share", no_argument, 0, 'U'},
+ {"output", required_argument, 0, OPTION_OUTPUT},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":f:hU",
- long_options, &option_index);
+ c = getopt_long(argc, argv, "hf:bU",
+ long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
+ cmd_help(ccmd, "[-f FMT | --image-opts] [-b] [-U]"
+" [--output human|json] [--object OBJDEF] FILE\n"
+,
+" -f, --format FMT\n"
+" specify FILE image format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -b, --backing-chain\n"
+" display information about backing chaing\n"
+" in case the image is stacked\n"
+" -U, --force-share\n"
+" open image in shared mode for concurrent access\n"
+" --output human|json\n"
+" specify output format (default: human)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
break;
case 'f':
fmt = optarg;
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
+ case 'b':
+ chain = true;
+ break;
case 'U':
force_share = true;
break;
case OPTION_OUTPUT:
output_format = parse_output_format(argv[0], optarg);
break;
- case OPTION_BACKING_CHAIN:
- chain = true;
- break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
if (optind != argc - 1) {
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 14/27] qemu-img: map: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (12 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 13/27] qemu-img: info: refresh options/--help Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-07-15 13:07 ` Kevin Wolf
2025-05-31 17:15 ` [PATCH 15/27] qemu-img: snapshot: allow specifying -f fmt Michael Tokarev
` (16 subsequent siblings)
30 siblings, 1 reply; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
While at it, remove unused option_index variable.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 57 ++++++++++++++++++++++++++++++++++--------------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index f0d04a874d..f5820a7017 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3451,41 +3451,51 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
fmt = NULL;
for (;;) {
- int option_index = 0;
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
- {"output", required_argument, 0, OPTION_OUTPUT},
- {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
- {"force-share", no_argument, 0, 'U'},
{"start-offset", required_argument, 0, 's'},
{"max-length", required_argument, 0, 'l'},
+ {"force-share", no_argument, 0, 'U'},
+ {"output", required_argument, 0, OPTION_OUTPUT},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":f:s:l:hU",
- long_options, &option_index);
+ c = getopt_long(argc, argv, "hf:s:l:U",
+ long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
+ cmd_help(ccmd, "[-f FMT | --image-opts]\n"
+" [--start-offset OFFSET] [--max-length LENGTH]\n"
+" [--output human|json] [-U] [--object OBJDEF] FILE\n"
+,
+" -f, --format FMT\n"
+" specify FILE image format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" --start-offset OFFSET\n"
+" --max-length LENGTH\n"
+" --output human|json\n"
+" specify output format name (default: human)\n"
+" -U, --force-share\n"
+" open image in shared mode for concurrent access\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" the image file name, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
break;
case 'f':
fmt = optarg;
break;
- case 'U':
- force_share = true;
- break;
- case OPTION_OUTPUT:
- output_format = parse_output_format(argv[0], optarg);
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
break;
case 's':
start_offset = cvtnum("start offset", optarg);
@@ -3499,12 +3509,17 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
return 1;
}
break;
+ case OPTION_OUTPUT:
+ output_format = parse_output_format(argv[0], optarg);
+ break;
+ case 'U':
+ force_share = true;
+ break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
if (optind != argc - 1) {
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 15/27] qemu-img: snapshot: allow specifying -f fmt
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (13 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 14/27] qemu-img: map: " Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 16/27] qemu-img: snapshot: make -l (list) the default, simplify option handling Michael Tokarev
` (15 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
For consistency with other commands, and since it already
accepts --image-opts, allow specifying -f fmt too.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
docs/tools/qemu-img.rst | 2 +-
qemu-img-cmds.hx | 4 ++--
qemu-img.c | 9 ++++++---
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 23715811e2..935f28bbc5 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -663,7 +663,7 @@ Command description:
bitmap support, or 0 if bitmaps are supported but there is nothing
to copy.
-.. option:: snapshot [--object OBJECTDEF] [--image-opts] [-U] [-q] [-l | -a SNAPSHOT | -c SNAPSHOT | -d SNAPSHOT] FILENAME
+.. option:: snapshot [--object OBJECTDEF] [-f FMT | --image-opts] [-U] [-q] [-l | -a SNAPSHOT | -c SNAPSHOT | -d SNAPSHOT] FILENAME
List, apply, create or delete snapshots in image *FILENAME*.
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index c9dd70a892..2c5a8a28f9 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -84,9 +84,9 @@ SRST
ERST
DEF("snapshot", img_snapshot,
- "snapshot [--object objectdef] [--image-opts] [-U] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
+ "snapshot [--object objectdef] [-f fmt | --image-opts] [-U] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
SRST
-.. option:: snapshot [--object OBJECTDEF] [--image-opts] [-U] [-q] [-l | -a SNAPSHOT | -c SNAPSHOT | -d SNAPSHOT] FILENAME
+.. option:: snapshot [--object OBJECTDEF] [-f FMT | --image-opts] [-U] [-q] [-l | -a SNAPSHOT | -c SNAPSHOT | -d SNAPSHOT] FILENAME
ERST
DEF("rebase", img_rebase,
diff --git a/qemu-img.c b/qemu-img.c
index f5820a7017..38352e54ad 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3593,7 +3593,7 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
BlockBackend *blk;
BlockDriverState *bs;
QEMUSnapshotInfo sn;
- char *filename, *snapshot_name = NULL;
+ char *filename, *fmt = NULL, *snapshot_name = NULL;
int c, ret = 0, bdrv_oflags;
int action = 0;
bool quiet = false;
@@ -3612,7 +3612,7 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
{"force-share", no_argument, 0, 'U'},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":la:c:d:hqU",
+ c = getopt_long(argc, argv, ":la:c:d:f:hqU",
long_options, NULL);
if (c == -1) {
break;
@@ -3627,6 +3627,9 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
case 'h':
help();
return 0;
+ case 'f':
+ fmt = optarg;
+ break;
case 'l':
if (action) {
error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
@@ -3680,7 +3683,7 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
filename = argv[optind++];
/* Open the image */
- blk = img_open(image_opts, filename, NULL, bdrv_oflags, false, quiet,
+ blk = img_open(image_opts, filename, fmt, bdrv_oflags, false, quiet,
force_share);
if (!blk) {
return 1;
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 16/27] qemu-img: snapshot: make -l (list) the default, simplify option handling
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (14 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 15/27] qemu-img: snapshot: allow specifying -f fmt Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 17/27] qemu-img: snapshot: refresh options/--help Michael Tokarev
` (14 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
When no -l/-a/-c/-d specified, assume -l (list).
Use the same values for SNAPSHOT_LIST/etc constants as the
option chars (lacd), this makes it possible to simplify
option handling a lot, combining cases for 4 options into
one.
Also remove bdrv_oflags handling (only list can use RO mode).
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
docs/tools/qemu-img.rst | 2 +-
qemu-img.c | 52 ++++++++++++++---------------------------
2 files changed, 19 insertions(+), 35 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index 935f28bbc5..a346988292 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -256,7 +256,7 @@ Parameters to snapshot subcommand:
.. option:: -l
- Lists all snapshots in the given image
+ Lists all snapshots in the given image (default action)
Command description:
diff --git a/qemu-img.c b/qemu-img.c
index 38352e54ad..8fbf0c67a7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3583,10 +3583,11 @@ out:
return ret < 0;
}
-#define SNAPSHOT_LIST 1
-#define SNAPSHOT_CREATE 2
-#define SNAPSHOT_APPLY 3
-#define SNAPSHOT_DELETE 4
+/* the same as options */
+#define SNAPSHOT_LIST 'l'
+#define SNAPSHOT_CREATE 'c'
+#define SNAPSHOT_APPLY 'a'
+#define SNAPSHOT_DELETE 'd'
static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
{
@@ -3594,7 +3595,7 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
BlockDriverState *bs;
QEMUSnapshotInfo sn;
char *filename, *fmt = NULL, *snapshot_name = NULL;
- int c, ret = 0, bdrv_oflags;
+ int c, ret = 0;
int action = 0;
bool quiet = false;
Error *err = NULL;
@@ -3602,7 +3603,6 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
bool force_share = false;
int64_t rt;
- bdrv_oflags = BDRV_O_RDWR;
/* Parse commandline parameters */
for(;;) {
static const struct option long_options[] = {
@@ -3630,36 +3630,15 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
case 'f':
fmt = optarg;
break;
- case 'l':
- if (action) {
- error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
- return 0;
- }
- action = SNAPSHOT_LIST;
- bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
- break;
- case 'a':
+ case SNAPSHOT_LIST:
+ case SNAPSHOT_APPLY:
+ case SNAPSHOT_CREATE:
+ case SNAPSHOT_DELETE:
if (action) {
error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
return 0;
}
- action = SNAPSHOT_APPLY;
- snapshot_name = optarg;
- break;
- case 'c':
- if (action) {
- error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
- return 0;
- }
- action = SNAPSHOT_CREATE;
- snapshot_name = optarg;
- break;
- case 'd':
- if (action) {
- error_exit(argv[0], "Cannot mix '-l', '-a', '-c', '-d'");
- return 0;
- }
- action = SNAPSHOT_DELETE;
+ action = c;
snapshot_name = optarg;
break;
case 'q':
@@ -3682,9 +3661,14 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
}
filename = argv[optind++];
+ if (!action) {
+ action = SNAPSHOT_LIST;
+ }
+
/* Open the image */
- blk = img_open(image_opts, filename, fmt, bdrv_oflags, false, quiet,
- force_share);
+ blk = img_open(image_opts, filename, fmt,
+ action == SNAPSHOT_LIST ? 0 : BDRV_O_RDWR,
+ false, quiet, force_share);
if (!blk) {
return 1;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 17/27] qemu-img: snapshot: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (15 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 16/27] qemu-img: snapshot: make -l (list) the default, simplify option handling Michael Tokarev
@ 2025-05-31 17:15 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 18/27] qemu-img: rebase: refresh options/--help (short option change) Michael Tokarev
` (13 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:15 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 60 +++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 16 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 8fbf0c67a7..0774529383 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3607,29 +3607,58 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"list", no_argument, 0, SNAPSHOT_LIST},
+ {"apply", required_argument, 0, SNAPSHOT_APPLY},
+ {"create", required_argument, 0, SNAPSHOT_CREATE},
+ {"delete", required_argument, 0, SNAPSHOT_DELETE},
{"force-share", no_argument, 0, 'U'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":la:c:d:f:hqU",
+ c = getopt_long(argc, argv, "hf:la:c:d:Uq",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
- return 0;
+ cmd_help(ccmd, "[-f FMT | --image-opts] [-l | -a|-c|-d SNAPSHOT]\n"
+" [-U] [-q] [--object OBJDEF] FILE\n"
+,
+" -f, --format FMT\n"
+" specify FILE format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -l, --list\n"
+" list snapshots in FILE (default action if no -l|-c|-a|-d is given)\n"
+" -c, --create SNAPSHOT\n"
+" create named snapshot\n"
+" -a, --apply SNAPSHOT\n"
+" apply named snapshot to the base\n"
+" -d, --delete SNAPSHOT\n"
+" delete named snapshot\n"
+" (only one of -l|-c|-a|-d can be specified)\n"
+" -U, --force-share\n"
+" open image in shared mode for concurrent access\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or option string (key=value,..)\n"
+" with --image-opts) to operate on\n"
+);
+ break;
case 'f':
fmt = optarg;
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
case SNAPSHOT_LIST:
case SNAPSHOT_APPLY:
case SNAPSHOT_CREATE:
@@ -3641,18 +3670,17 @@ static int img_snapshot(const img_cmd_t *ccmd, int argc, char **argv)
action = c;
snapshot_name = optarg;
break;
- case 'q':
- quiet = true;
- break;
case 'U':
force_share = true;
break;
+ case 'q':
+ quiet = true;
+ break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 18/27] qemu-img: rebase: refresh options/--help (short option change)
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (16 preceding siblings ...)
2025-05-31 17:15 ` [PATCH 17/27] qemu-img: snapshot: refresh options/--help Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 19/27] qemu-img: resize: do not always eat last argument Michael Tokarev
` (12 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Use -B for --backing-format, keep -F for
backwards compatibility.
Options added:
--format, --cache - for the image in question
--backing, --backing-format, --backing-cache, --backing-unsafe -
for the new backing file
(was eg CACHE vs SRC_CACHE, which is unclear).
Probably should rename local variables.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
docs/tools/qemu-img.rst | 2 +-
qemu-img.c | 88 +++++++++++++++++++++++++++++------------
2 files changed, 64 insertions(+), 26 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index a346988292..5e7b85079d 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -667,7 +667,7 @@ Command description:
List, apply, create or delete snapshots in image *FILENAME*.
-.. option:: rebase [--object OBJECTDEF] [--image-opts] [-U] [-q] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-p] [-u] [-c] -b BACKING_FILE [-F BACKING_FMT] FILENAME
+.. option:: rebase [--object OBJECTDEF] [--image-opts] [-U] [-q] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-p] [-u] [-c] -b BACKING_FILE [-B BACKING_FMT] FILENAME
Changes the backing file of an image. Only the formats ``qcow2`` and
``qed`` support changing the backing file.
diff --git a/qemu-img.c b/qemu-img.c
index 0774529383..08b37ed486 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3792,45 +3792,90 @@ static int img_rebase(const img_cmd_t *ccmd, int argc, char **argv)
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
- {"force-share", no_argument, 0, 'U'},
+ {"cache", required_argument, 0, 't'},
{"compress", no_argument, 0, 'c'},
+ {"backing", required_argument, 0, 'b'},
+ {"backing-format", required_argument, 0, 'B'},
+ {"backing-cache", required_argument, 0, 'T'},
+ {"backing-unsafe", no_argument, 0, 'u'},
+ {"force-share", no_argument, 0, 'U'},
+ {"progress", no_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":hf:F:b:upt:T:qUc",
+ c = getopt_long(argc, argv, "hf:t:cb:F:B:T:uUpq",
long_options, NULL);
if (c == -1) {
break;
}
- switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
+ switch (c) {
case 'h':
- help();
+ cmd_help(ccmd, "[-f FMT | --image-opts] [-t CACHE]\n"
+" [-b BACKING_FILE [-B BACKING_FMT] [-T BACKING_CACHE]] [-u]\n"
+" [-c] [-U] [-p] [-q] [--object OBJDEF] FILE\n"
+"Rebases FILE on top of BACKING_FILE or no backing file\n"
+,
+" -f, --format FMT\n"
+" specify FILE format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -t, --cache CACHE\n"
+" cache mode for FILE (default: " BDRV_DEFAULT_CACHE ")\n"
+" -b, --backing BACKING_FILE|\"\"\n"
+" rebase onto this file (specify empty name for no backing file)\n"
+" -B, --backing-format BACKING_FMT (was -F in <=10.0)\n"
+" specify format for BACKING_FILE explicitly (default: probing is used)\n"
+" -T, --backing-cache CACHE\n"
+" BACKING_FILE cache mode (default: " BDRV_DEFAULT_CACHE ")\n"
+" -u, --backing-unsafe\n"
+" do not fail if BACKING_FILE can not be read\n"
+" -c, --compress\n"
+" compress image (when image supports this)\n"
+" -U, --force-share\n"
+" open image in shared mode for concurrent access\n"
+" -p, --progress\n"
+" display progress information\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
return 0;
case 'f':
fmt = optarg;
break;
- case 'F':
- out_basefmt = optarg;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
+ case 't':
+ cache = optarg;
break;
case 'b':
out_baseimg = optarg;
break;
+ case 'F': /* <=10.0 */
+ case 'B':
+ out_basefmt = optarg;
+ break;
case 'u':
unsafe = 1;
break;
+ case 'c':
+ compress = true;
+ break;
+ case 'U':
+ force_share = true;
+ break;
case 'p':
progress = 1;
break;
- case 't':
- cache = optarg;
- break;
case 'T':
src_cache = optarg;
break;
@@ -3840,15 +3885,8 @@ static int img_rebase(const img_cmd_t *ccmd, int argc, char **argv)
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
- case 'U':
- force_share = true;
- break;
- case 'c':
- compress = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 19/27] qemu-img: resize: do not always eat last argument
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (17 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 18/27] qemu-img: rebase: refresh options/--help (short option change) Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 20/27] qemu-img: resize: refresh options/--help Michael Tokarev
` (11 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
'qemu-img resize --help' does not work, since it wants more
arguments. Also -size is only recognized as a very last
argument, but it is common for tools to handle other options
after positional arguments too.
Tell getopt_long() to return non-options together with options,
and process filename and size in the loop, and check if there's
an argument right after filename which looks like -N (number),
and treat it as size (decrement). This way we can handle --help,
and we can also have options after filename and size, and `--'
will be handled fine too.
The only case which is not handled right is when there's an option
between filename and size, and size is given as decrement, - in
this case -size will be treated as option, not as size.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 41 +++++++++++++++++++++++++++--------------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 08b37ed486..f655c301af 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4297,7 +4297,7 @@ static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
{
Error *err = NULL;
int c, ret, relative;
- const char *filename, *fmt, *size;
+ const char *filename = NULL, *fmt = NULL, *size = NULL;
int64_t n, total_size, current_size;
bool quiet = false;
BlockBackend *blk = NULL;
@@ -4320,17 +4320,7 @@ static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
bool image_opts = false;
bool shrink = false;
- /* Remove size from argv manually so that negative numbers are not treated
- * as options by getopt. */
- if (argc < 3) {
- error_exit(argv[0], "Not enough arguments");
- return 1;
- }
-
- size = argv[--argc];
-
/* Parse getopt arguments */
- fmt = NULL;
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
@@ -4340,7 +4330,7 @@ static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
{"shrink", no_argument, 0, OPTION_SHRINK},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":f:hq",
+ c = getopt_long(argc, argv, "-:f:hq",
long_options, NULL);
if (c == -1) {
break;
@@ -4378,12 +4368,35 @@ static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
case OPTION_SHRINK:
shrink = true;
break;
+ case 1: /* a non-optional argument */
+ if (!filename) {
+ filename = optarg;
+ /* see if we have -size (number) next to filename */
+ if (optind < argc) {
+ size = argv[optind];
+ if (size[0] == '-' && size[1] >= '0' && size[1] <= '9') {
+ ++optind;
+ } else {
+ size = NULL;
+ }
+ }
+ } else if (!size) {
+ size = optarg;
+ } else {
+ error_exit(argv[0], "Extra argument(s) in command line");
+ }
+ break;
}
}
- if (optind != argc - 1) {
+ if (!filename && optind < argc) {
+ filename = argv[optind++];
+ }
+ if (!size && optind < argc) {
+ size = argv[optind++];
+ }
+ if (!filename || !size || optind < argc) {
error_exit(argv[0], "Expecting image file name and size");
}
- filename = argv[optind++];
/* Choose grow, shrink, or absolute resize mode */
switch (size[0]) {
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 20/27] qemu-img: resize: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (18 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 19/27] qemu-img: resize: do not always eat last argument Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 21/27] qemu-img: amend: " Michael Tokarev
` (10 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 52 ++++++++++++++++++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 16 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index f655c301af..3dbfce527b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4324,36 +4324,48 @@ static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"preallocation", required_argument, 0, OPTION_PREALLOCATION},
{"shrink", no_argument, 0, OPTION_SHRINK},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "-:f:hq",
+ c = getopt_long(argc, argv, "-hf:q",
long_options, NULL);
if (c == -1) {
break;
}
switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
- break;
+ cmd_help(ccmd, "[-f FMT | --image-opts] [--preallocation PREALLOC] [--shrink]\n"
+" [-q] [--object OBJDEF] FILE [+-]SIZE[bkKMGTPE]\n"
+,
+" -f, --format FMT\n"
+" specify FILE format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,...), not a file name\n"
+" (incompatible with -f|--format)\n"
+" --shrink\n"
+" allow operation when the new size is smaller than the original\n"
+" --preallocation PREALLOC\n"
+" specify FMT-specific preallocation type for the new areas\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+" [+-]SIZE[bkKMGTPE]\n"
+" new image size or amount by which to shrink (-)/grow (+),\n"
+" with optional multiplier suffix (powers of 1024, default is bytes)\n"
+);
+ return 0;
case 'f':
fmt = optarg;
break;
- case 'q':
- quiet = true;
- break;
- case OPTION_OBJECT:
- user_creatable_process_cmdline(optarg);
- break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
@@ -4368,6 +4380,12 @@ static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
case OPTION_SHRINK:
shrink = true;
break;
+ case 'q':
+ quiet = true;
+ break;
+ case OPTION_OBJECT:
+ user_creatable_process_cmdline(optarg);
+ break;
case 1: /* a non-optional argument */
if (!filename) {
filename = optarg;
@@ -4386,6 +4404,8 @@ static int img_resize(const img_cmd_t *ccmd, int argc, char **argv)
error_exit(argv[0], "Extra argument(s) in command line");
}
break;
+ default:
+ tryhelp(argv[0]);
}
}
if (!filename && optind < argc) {
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 21/27] qemu-img: amend: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (19 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 20/27] qemu-img: resize: refresh options/--help Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 22/27] qemu-img: bench: " Michael Tokarev
` (9 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 54 +++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 39 insertions(+), 15 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 3dbfce527b..0d4bdc5df5 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4559,26 +4559,48 @@ static int img_amend(const img_cmd_t *ccmd, int argc, char **argv)
for (;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"options", required_argument, 0, 'o'},
+ {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"cache", required_argument, 0, 't'},
{"force", no_argument, 0, OPTION_FORCE},
+ {"progress", no_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":ho:f:t:pq",
+ c = getopt_long(argc, argv, "ho:f:t:pq",
long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
+ cmd_help(ccmd, "-o FMT_OPTS [-f FMT | --image-opts]\n"
+" [-t CACHE] [--force] [-p] [-q] [--object OBJDEF] FILE\n"
+,
+" -o, --options FMT_OPTS\n"
+" FMT-specfic format options (required)\n"
+" -f, --format FMT\n"
+" specify FILE format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -t, --cache CACHE\n"
+" cache mode for FILE (default: " BDRV_DEFAULT_CACHE ")\n"
+" --force\n"
+" allow certain unsafe operations\n"
+" -p, --progres\n"
+" show operation progress\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
break;
case 'o':
if (accumulate_options(&options, optarg) < 0) {
@@ -4589,9 +4611,15 @@ static int img_amend(const img_cmd_t *ccmd, int argc, char **argv)
case 'f':
fmt = optarg;
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
case 't':
cache = optarg;
break;
+ case OPTION_FORCE:
+ force = true;
+ break;
case 'p':
progress = true;
break;
@@ -4601,12 +4629,8 @@ static int img_amend(const img_cmd_t *ccmd, int argc, char **argv)
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
- case OPTION_FORCE:
- force = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 22/27] qemu-img: bench: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (20 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 21/27] qemu-img: amend: " Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 23/27] qemu-img: bitmap: " Michael Tokarev
` (8 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Add missing --object option.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 112 +++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 84 insertions(+), 28 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 0d4bdc5df5..5011ec5fce 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -4859,28 +4859,93 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
for (;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"flush-interval", required_argument, 0, OPTION_FLUSH_INTERVAL},
+ {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"cache", required_argument, 0, 't'},
+ {"count", required_argument, 0, 'c'},
+ {"depth", required_argument, 0, 'd'},
+ {"offset", required_argument, 0, 'o'},
+ {"buffer-size", required_argument, 0, 's'},
+ {"step-size", required_argument, 0, 'S'},
+ {"write", no_argument, 0, 'w'},
{"pattern", required_argument, 0, OPTION_PATTERN},
+ {"flush-interval", required_argument, 0, OPTION_FLUSH_INTERVAL},
{"no-drain", no_argument, 0, OPTION_NO_DRAIN},
+ {"aio", required_argument, 0, 'i'},
+ {"native", no_argument, 0, 'n'},
{"force-share", no_argument, 0, 'U'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":hc:d:f:ni:o:qs:S:t:wU", long_options,
- NULL);
+ c = getopt_long(argc, argv, "hf:t:c:d:o:s:S:wi:nUq",
+ long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case ':':
- missing_argument(argv[optind - 1]);
+ case 'h':
+ cmd_help(ccmd, "[-f FMT | --image-opts] [-t CACHE]\n"
+" [-c COUNT] [-d DEPTH] [-o OFFSET] [-s BUFFER_SIZE] [-S STEP_SIZE]\n"
+" [-w [--pattern PATTERN] [--flush-interval INTERVAL [--no-drain]]]\n"
+" [-i AIO] [-n] [-U] [-q] FILE\n"
+,
+" -f, --format FMT\n"
+" specify FILE format explicitly\n"
+" --image-opts\n"
+" indicates that FILE is a complete image specification\n"
+" instead of a file name (incompatible with --format)\n"
+" -t, --cache CACHE\n"
+" cache mode for FILE (default: " BDRV_DEFAULT_CACHE ")\n"
+" -c, --count COUNT\n"
+" number of I/O requests to perform\n"
+" -d, --depth DEPTH\n"
+" number of requests to perform in parallel\n"
+" -o, --offset OFFSET\n"
+" start first request at this OFFSET\n"
+" -s, --buffer-size BUFFER_SIZE[bkKMGTPE]\n"
+" size of each I/O request, with optional multiplier suffix\n"
+" (powers of 1024, default is 4K)\n"
+" -S, --step-size STEP_SIZE[bkKMGTPE]\n"
+" each next request offset increment, with optional multiplier suffix\n"
+" (powers of 1024, default is the same as BUFFER_SIZE)\n"
+" -w, --write\n"
+" perform write test (default is read)\n"
+" --pattern PATTERN\n"
+" write this pattern byte instead of zero\n"
+" --flush-interval FLUSH_INTERVAL\n"
+" issue flush after this number of requests\n"
+" --no-drain\n"
+" do not wait when flushing pending requests\n"
+" -i, --aio AIO\n"
+" async-io backend (threads, native, io_uring)\n"
+" -n, --native\n"
+" use native AIO backend if possible\n"
+" -U, --force-share\n"
+" open images in shared mode for concurrent access\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
break;
- case '?':
- unrecognized_option(argv[optind - 1]);
+ case 'f':
+ fmt = optarg;
break;
- case 'h':
- help();
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
+ case 't':
+ ret = bdrv_parse_cache_mode(optarg, &flags, &writethrough);
+ if (ret < 0) {
+ error_report("Invalid cache mode");
+ ret = -1;
+ goto out;
+ }
break;
case 'c':
{
@@ -4904,9 +4969,6 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
depth = res;
break;
}
- case 'f':
- fmt = optarg;
- break;
case 'n':
flags |= BDRV_O_NATIVE_AIO;
break;
@@ -4927,9 +4989,6 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
break;
}
break;
- case 'q':
- quiet = true;
- break;
case 's':
{
int64_t sval;
@@ -4954,21 +5013,10 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
step = sval;
break;
}
- case 't':
- ret = bdrv_parse_cache_mode(optarg, &flags, &writethrough);
- if (ret < 0) {
- error_report("Invalid cache mode");
- ret = -1;
- goto out;
- }
- break;
case 'w':
flags |= BDRV_O_RDWR;
is_write = true;
break;
- case 'U':
- force_share = true;
- break;
case OPTION_PATTERN:
{
unsigned long res;
@@ -4994,9 +5042,17 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
case OPTION_NO_DRAIN:
drain_on_flush = false;
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
+ case 'U':
+ force_share = true;
break;
+ case 'q':
+ quiet = true;
+ break;
+ case OPTION_OBJECT:
+ user_creatable_process_cmdline(optarg);
+ break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 23/27] qemu-img: bitmap: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (21 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 22/27] qemu-img: bench: " Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 24/27] qemu-img: dd: " Michael Tokarev
` (7 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 80 ++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 56 insertions(+), 24 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 5011ec5fce..97ce51a1c3 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -5179,48 +5179,69 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, char **argv)
for (;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"format", required_argument, 0, 'f'},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{"add", no_argument, 0, OPTION_ADD},
+ {"granularity", required_argument, 0, 'g'},
{"remove", no_argument, 0, OPTION_REMOVE},
{"clear", no_argument, 0, OPTION_CLEAR},
{"enable", no_argument, 0, OPTION_ENABLE},
{"disable", no_argument, 0, OPTION_DISABLE},
{"merge", required_argument, 0, OPTION_MERGE},
- {"granularity", required_argument, 0, 'g'},
{"source-file", required_argument, 0, 'b'},
{"source-format", required_argument, 0, 'F'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":b:f:F:g:h", long_options, NULL);
+ c = getopt_long(argc, argv, "hf:g:b:F:",
+ long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
- break;
- case 'b':
- src_filename = optarg;
+ cmd_help(ccmd, "[-f FMT | --image-opts]\n"
+" ( --add [-g SIZE] | --remove | --clear | --enable | --disable |\n"
+" --merge SOURCE [-b SRC_FILE [-F SRC_FMT]] )..\n"
+" [--object OBJDEF] FILE BITMAP\n"
+,
+" -f, --format FMT\n"
+" specify FILE format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" --add\n"
+" creates BITMAP in FILE, enables to record future edits\n"
+" -g, --granularity SIZE[bKMGTPE]\n"
+" sets non-default granularity for the bitmap being added,\n"
+" with optional multiplier suffix (in powers of 1024)\n"
+" --remove\n"
+" removes BITMAP from FILE\n"
+" --clear\n"
+" clears BITMAP in FILE\n"
+" --enable, --disable\n"
+" starts and stops recording future edits to BITMAP in FILE\n"
+" --merge SOURCE\n"
+" merges contents of the SOURCE bitmap into BITMAP in FILE\n"
+" -b, --source-file SRC_FILE\n"
+" select alternative source file for --merge\n"
+" -F, --source-format SRC_FMT\n"
+" specify format for SRC_FILE explicitly\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" name of the image file, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+" BITMAP\n"
+" name of the bitmap to add, remove, clear, enable, disable or merge to\n"
+);
break;
case 'f':
fmt = optarg;
break;
- case 'F':
- src_fmt = optarg;
- break;
- case 'g':
- granularity = cvtnum("granularity", optarg);
- if (granularity < 0) {
- return 1;
- }
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
break;
case OPTION_ADD:
act = g_new0(ImgBitmapAction, 1);
@@ -5228,6 +5249,12 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, char **argv)
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
add = true;
break;
+ case 'g':
+ granularity = cvtnum("granularity", optarg);
+ if (granularity < 0) {
+ return 1;
+ }
+ break;
case OPTION_REMOVE:
act = g_new0(ImgBitmapAction, 1);
act->act = BITMAP_REMOVE;
@@ -5255,12 +5282,17 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, char **argv)
QSIMPLEQ_INSERT_TAIL(&actions, act, next);
merge = true;
break;
+ case 'b':
+ src_filename = optarg;
+ break;
+ case 'F':
+ src_fmt = optarg;
+ break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 24/27] qemu-img: dd: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (22 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 23/27] qemu-img: bitmap: " Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 25/27] qemu-img: measure: " Michael Tokarev
` (6 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 50 ++++++++++++++++++++++++++++++++++++--------------
1 file changed, 36 insertions(+), 14 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 97ce51a1c3..3220c95e3c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -5533,31 +5533,54 @@ static int img_dd(const img_cmd_t *ccmd, int argc, char **argv)
};
const struct option long_options[] = {
{ "help", no_argument, 0, 'h'},
- { "object", required_argument, 0, OPTION_OBJECT},
+ { "format", required_argument, 0, 'f'},
{ "image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ { "output-format", required_argument, 0, 'O'},
{ "force-share", no_argument, 0, 'U'},
+ { "object", required_argument, 0, OPTION_OBJECT},
{ 0, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, ":hf:O:U", long_options, NULL))) {
+ while ((c = getopt_long(argc, argv, "hf:O:U", long_options, NULL))) {
if (c == EOF) {
break;
}
switch (c) {
- case 'O':
- out_fmt = optarg;
+ case 'h':
+ cmd_help(ccmd, "[-f FMT|--image-opts] [-O OUTPUT_FMT] [-U]\n"
+" [--object OBJDEF] [bs=BLOCK_SIZE] [count=BLOCKS] if=INPUT of=OUTPUT\n"
+,
+" -f, --format FMT\n"
+" specify format for INPUT explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat INPUT as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -O, --output-format OUTPUT_FMT\n"
+" format of the OUTPUT (default: raw)\n"
+" -U, --force-share\n"
+" open images in shared mode for concurrent access\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" bs=BLOCK_SIZE[bKMGTP]\n"
+" size of the I/O block, with optional multiplier suffix (powers of 1024)\n"
+" (default: 512)\n"
+" count=COUNT\n"
+" number of blocks to convert (default whole INPUT)\n"
+" if=INPUT\n"
+" name of the file, or option string (key=value,..)\n"
+" with --image-opts, to use for input\n"
+" of=OUTPUT\n"
+" output file name to create (will be overridden if alrady exists)\n"
+);
break;
case 'f':
fmt = optarg;
break;
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
break;
- case 'h':
- help();
+ case 'O':
+ out_fmt = optarg;
break;
case 'U':
force_share = true;
@@ -5565,9 +5588,8 @@ static int img_dd(const img_cmd_t *ccmd, int argc, char **argv)
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 25/27] qemu-img: measure: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (23 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 24/27] qemu-img: dd: " Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 26/27] qemu-img: implement short --help, remove global help() function Michael Tokarev
` (5 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
Also add -s short option for --size (and remove OPTION_SIZE).
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 89 +++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 62 insertions(+), 27 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 3220c95e3c..44212de3f6 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -71,7 +71,6 @@ enum {
OPTION_FLUSH_INTERVAL = 261,
OPTION_NO_DRAIN = 262,
OPTION_TARGET_IMAGE_OPTS = 263,
- OPTION_SIZE = 264,
OPTION_PREALLOCATION = 265,
OPTION_SHRINK = 266,
OPTION_SALVAGE = 267,
@@ -5781,15 +5780,6 @@ static void dump_json_block_measure_info(BlockMeasureInfo *info)
static int img_measure(const img_cmd_t *ccmd, int argc, char **argv)
{
- static const struct option long_options[] = {
- {"help", no_argument, 0, 'h'},
- {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
- {"object", required_argument, 0, OPTION_OBJECT},
- {"output", required_argument, 0, OPTION_OUTPUT},
- {"size", required_argument, 0, OPTION_SIZE},
- {"force-share", no_argument, 0, 'U'},
- {0, 0, 0, 0}
- };
OutputFormat output_format = OFORMAT_HUMAN;
BlockBackend *in_blk = NULL;
BlockDriver *drv;
@@ -5810,23 +5800,61 @@ static int img_measure(const img_cmd_t *ccmd, int argc, char **argv)
int ret = 1;
int c;
- while ((c = getopt_long(argc, argv, "hf:O:o:l:U",
+ static const struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"source-format", required_argument, 0, 'f'}, /* img_convert */
+ {"format", required_argument, 0, 'f'},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
+ {"source-image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, /* img_convert */
+ {"snapshot", required_argument, 0, 'l'},
+ {"target-format", required_argument, 0, 'O'},
+ {"target-format-options", required_argument, 0, 'o'}, /* img_convert */
+ {"options", required_argument, 0, 'o'},
+ {"force-share", no_argument, 0, 'U'},
+ {"output", required_argument, 0, OPTION_OUTPUT},
+ {"object", required_argument, 0, OPTION_OBJECT},
+ {"size", required_argument, 0, 's'},
+ {0, 0, 0, 0}
+ };
+
+ while ((c = getopt_long(argc, argv, "hf:l:O:o:Us:",
long_options, NULL)) != -1) {
switch (c) {
- case '?':
case 'h':
- help();
+ cmd_help(ccmd, "[-f FMT|--image-opts] [-l SNAPSHOT_PARAM]\n"
+" [-O TARGET_FMT] [-o TARGET_FMT_OPTS] [--output human|json]\n"
+" [--object OBJDEF] (--size SIZE | FILE)\n"
+,
+" -f, --format\n"
+" specify format of FILE explicitly (default: probing is used)\n"
+" --image-opts\n"
+" indicates that FILE is a complete image specification\n"
+" instead of a file name (incompatible with --format)\n"
+" -l, --snapshot SNAPSHOT\n"
+" use this snapshot in FILE as source\n"
+" -O, --target-format TARGET_FMT\n"
+" desired target/output image format (default: raw)\n"
+" -o TARGET_FMT_OPTS\n"
+" options specific to TARGET_FMT\n"
+" --output human|json\n"
+" output format (default: human)\n"
+" -U, --force-share\n"
+" open images in shared mode for concurrent access\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" -s, --size SIZE[bKMGTPE]\n"
+" measure file size for given image size,\n"
+" with optional multiplier suffix (powers of 1024)\n"
+" FILE\n"
+" measure file size required to convert from FILE (either a file name\n"
+" or an option string (key=value,..) with --image-options)\n"
+);
break;
case 'f':
fmt = optarg;
break;
- case 'O':
- out_fmt = optarg;
- break;
- case 'o':
- if (accumulate_options(&options, optarg) < 0) {
- goto out;
- }
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
break;
case 'l':
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
@@ -5841,24 +5869,31 @@ static int img_measure(const img_cmd_t *ccmd, int argc, char **argv)
snapshot_name = optarg;
}
break;
- case 'U':
- force_share = true;
+ case 'O':
+ out_fmt = optarg;
break;
- case OPTION_OBJECT:
- user_creatable_process_cmdline(optarg);
+ case 'o':
+ if (accumulate_options(&options, optarg) < 0) {
+ goto out;
+ }
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
+ case 'U':
+ force_share = true;
break;
case OPTION_OUTPUT:
output_format = parse_output_format(argv[0], optarg);
break;
- case OPTION_SIZE:
+ case OPTION_OBJECT:
+ user_creatable_process_cmdline(optarg);
+ break;
+ case 's':
img_size = cvtnum("image size", optarg);
if (img_size < 0) {
goto out;
}
break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 26/27] qemu-img: implement short --help, remove global help() function
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (24 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 25/27] qemu-img: measure: " Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-05-31 17:16 ` [PATCH 27/27] qemu-img: extend cvtnum() and use it in more places Michael Tokarev
` (4 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
now once all individual subcommands has --help support, remove
the large unreadable help() thing and replace it with small
global --help, which refers to individual command --help for
more info.
While at it, also line-wrap list of formats after 75 chars.
Since missing_argument() and unrecognized_option() are now unused,
remove them.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
qemu-img.c | 210 ++++++++++++++++++-----------------------------------
1 file changed, 72 insertions(+), 138 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 44212de3f6..18f7ba07c9 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -61,6 +61,7 @@
typedef struct img_cmd_t {
const char *name;
int (*handler)(const struct img_cmd_t *ccmd, int argc, char **argv);
+ const char *description;
} img_cmd_t;
enum {
@@ -94,11 +95,6 @@ typedef enum OutputFormat {
/* Default to cache=writeback as data integrity is not important for qemu-img */
#define BDRV_DEFAULT_CACHE "writeback"
-static void format_print(void *opaque, const char *name)
-{
- printf(" %s", name);
-}
-
static G_NORETURN
void tryhelp(const char *argv0)
{
@@ -118,18 +114,6 @@ void error_exit(const char *argv0, const char *fmt, ...)
tryhelp(argv0);
}
-static G_NORETURN
-void missing_argument(const char *option)
-{
- error_exit("qemu-img", "missing argument for option '%s'", option);
-}
-
-static G_NORETURN
-void unrecognized_option(const char *option)
-{
- error_exit("qemu-img", "unrecognized option '%s'", option);
-}
-
/*
* Print --help output for a command and exit.
* @syntax and @description are multi-line with trailing EOL
@@ -144,6 +128,7 @@ void cmd_help(const img_cmd_t *ccmd,
{
printf(
"Usage:\n"
+"%s. Usage:\n"
"\n"
" %s %s %s"
"\n"
@@ -151,7 +136,7 @@ void cmd_help(const img_cmd_t *ccmd,
" -h, --help\n"
" print this help and exit\n"
"%s\n",
- "qemu-img", ccmd->name,
+ ccmd->description, "qemu-img", ccmd->name,
syntax, arguments);
exit(EXIT_SUCCESS);
}
@@ -167,114 +152,6 @@ static OutputFormat parse_output_format(const char *argv0, const char *arg)
}
}
-/* Please keep in synch with docs/tools/qemu-img.rst */
-static G_NORETURN
-void help(void)
-{
- const char *help_msg =
- QEMU_IMG_VERSION
- "usage: qemu-img [standard options] command [command options]\n"
- "QEMU disk image utility\n"
- "\n"
- " '-h', '--help' display this help and exit\n"
- " '-V', '--version' output version information and exit\n"
- " '-T', '--trace' [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
- " specify tracing options\n"
- "\n"
- "Command syntax:\n"
-#define DEF(option, callback, arg_string) \
- " " arg_string "\n"
-#include "qemu-img-cmds.h"
-#undef DEF
- "\n"
- "Command parameters:\n"
- " 'filename' is a disk image filename\n"
- " 'objectdef' is a QEMU user creatable object definition. See the qemu(1)\n"
- " manual page for a description of the object properties. The most common\n"
- " object type is a 'secret', which is used to supply passwords and/or\n"
- " encryption keys.\n"
- " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
- " 'cache' is the cache mode used to write the output disk image, the valid\n"
- " options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
- " 'directsync' and 'unsafe' (default for convert)\n"
- " 'src_cache' is the cache mode used to read input disk images, the valid\n"
- " options are the same as for the 'cache' option\n"
- " 'size' is the disk image size in bytes. Optional suffixes\n"
- " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
- " 'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P) are\n"
- " supported. 'b' is ignored.\n"
- " 'output_filename' is the destination disk image filename\n"
- " 'output_fmt' is the destination format\n"
- " 'options' is a comma separated list of format specific options in a\n"
- " name=value format. Use -o help for an overview of the options supported by\n"
- " the used format\n"
- " 'snapshot_param' is param used for internal snapshot, format\n"
- " is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
- " '[ID_OR_NAME]'\n"
- " '-c' indicates that target image must be compressed (qcow format only)\n"
- " '-u' allows unsafe backing chains. For rebasing, it is assumed that old and\n"
- " new backing file match exactly. The image doesn't need a working\n"
- " backing file before rebasing in this case (useful for renaming the\n"
- " backing file). For image creation, allow creating without attempting\n"
- " to open the backing file.\n"
- " '-h' with or without a command shows this help and lists the supported formats\n"
- " '-p' show progress of command (only certain commands)\n"
- " '-q' use Quiet mode - do not print any output (except errors)\n"
- " '-S' indicates the consecutive number of bytes (defaults to 4k) that must\n"
- " contain only zeros for qemu-img to create a sparse image during\n"
- " conversion. If the number of bytes is 0, the source will not be scanned for\n"
- " unallocated or zero sectors, and the destination image will always be\n"
- " fully allocated\n"
- " '--output' takes the format in which the output must be done (human or json)\n"
- " '-n' skips the target volume creation (useful if the volume is created\n"
- " prior to running qemu-img)\n"
- "\n"
- "Parameters to bitmap subcommand:\n"
- " 'bitmap' is the name of the bitmap to manipulate, through one or more\n"
- " actions from '--add', '--remove', '--clear', '--enable', '--disable',\n"
- " or '--merge source'\n"
- " '-g granularity' sets the granularity for '--add' actions\n"
- " '-b source' and '-F src_fmt' tell '--merge' actions to find the source\n"
- " bitmaps from an alternative file\n"
- "\n"
- "Parameters to check subcommand:\n"
- " '-r' tries to repair any inconsistencies that are found during the check.\n"
- " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
- " kinds of errors, with a higher risk of choosing the wrong fix or\n"
- " hiding corruption that has already occurred.\n"
- "\n"
- "Parameters to convert subcommand:\n"
- " '--bitmaps' copies all top-level persistent bitmaps to destination\n"
- " '-m' specifies how many coroutines work in parallel during the convert\n"
- " process (defaults to 8)\n"
- " '-W' allow to write to the target out of order rather than sequential\n"
- "\n"
- "Parameters to snapshot subcommand:\n"
- " 'snapshot' is the name of the snapshot to create, apply or delete\n"
- " '-a' applies a snapshot (revert disk to saved state)\n"
- " '-c' creates a snapshot\n"
- " '-d' deletes a snapshot\n"
- " '-l' lists all snapshots in the given image\n"
- "\n"
- "Parameters to compare subcommand:\n"
- " '-f' first image format\n"
- " '-F' second image format\n"
- " '-s' run in Strict mode - fail on different image size or sector allocation\n"
- "\n"
- "Parameters to dd subcommand:\n"
- " 'bs=BYTES' read and write up to BYTES bytes at a time "
- "(default: 512)\n"
- " 'count=N' copy only N input blocks\n"
- " 'if=FILE' read from FILE\n"
- " 'of=FILE' write to FILE\n"
- " 'skip=N' skip N bs-sized blocks at the start of input\n";
-
- printf("%s\nSupported formats:", help_msg);
- bdrv_iterate_format(format_print, NULL, false);
- printf("\n\n" QEMU_HELP_BOTTOM "\n");
- exit(EXIT_SUCCESS);
-}
-
/*
* Is @list safe for accumulate_options()?
* It is when multiple of them can be joined together separated by ','.
@@ -5994,13 +5871,49 @@ out:
}
static const img_cmd_t img_cmds[] = {
-#define DEF(option, callback, arg_string) \
- { option, callback },
-#include "qemu-img-cmds.h"
-#undef DEF
+ { "amend", img_amend,
+ "Update format-specific options of the image" },
+ { "bench", img_bench,
+ "Run simple image benchmark" },
+ { "bitmap", img_bitmap,
+ "Perform modifications of the persistent bitmap in the image" },
+ { "check", img_check,
+ "Check basic image integrity" },
+ { "commit", img_commit,
+ "Commit image to its backing file" },
+ { "compare", img_compare,
+ "Check if two images have the same contents" },
+ { "convert", img_convert,
+ "Copy one image to another with optional format conversion" },
+ { "create", img_create,
+ "Create and format new image file" },
+ { "dd", img_dd,
+ "Copy input to output with optional format conversion" },
+ { "info", img_info,
+ "Display information about image" },
+ { "map", img_map,
+ "Dump image metadata" },
+ { "measure", img_measure,
+ "Calculate file size requred for a new image" },
+ { "rebase", img_rebase,
+ "Change backing file of the image" },
+ { "resize", img_resize,
+ "Resize the image to the new size" },
+ { "snapshot", img_snapshot,
+ "List or manipulate snapshots within image" },
{ NULL, NULL, },
};
+static void format_print(void *opaque, const char *name)
+{
+ int *np = opaque;
+ if (*np + strlen(name) > 75) {
+ printf("\n ");
+ *np = 1;
+ }
+ *np += printf(" %s", name);
+}
+
int main(int argc, char **argv)
{
const img_cmd_t *cmd;
@@ -6032,16 +5945,35 @@ int main(int argc, char **argv)
qemu_add_opts(&qemu_source_opts);
qemu_add_opts(&qemu_trace_opts);
- while ((c = getopt_long(argc, argv, "+:hVT:", long_options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "+hVT:", long_options, NULL)) != -1) {
switch (c) {
- case ':':
- missing_argument(argv[optind - 1]);
- return 0;
- case '?':
- unrecognized_option(argv[optind - 1]);
- return 0;
case 'h':
- help();
+ printf(
+QEMU_IMG_VERSION
+"QEMU disk image utility. Usage:\n"
+"\n"
+" qemu-img [standard options] COMMAND [--help | command options]\n"
+"\n"
+"Standard options:\n"
+" -h, --help\n"
+" display this help and exit\n"
+" -V, --version\n"
+" display version info and exit\n"
+" -T,--trace TRACE\n"
+" specify tracing options:\n"
+" [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
+"\n"
+"Recognized commands (run qemu-img COMMAND --help for command-specific help):\n\n");
+ for (cmd = img_cmds; cmd->name != NULL; cmd++) {
+ printf(" %s - %s\n", cmd->name, cmd->description);
+ }
+ printf("\nSupported image formats:\n");
+ c = 99; /* force a newline */
+ bdrv_iterate_format(format_print, &c, false);
+ if (c) {
+ printf("\n");
+ }
+ printf("\n" QEMU_HELP_BOTTOM "\n");
return 0;
case 'V':
printf(QEMU_IMG_VERSION);
@@ -6049,6 +5981,8 @@ int main(int argc, char **argv)
case 'T':
trace_opt_parse(optarg);
break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 27/27] qemu-img: extend cvtnum() and use it in more places
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (25 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 26/27] qemu-img: implement short --help, remove global help() function Michael Tokarev
@ 2025-05-31 17:16 ` Michael Tokarev
2025-06-23 9:15 ` [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (3 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-05-31 17:16 UTC (permalink / raw)
To: qemu-devel, qemu-block; +Cc: Michael Tokarev
cvtnum() expects input string to specify some sort of size
(optionally with KMG... suffix). However, there are a lot
of other number conversions in there (using qemu_strtol &Co),
also, not all conversions which use cvtnum, actually expects
size, - like dd count=nn.
Add bool issize argument to cvtnum() to specify if it should
treat the argument as a size or something else, - this changes
conversion routine in use and error text.
Use the new cvtnum() in more places (like where strtol were used),
since it never return negative number in successful conversion.
When it makes sense, also specify upper or lower bounds at the
same time. This simplifies option processing in multiple places,
removing the need of local temporary variables and longer error
reporting code.
While at it, fix errors, like depth in measure must be >= 1,
while the previous code allowed it to be 0.
In a few places, change unsigned variables (like of type size_t)
to be signed instead, - to avoid the need of temporary conversion
variable. All these variables are okay to be signed, we never
assign <0 value to them except of the cases of conversion error,
where we return immediately.
While at it, remove allowed size suffixes from the error message
as it makes no sense most of the time (should be in help instead).
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
qemu-img.c | 111 +++++++++++++------------------------
tests/qemu-iotests/049.out | 9 +--
2 files changed, 40 insertions(+), 80 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 18f7ba07c9..8925e14ba6 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -399,18 +399,16 @@ static int add_old_style_options(const char *fmt, QemuOpts *opts,
return 0;
}
-static int64_t cvtnum_full(const char *name, const char *value, int64_t min,
- int64_t max)
+static int64_t cvtnum_full(const char *name, const char *value,
+ bool issize, int64_t min, int64_t max)
{
int err;
uint64_t res;
- err = qemu_strtosz(value, NULL, &res);
+ err = issize ? qemu_strtosz(value, NULL, &res) :
+ qemu_strtou64(value, NULL, 0, &res);
if (err < 0 && err != -ERANGE) {
- error_report("Invalid %s specified. You may use "
- "k, M, G, T, P or E suffixes for", name);
- error_report("kilobytes, megabytes, gigabytes, terabytes, "
- "petabytes and exabytes.");
+ error_report("Invalid %s specified: '%s'.", name, value);
return err;
}
if (err == -ERANGE || res > max || res < min) {
@@ -421,9 +419,9 @@ static int64_t cvtnum_full(const char *name, const char *value, int64_t min,
return res;
}
-static int64_t cvtnum(const char *name, const char *value)
+static int64_t cvtnum(const char *name, const char *value, bool issize)
{
- return cvtnum_full(name, value, 0, INT64_MAX);
+ return cvtnum_full(name, value, issize, 0, INT64_MAX);
}
static int img_create(const img_cmd_t *ccmd, int argc, char **argv)
@@ -526,7 +524,7 @@ static int img_create(const img_cmd_t *ccmd, int argc, char **argv)
/* Get image size, if specified */
if (optind < argc) {
- img_size = cvtnum("image size", argv[optind++]);
+ img_size = cvtnum("image size", argv[optind++], true);
if (img_size < 0) {
goto fail;
}
@@ -985,7 +983,7 @@ static int img_commit(const img_cmd_t *ccmd, int argc, char **argv)
drop = true;
break;
case 'r':
- rate_limit = cvtnum("rate limit", optarg);
+ rate_limit = cvtnum("rate limit", optarg, true);
if (rate_limit < 0) {
return 1;
}
@@ -2426,7 +2424,7 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
{
int64_t sval;
- sval = cvtnum("buffer size for sparse output", optarg);
+ sval = cvtnum("buffer size for sparse output", optarg, true);
if (sval < 0) {
goto fail_getopt;
} else if (!QEMU_IS_ALIGNED(sval, BDRV_SECTOR_SIZE) ||
@@ -2460,16 +2458,15 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
force_share = true;
break;
case 'r':
- rate_limit = cvtnum("rate limit", optarg);
+ rate_limit = cvtnum("rate limit", optarg, true);
if (rate_limit < 0) {
goto fail_getopt;
}
break;
case 'm':
- if (qemu_strtol(optarg, NULL, 0, &s.num_coroutines) ||
- s.num_coroutines < 1 || s.num_coroutines > MAX_COROUTINES) {
- error_report("Invalid number of coroutines. Allowed number of"
- " coroutines is between 1 and %d", MAX_COROUTINES);
+ s.num_coroutines = cvtnum_full("number of coroutines", optarg,
+ false, 1, MAX_COROUTINES);
+ if (s.num_coroutines < 0) {
goto fail_getopt;
}
break;
@@ -3374,13 +3371,13 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
image_opts = true;
break;
case 's':
- start_offset = cvtnum("start offset", optarg);
+ start_offset = cvtnum("start offset", optarg, true);
if (start_offset < 0) {
return 1;
}
break;
case 'l':
- max_length = cvtnum("max length", optarg);
+ max_length = cvtnum("max length", optarg, true);
if (max_length < 0) {
return 1;
}
@@ -4717,9 +4714,9 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
int count = 75000;
int depth = 64;
int64_t offset = 0;
- size_t bufsize = 4096;
+ ssize_t bufsize = 4096;
int pattern = 0;
- size_t step = 0;
+ ssize_t step = 0;
int flush_interval = 0;
bool drain_on_flush = true;
int64_t image_size;
@@ -4824,27 +4821,17 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
}
break;
case 'c':
- {
- unsigned long res;
-
- if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
- error_report("Invalid request count specified");
+ count = cvtnum_full("request count", optarg, false, 1, INT_MAX);
+ if (count < 0) {
return 1;
}
- count = res;
break;
- }
case 'd':
- {
- unsigned long res;
-
- if (qemu_strtoul(optarg, NULL, 0, &res) <= 0 || res > INT_MAX) {
- error_report("Invalid queue depth specified");
+ depth = cvtnum_full("queue depth", optarg, false, 1, INT_MAX);
+ if (depth < 0) {
return 1;
}
- depth = res;
break;
- }
case 'n':
flags |= BDRV_O_NATIVE_AIO;
break;
@@ -4857,64 +4844,40 @@ static int img_bench(const img_cmd_t *ccmd, int argc, char **argv)
}
break;
case 'o':
- {
- offset = cvtnum("offset", optarg);
+ offset = cvtnum("offset", optarg, true);
if (offset < 0) {
return 1;
}
break;
- }
- break;
case 's':
- {
- int64_t sval;
-
- sval = cvtnum_full("buffer size", optarg, 0, INT_MAX);
- if (sval < 0) {
+ bufsize = cvtnum_full("buffer size", optarg, true, 1, INT_MAX);
+ if (bufsize < 0) {
return 1;
}
-
- bufsize = sval;
break;
- }
case 'S':
- {
- int64_t sval;
-
- sval = cvtnum_full("step_size", optarg, 0, INT_MAX);
- if (sval < 0) {
+ step = cvtnum_full("step size", optarg, true, 0, INT_MAX);
+ if (step < 0) {
return 1;
}
-
- step = sval;
break;
- }
case 'w':
flags |= BDRV_O_RDWR;
is_write = true;
break;
case OPTION_PATTERN:
- {
- unsigned long res;
-
- if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > 0xff) {
- error_report("Invalid pattern byte specified");
+ pattern = cvtnum_full("pattern byte", optarg, false, 0, 0xff);
+ if (pattern < 0) {
return 1;
}
- pattern = res;
break;
- }
case OPTION_FLUSH_INTERVAL:
- {
- unsigned long res;
-
- if (qemu_strtoul(optarg, NULL, 0, &res) < 0 || res > INT_MAX) {
- error_report("Invalid flush interval specified");
+ flush_interval = cvtnum_full("flush interval", optarg,
+ false, 0, INT_MAX);
+ if (flush_interval < 0) {
return 1;
}
- flush_interval = res;
break;
- }
case OPTION_NO_DRAIN:
drain_on_flush = false;
break;
@@ -5126,7 +5089,7 @@ static int img_bitmap(const img_cmd_t *ccmd, int argc, char **argv)
add = true;
break;
case 'g':
- granularity = cvtnum("granularity", optarg);
+ granularity = cvtnum("granularity", optarg, true);
if (granularity < 0) {
return 1;
}
@@ -5311,7 +5274,7 @@ static int img_dd_bs(const char *arg,
{
int64_t res;
- res = cvtnum_full("bs", arg, 1, INT_MAX);
+ res = cvtnum_full("bs", arg, true, 1, INT_MAX);
if (res < 0) {
return 1;
@@ -5325,7 +5288,7 @@ static int img_dd_count(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
- dd->count = cvtnum("count", arg);
+ dd->count = cvtnum("count", arg, false);
if (dd->count < 0) {
return 1;
@@ -5356,7 +5319,7 @@ static int img_dd_skip(const char *arg,
struct DdIo *in, struct DdIo *out,
struct DdInfo *dd)
{
- in->offset = cvtnum("skip", arg);
+ in->offset = cvtnum("skip", arg, false);
if (in->offset < 0) {
return 1;
@@ -5764,7 +5727,7 @@ static int img_measure(const img_cmd_t *ccmd, int argc, char **argv)
user_creatable_process_cmdline(optarg);
break;
case 's':
- img_size = cvtnum("image size", optarg);
+ img_size = cvtnum("image size", optarg, true);
if (img_size < 0) {
goto out;
}
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index 34e1b452e6..a7a7d5a96e 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -98,8 +98,7 @@ qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Value '-1024' is out of range for parameter 'size'
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k
-qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
-qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
+qemu-img: Invalid image size specified: '-1k'.
qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below 2^64
@@ -107,8 +106,7 @@ Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta-
and exabytes, respectively.
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte
-qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
-qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
+qemu-img: Invalid image size specified: '1kilobyte'.
qemu-img create -f qcow2 -o size=1kilobyte TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below 2^64
@@ -116,8 +114,7 @@ Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta-
and exabytes, respectively.
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- foobar
-qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
-qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
+qemu-img: Invalid image size specified: 'foobar'.
qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below 2^64
--
2.39.5
^ permalink raw reply related [flat|nested] 37+ messages in thread
* Re: [PATCH v4 00/27] refresh qemu-img options handling
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (26 preceding siblings ...)
2025-05-31 17:16 ` [PATCH 27/27] qemu-img: extend cvtnum() and use it in more places Michael Tokarev
@ 2025-06-23 9:15 ` Michael Tokarev
2025-07-15 14:07 ` [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change) Michael Tokarev
` (2 subsequent siblings)
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-06-23 9:15 UTC (permalink / raw)
To: qemu-devel, qemu-block
Ping once again?
Please let's move with this one. Either it should be accepted,
maybe with some tweaks, or dropped entirely. There's enough
silence already - it's been there for over 2 years.
Thanks,
/mjt
On 31.05.2025 20:15, Michael Tokarev wrote:
> This is another iteration of this patch series, which tries
> to add missing command-line options, --help output, make it
> all more or less consistent, etc.
>
> I addressed (hopefully) all comments so far, mostly by Kevin.
> I ended up (so far) with a bit different wording somewhere.
>
> The manpage (and the separate documentation) hasn't changed
> much, but I intend to use the same wording there as in --help
> output. An example of the separate documentation change is
> provided with "create" subcommand only, as a PoC.
>
> I tried to rename a few existing options to make them more
> consistent. This is an RFC, so to say, - I'd love to make
> more changes but it isn't really possible because the names
> I want to use are already used for different purpose. All
> such changes (3 in total) are marked with "(short option change)"
> suffix in the patch subject. In particular, I tried to use
> -b for backing-file, and -B for backing-format, in all places.
> Maybe it's too late to change that though.
>
> All subcommands now have --object option. I wonder why we
> haven't done it in common place, before a subcommand. Maybe
> it's a good idea (and I think it is) to add it to the common
> (before-subcomman) place, document it there, and remove the
> --object mentions from individual commands --help output.
>
> Thanks,
>
> /mjt
>
> Michael Tokarev (27):
> qemu-img: measure: convert img_size to signed, simplify handling
> qemu-img: create: convert img_size to signed, simplify handling
> qemu-img: global option processing and error printing
> qemu-img: pass current cmd info into command handlers
> qemu-img: create: refresh options/--help (short option change)
> qemu-img: factor out parse_output_format() and use it in the code
> qemu-img: check: refresh options/--help
> qemu-img: simplify --repair error message
> qemu-img: commit: refresh options/--help
> qemu-img: compare: use helper function for --object
> qemu-img: compare: refresh options/--help
> qemu-img: convert: refresh options/--help (short option change)
> qemu-img: info: refresh options/--help
> qemu-img: map: refresh options/--help
> qemu-img: snapshot: allow specifying -f fmt
> qemu-img: snapshot: make -l (list) the default, simplify option handling
> qemu-img: snapshot: refresh options/--help
> qemu-img: rebase: refresh options/--help (short option change)
> qemu-img: resize: do not always eat last argument
> qemu-img: resize: refresh options/--help
> qemu-img: amend: refresh options/--help
> qemu-img: bench: refresh options/--help
> qemu-img: bitmap: refresh options/--help
> qemu-img: dd: refresh options/--help
> qemu-img: measure: refresh options/--help
> qemu-img: implement short --help, remove global help() function
> qemu-img: extend cvtnum() and use it in more places
>
> docs/tools/qemu-img.rst | 18 +-
> qemu-img-cmds.hx | 4 +-
> qemu-img.c | 1782 +++++++++++++++++++++---------------
> tests/qemu-iotests/049.out | 9 +-
> 4 files changed, 1082 insertions(+), 731 deletions(-)
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 13/27] qemu-img: info: refresh options/--help
2025-05-31 17:15 ` [PATCH 13/27] qemu-img: info: refresh options/--help Michael Tokarev
@ 2025-07-15 13:04 ` Kevin Wolf
0 siblings, 0 replies; 37+ messages in thread
From: Kevin Wolf @ 2025-07-15 13:04 UTC (permalink / raw)
To: Michael Tokarev; +Cc: qemu-devel, qemu-block
Am 31.05.2025 um 19:15 hat Michael Tokarev geschrieben:
> Add missing long options and --help output.
> Also add -b short option for --backing-chain, and remove
> now-unused OPTION_BACKING_CHAIN.
I think I wouldn't do this part, -b specifies a backing file name
elsewhere, so this feels a little inconsistent. Adding long options
everywhere is obvious, but overloading short options with more meanings
in different subcommands could be confusing.
> Reorder options for consistency.
>
> While at it, remove unused option_index variable.
>
> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
> ---
> qemu-img.c | 54 ++++++++++++++++++++++++++++++++++--------------------
> 1 file changed, 34 insertions(+), 20 deletions(-)
>
> diff --git a/qemu-img.c b/qemu-img.c
> index 5858304a62..f0d04a874d 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -65,7 +65,6 @@ typedef struct img_cmd_t {
>
> enum {
> OPTION_OUTPUT = 256,
> - OPTION_BACKING_CHAIN = 257,
> OPTION_OBJECT = 258,
> OPTION_IMAGE_OPTS = 259,
> OPTION_PATTERN = 260,
> @@ -3217,50 +3216,65 @@ static int img_info(const img_cmd_t *ccmd, int argc, char **argv)
>
> fmt = NULL;
> for(;;) {
> - int option_index = 0;
> static const struct option long_options[] = {
> {"help", no_argument, 0, 'h'},
> {"format", required_argument, 0, 'f'},
> - {"output", required_argument, 0, OPTION_OUTPUT},
> - {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
> - {"object", required_argument, 0, OPTION_OBJECT},
> {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
> + {"backing-chain", no_argument, 0, 'b'},
> {"force-share", no_argument, 0, 'U'},
> + {"output", required_argument, 0, OPTION_OUTPUT},
> + {"object", required_argument, 0, OPTION_OBJECT},
> {0, 0, 0, 0}
> };
> - c = getopt_long(argc, argv, ":f:hU",
> - long_options, &option_index);
> + c = getopt_long(argc, argv, "hf:bU",
> + long_options, NULL);
> if (c == -1) {
> break;
> }
> switch(c) {
> - case ':':
> - missing_argument(argv[optind - 1]);
> - break;
> - case '?':
> - unrecognized_option(argv[optind - 1]);
> - break;
> case 'h':
> - help();
> + cmd_help(ccmd, "[-f FMT | --image-opts] [-b] [-U]"
> +" [--output human|json] [--object OBJDEF] FILE\n"
> +,
> +" -f, --format FMT\n"
> +" specify FILE image format explicitly (default: probing is used)\n"
> +" --image-opts\n"
> +" treat FILE as an option string (key=value,..), not a file name\n"
> +" (incompatible with -f|--format)\n"
> +" -b, --backing-chain\n"
> +" display information about backing chaing\n"
> +" in case the image is stacked\n"
s/chaing/chain/
Also no need for the \n in the middle, the whole message fits in 80
characters.
Kevin
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 14/27] qemu-img: map: refresh options/--help
2025-05-31 17:15 ` [PATCH 14/27] qemu-img: map: " Michael Tokarev
@ 2025-07-15 13:07 ` Kevin Wolf
2025-07-15 13:50 ` Michael Tokarev
0 siblings, 1 reply; 37+ messages in thread
From: Kevin Wolf @ 2025-07-15 13:07 UTC (permalink / raw)
To: Michael Tokarev; +Cc: qemu-devel, qemu-block
Am 31.05.2025 um 19:15 hat Michael Tokarev geschrieben:
> Add missing long options and --help output,
> reorder options for consistency.
>
> While at it, remove unused option_index variable.
>
> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
> ---
> qemu-img.c | 57 ++++++++++++++++++++++++++++++++++--------------------
> 1 file changed, 36 insertions(+), 21 deletions(-)
>
> diff --git a/qemu-img.c b/qemu-img.c
> index f0d04a874d..f5820a7017 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -3451,41 +3451,51 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
>
> fmt = NULL;
> for (;;) {
> - int option_index = 0;
> static const struct option long_options[] = {
> {"help", no_argument, 0, 'h'},
> {"format", required_argument, 0, 'f'},
> - {"output", required_argument, 0, OPTION_OUTPUT},
> - {"object", required_argument, 0, OPTION_OBJECT},
> {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
> - {"force-share", no_argument, 0, 'U'},
> {"start-offset", required_argument, 0, 's'},
> {"max-length", required_argument, 0, 'l'},
> + {"force-share", no_argument, 0, 'U'},
> + {"output", required_argument, 0, OPTION_OUTPUT},
> + {"object", required_argument, 0, OPTION_OBJECT},
> {0, 0, 0, 0}
> };
> - c = getopt_long(argc, argv, ":f:s:l:hU",
> - long_options, &option_index);
> + c = getopt_long(argc, argv, "hf:s:l:U",
> + long_options, NULL);
> if (c == -1) {
> break;
> }
> switch (c) {
> - case ':':
> - missing_argument(argv[optind - 1]);
> - break;
> - case '?':
> - unrecognized_option(argv[optind - 1]);
> - break;
> case 'h':
> - help();
> + cmd_help(ccmd, "[-f FMT | --image-opts]\n"
> +" [--start-offset OFFSET] [--max-length LENGTH]\n"
> +" [--output human|json] [-U] [--object OBJDEF] FILE\n"
> +,
> +" -f, --format FMT\n"
> +" specify FILE image format explicitly (default: probing is used)\n"
> +" --image-opts\n"
> +" treat FILE as an option string (key=value,..), not a file name\n"
> +" (incompatible with -f|--format)\n"
> +" --start-offset OFFSET\n"
-s, --start-offset
> +" --max-length LENGTH\n"
-l, --max-length
> +" --output human|json\n"
> +" specify output format name (default: human)\n"
> +" -U, --force-share\n"
> +" open image in shared mode for concurrent access\n"
> +" --object OBJDEF\n"
> +" defines QEMU user-creatable object\n"
> +" FILE\n"
> +" the image file name, or option string (key=value,..)\n"
> +" with --image-opts, to operate on\n"
> +);
Kevin
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH 14/27] qemu-img: map: refresh options/--help
2025-07-15 13:07 ` Kevin Wolf
@ 2025-07-15 13:50 ` Michael Tokarev
0 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-07-15 13:50 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-devel, qemu-block
On 15.07.2025 16:07, Kevin Wolf wrote:
>> +" --start-offset OFFSET\n"
>
> -s, --start-offset
>
>> +" --max-length LENGTH\n"
>
> -l, --max-length
These are also undocumented. Lemme add some info for them..
/mjt
^ permalink raw reply [flat|nested] 37+ messages in thread
* [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change)
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (27 preceding siblings ...)
2025-06-23 9:15 ` [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
@ 2025-07-15 14:07 ` Michael Tokarev
2025-07-15 14:09 ` [PATCH 14/27] qemu-img: map: refresh options/--help Michael Tokarev
2025-07-15 18:42 ` [PATCH v4 00/27] refresh qemu-img options handling Kevin Wolf
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-07-15 14:07 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, Kevin Wolf, Michael Tokarev
Add missing long options and --help output.
Reorder options for consistency.
Use -b for --backing, and recognize -B for backwards
compatibility. Unfortunately we can't use -B to
specify backing format.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
docs/tools/qemu-img.rst | 2 +-
qemu-img.c | 230 +++++++++++++++++++++++++++-------------
2 files changed, 159 insertions(+), 73 deletions(-)
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
index a21e439082..23715811e2 100644
--- a/docs/tools/qemu-img.rst
+++ b/docs/tools/qemu-img.rst
@@ -419,7 +419,7 @@ Command description:
4
Error on reading data
-.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps [--skip-broken-bitmaps]] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-B BACKING_FILE [-F BACKING_FMT]] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
+.. option:: convert [--object OBJECTDEF] [--image-opts] [--target-image-opts] [--target-is-zero] [--bitmaps [--skip-broken-bitmaps]] [-U] [-C] [-c] [-p] [-q] [-n] [-f FMT] [-t CACHE] [-T SRC_CACHE] [-O OUTPUT_FMT] [-b BACKING_FILE [-F BACKING_FMT]] [-o OPTIONS] [-l SNAPSHOT_PARAM] [-S SPARSE_SIZE] [-r RATE_LIMIT] [-m NUM_COROUTINES] [-W] FILENAME [FILENAME2 [...]] OUTPUT_FILENAME
Convert the disk image *FILENAME* or a snapshot *SNAPSHOT_PARAM*
to disk image *OUTPUT_FILENAME* using format *OUTPUT_FMT*. It can
diff --git a/qemu-img.c b/qemu-img.c
index 40a5a1f604..6952d78ea7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -2390,53 +2390,122 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
for(;;) {
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
- {"object", required_argument, 0, OPTION_OBJECT},
+ {"source-format", required_argument, 0, 'f'},
+ /*
+ * XXX: historic --image-opts acts on source file only,
+ * it seems better to have it affect both source and target,
+ * and have separate --source-image-opts for source,
+ * but this might break existing setups.
+ */
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
- {"force-share", no_argument, 0, 'U'},
- {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
- {"salvage", no_argument, 0, OPTION_SALVAGE},
- {"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO},
+ {"source-cache", required_argument, 0, 'T'},
+ {"snapshot", required_argument, 0, 'l'},
{"bitmaps", no_argument, 0, OPTION_BITMAPS},
{"skip-broken-bitmaps", no_argument, 0, OPTION_SKIP_BROKEN},
+ {"salvage", no_argument, 0, OPTION_SALVAGE},
+ {"target-format", required_argument, 0, 'O'},
+ {"target-image-opts", no_argument, 0, OPTION_TARGET_IMAGE_OPTS},
+ {"target-format-options", required_argument, 0, 'o'},
+ {"target-cache", required_argument, 0, 't'},
+ {"backing", required_argument, 0, 'b'},
+ {"backing-format", required_argument, 0, 'F'},
+ {"sparse-size", required_argument, 0, 'S'},
+ {"no-create", no_argument, 0, 'n'},
+ {"target-is-zero", no_argument, 0, OPTION_TARGET_IS_ZERO},
+ {"force-share", no_argument, 0, 'U'},
+ {"rate-limit", required_argument, 0, 'r'},
+ {"parallel", required_argument, 0, 'm'},
+ {"oob-writes", no_argument, 0, 'W'},
+ {"copy-range-offloading", no_argument, 0, 'C'},
+ {"progress", no_argument, 0, 'p'},
+ {"quiet", no_argument, 0, 'q'},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":hf:O:B:CcF:o:l:S:pt:T:qnm:WUr:",
+ c = getopt_long(argc, argv, "hf:O:b:B:CcF:o:l:S:pt:T:nm:WUr:q",
long_options, NULL);
if (c == -1) {
break;
}
- switch(c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
+ switch (c) {
case 'h':
- help();
+ cmd_help(ccmd, "[-f SRC_FMT | --image-opts] [-T SRC_CACHE]\n"
+" [-l SNAPSHOT_PARAM] [--bitmaps [--skip-broken-bitmaps]] [--salvage]\n"
+" [-O TGT_FMT | --target-image-opts] [-o TGT_FMT_OPTS] [-t TGT_CACHE]\n"
+" [-b BACKING_FILE [-F BACKING_FMT]] [-S SPARSE_SIZE]\n"
+" [-n] [--target-is-zero] [-c]\n"
+" [-U] [-r RATE] [-m NUM_PARALLEL] [-W] [-C] [-p] [-q] [--object OBJDEF]\n"
+" SRC_FILE [SRC_FILE2...] TGT_FILE\n"
+,
+" -f, --source-format SRC_FMT\n"
+" specify format of all SRC_FILEs explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat each SRC_FILE as an option string (key=value,...), not a file name\n"
+" (incompatible with -f|--source-format)\n"
+" -T, --source-cache SRC_CACHE\n"
+" source image(s) cache mode (" BDRV_DEFAULT_CACHE ")\n"
+" -l, --snapshot SNAPSHOT_PARAMS\n"
+" specify source snapshot parameters\n"
+" --bitmaps\n"
+" also copy any persistent bitmaps present in source\n"
+" --skip-broken-bitmaps\n"
+" skip (do not error out) any broken bitmaps\n"
+" --salvage\n"
+" ignore errors on input (convert unreadable areas to zeros)\n"
+" -O, --target-format TGT_FMT\n"
+" specify TGT_FILE image format (default: raw)\n"
+" --target-image-opts\n"
+" treat TGT_FILE as an option string (key=value,...), not a file name\n"
+" (incompatible with -O|--target-format)\n"
+" -o, --target-format-options TGT_FMT_OPTS\n"
+" TGT_FMT-specific options\n"
+" -t, --target-cache TGT_CACHE\n"
+" cache mode when opening output image (default: unsafe)\n"
+" -b, --backing BACKING_FILE (was -B in <= 10.0)\n"
+" create target image to be a CoW on top of BACKING_FILE\n"
+" -F, --backing-format BACKING_FMT\n" /* -B used for -b in <=10.0 */
+" specify BACKING_FILE image format explicitly (default: probing is used)\n"
+" -S, --sparse-size SPARSE_SIZE[bkKMGTPE]\n"
+" specify number of consecutive zero bytes to treat as a gap on output\n"
+" (rounded down to nearest 512 bytes), with optional multiplier suffix\n"
+" -n, --no-create\n"
+" omit target volume creation (e.g. on rbd)\n"
+" --target-is-zero\n"
+" indicates that the target volume is pre-zeroed\n"
+" -c, --compress\n"
+" create compressed output image (qcow and qcow2 formats only)\n"
+" -U, --force-share\n"
+" open images in shared mode for concurrent access\n"
+" -r, --rate-limit RATE\n"
+" I/O rate limit, in bytes per second\n"
+" -m, --parallel NUM_PARALLEL\n"
+" specify parallelism (default: 8)\n"
+" -C, --copy-range-offloading\n"
+" try to use copy offloading\n"
+" -W, --oob-writes\n"
+" enable out-of-order writes to improve performance\n"
+" -p, --progress\n"
+" display progress information\n"
+" -q, --quiet\n"
+" quiet mode (produce only error messages if any)\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" SRC_FILE...\n"
+" one or more source image file names,\n"
+" or option strings (key=value,..) with --source-image-opts\n"
+" TGT_FILE\n"
+" target (output) image file name,\n"
+" or option string (key=value,..) with --target-image-opts\n"
+);
break;
case 'f':
fmt = optarg;
break;
- case 'O':
- out_fmt = optarg;
- break;
- case 'B':
- out_baseimg = optarg;
- break;
- case 'C':
- s.copy_range = true;
- break;
- case 'c':
- s.compressed = true;
- break;
- case 'F':
- backing_fmt = optarg;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
break;
- case 'o':
- if (accumulate_options(&options, optarg) < 0) {
- goto fail_getopt;
- }
+ case 'T':
+ src_cache = optarg;
break;
case 'l':
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
@@ -2451,6 +2520,36 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
snapshot_name = optarg;
}
break;
+ case OPTION_BITMAPS:
+ bitmaps = true;
+ break;
+ case OPTION_SKIP_BROKEN:
+ skip_broken = true;
+ break;
+ case OPTION_SALVAGE:
+ s.salvage = true;
+ break;
+ case 'O':
+ out_fmt = optarg;
+ break;
+ case OPTION_TARGET_IMAGE_OPTS:
+ tgt_image_opts = true;
+ break;
+ case 'o':
+ if (accumulate_options(&options, optarg) < 0) {
+ goto fail_getopt;
+ }
+ break;
+ case 't':
+ cache = optarg;
+ break;
+ case 'B': /* <=10.0 */
+ case 'b':
+ out_baseimg = optarg;
+ break;
+ case 'F': /* can't use -B as it used as -b in <=10.0 */
+ backing_fmt = optarg;
+ break;
case 'S':
{
int64_t sval;
@@ -2471,20 +2570,28 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
explict_min_sparse = true;
break;
}
- case 'p':
- progress = true;
+ case 'n':
+ skip_create = true;
break;
- case 't':
- cache = optarg;
+ case OPTION_TARGET_IS_ZERO:
+ /*
+ * The user asserting that the target is blank has the
+ * same effect as the target driver supporting zero
+ * initialisation.
+ */
+ s.has_zero_init = true;
break;
- case 'T':
- src_cache = optarg;
+ case 'c':
+ s.compressed = true;
break;
- case 'q':
- s.quiet = true;
+ case 'U':
+ force_share = true;
break;
- case 'n':
- skip_create = true;
+ case 'r':
+ rate_limit = cvtnum("rate limit", optarg);
+ if (rate_limit < 0) {
+ goto fail_getopt;
+ }
break;
case 'm':
if (qemu_strtol(optarg, NULL, 0, &s.num_coroutines) ||
@@ -2497,41 +2604,20 @@ static int img_convert(const img_cmd_t *ccmd, int argc, char **argv)
case 'W':
s.wr_in_order = false;
break;
- case 'U':
- force_share = true;
+ case 'C':
+ s.copy_range = true;
break;
- case 'r':
- rate_limit = cvtnum("rate limit", optarg);
- if (rate_limit < 0) {
- goto fail_getopt;
- }
+ case 'p':
+ progress = true;
+ break;
+ case 'q':
+ s.quiet = true;
break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
- case OPTION_SALVAGE:
- s.salvage = true;
- break;
- case OPTION_TARGET_IMAGE_OPTS:
- tgt_image_opts = true;
- break;
- case OPTION_TARGET_IS_ZERO:
- /*
- * The user asserting that the target is blank has the
- * same effect as the target driver supporting zero
- * initialisation.
- */
- s.has_zero_init = true;
- break;
- case OPTION_BITMAPS:
- bitmaps = true;
- break;
- case OPTION_SKIP_BROKEN:
- skip_broken = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
--
2.47.2
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [PATCH 14/27] qemu-img: map: refresh options/--help
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (28 preceding siblings ...)
2025-07-15 14:07 ` [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change) Michael Tokarev
@ 2025-07-15 14:09 ` Michael Tokarev
2025-07-15 18:42 ` [PATCH v4 00/27] refresh qemu-img options handling Kevin Wolf
30 siblings, 0 replies; 37+ messages in thread
From: Michael Tokarev @ 2025-07-15 14:09 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, Kevin Wolf, Michael Tokarev
Add missing long options and --help output,
reorder options for consistency.
While at it, remove unused option_index variable.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
qemu-img.c | 59 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 38 insertions(+), 21 deletions(-)
diff --git a/qemu-img.c b/qemu-img.c
index 8138166896..e407b06d0c 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -3454,41 +3454,53 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
fmt = NULL;
for (;;) {
- int option_index = 0;
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"format", required_argument, 0, 'f'},
- {"output", required_argument, 0, OPTION_OUTPUT},
- {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
- {"force-share", no_argument, 0, 'U'},
{"start-offset", required_argument, 0, 's'},
{"max-length", required_argument, 0, 'l'},
+ {"force-share", no_argument, 0, 'U'},
+ {"output", required_argument, 0, OPTION_OUTPUT},
+ {"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, ":f:s:l:hU",
- long_options, &option_index);
+ c = getopt_long(argc, argv, "hf:s:l:U",
+ long_options, NULL);
if (c == -1) {
break;
}
switch (c) {
- case ':':
- missing_argument(argv[optind - 1]);
- break;
- case '?':
- unrecognized_option(argv[optind - 1]);
- break;
case 'h':
- help();
+ cmd_help(ccmd, "[-f FMT | --image-opts]\n"
+" [--start-offset OFFSET] [--max-length LENGTH]\n"
+" [--output human|json] [-U] [--object OBJDEF] FILE\n"
+,
+" -f, --format FMT\n"
+" specify FILE image format explicitly (default: probing is used)\n"
+" --image-opts\n"
+" treat FILE as an option string (key=value,..), not a file name\n"
+" (incompatible with -f|--format)\n"
+" -s, --start-offset OFFSET\n"
+" start at the given OFFSET in the image, not at the beginning\n"
+" -l, --max-length LENGTH\n"
+" process at max LENGTH bytes instead up to the end of the image\n"
+" --output human|json\n"
+" specify output format name (default: human)\n"
+" -U, --force-share\n"
+" open image in shared mode for concurrent access\n"
+" --object OBJDEF\n"
+" defines QEMU user-creatable object\n"
+" FILE\n"
+" the image file name, or option string (key=value,..)\n"
+" with --image-opts, to operate on\n"
+);
break;
case 'f':
fmt = optarg;
break;
- case 'U':
- force_share = true;
- break;
- case OPTION_OUTPUT:
- output_format = parse_output_format(argv[0], optarg);
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
break;
case 's':
start_offset = cvtnum("start offset", optarg);
@@ -3502,12 +3514,17 @@ static int img_map(const img_cmd_t *ccmd, int argc, char **argv)
return 1;
}
break;
+ case OPTION_OUTPUT:
+ output_format = parse_output_format(argv[0], optarg);
+ break;
+ case 'U':
+ force_share = true;
+ break;
case OPTION_OBJECT:
user_creatable_process_cmdline(optarg);
break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
+ default:
+ tryhelp(argv[0]);
}
}
if (optind != argc - 1) {
--
2.47.2
^ permalink raw reply related [flat|nested] 37+ messages in thread
* Re: [PATCH v4 00/27] refresh qemu-img options handling
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
` (29 preceding siblings ...)
2025-07-15 14:09 ` [PATCH 14/27] qemu-img: map: refresh options/--help Michael Tokarev
@ 2025-07-15 18:42 ` Kevin Wolf
2025-07-17 8:27 ` Michael Tokarev
30 siblings, 1 reply; 37+ messages in thread
From: Kevin Wolf @ 2025-07-15 18:42 UTC (permalink / raw)
To: Michael Tokarev; +Cc: qemu-devel, qemu-block
Am 31.05.2025 um 19:15 hat Michael Tokarev geschrieben:
> This is another iteration of this patch series, which tries
> to add missing command-line options, --help output, make it
> all more or less consistent, etc.
>
> I addressed (hopefully) all comments so far, mostly by Kevin.
> I ended up (so far) with a bit different wording somewhere.
Thanks, I tweaked the wording and style a little bit here and there,
fixed some qemu-iotests and applied it to the block branch.
Kevin
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH v4 00/27] refresh qemu-img options handling
2025-07-15 18:42 ` [PATCH v4 00/27] refresh qemu-img options handling Kevin Wolf
@ 2025-07-17 8:27 ` Michael Tokarev
2025-07-17 16:01 ` Kevin Wolf
0 siblings, 1 reply; 37+ messages in thread
From: Michael Tokarev @ 2025-07-17 8:27 UTC (permalink / raw)
To: Kevin Wolf; +Cc: qemu-devel, qemu-block
On 15.07.2025 21:42, Kevin Wolf wrote:
> Am 31.05.2025 um 19:15 hat Michael Tokarev geschrieben:
>> This is another iteration of this patch series, which tries
>> to add missing command-line options, --help output, make it
>> all more or less consistent, etc.
>>
>> I addressed (hopefully) all comments so far, mostly by Kevin.
>> I ended up (so far) with a bit different wording somewhere.
>
> Thanks, I tweaked the wording and style a little bit here and there,
> fixed some qemu-iotests and applied it to the block branch.
Thank you very much Kevin. It was.. long :)
I'm not sure I follow - which iotests did you have to tweak?
It shouldn't affect iotests, maybe only if we have some stuff
testing for --help or invalid options?
Thanks,
/mjt
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [PATCH v4 00/27] refresh qemu-img options handling
2025-07-17 8:27 ` Michael Tokarev
@ 2025-07-17 16:01 ` Kevin Wolf
0 siblings, 0 replies; 37+ messages in thread
From: Kevin Wolf @ 2025-07-17 16:01 UTC (permalink / raw)
To: Michael Tokarev; +Cc: qemu-devel, qemu-block
Am 17.07.2025 um 10:27 hat Michael Tokarev geschrieben:
> On 15.07.2025 21:42, Kevin Wolf wrote:
> > Am 31.05.2025 um 19:15 hat Michael Tokarev geschrieben:
> > > This is another iteration of this patch series, which tries
> > > to add missing command-line options, --help output, make it
> > > all more or less consistent, etc.
> > >
> > > I addressed (hopefully) all comments so far, mostly by Kevin.
> > > I ended up (so far) with a bit different wording somewhere.
> >
> > Thanks, I tweaked the wording and style a little bit here and there,
> > fixed some qemu-iotests and applied it to the block branch.
>
> Thank you very much Kevin. It was.. long :)
>
> I'm not sure I follow - which iotests did you have to tweak?
> It shouldn't affect iotests, maybe only if we have some stuff
> testing for --help or invalid options?
Yes, there were some changed error messages for invalid options that
appeared in reference output.
Kevin
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2025-07-17 18:54 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-31 17:15 [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
2025-05-31 17:15 ` [PATCH 01/27] qemu-img: measure: convert img_size to signed, simplify handling Michael Tokarev
2025-05-31 17:15 ` [PATCH 02/27] qemu-img: create: " Michael Tokarev
2025-05-31 17:15 ` [PATCH 03/27] qemu-img: global option processing and error printing Michael Tokarev
2025-05-31 17:15 ` [PATCH 04/27] qemu-img: pass current cmd info into command handlers Michael Tokarev
2025-05-31 17:15 ` [PATCH 05/27] qemu-img: create: refresh options/--help (short option change) Michael Tokarev
2025-05-31 17:15 ` [PATCH 06/27] qemu-img: factor out parse_output_format() and use it in the code Michael Tokarev
2025-05-31 17:15 ` [PATCH 07/27] qemu-img: check: refresh options/--help Michael Tokarev
2025-05-31 17:15 ` [PATCH 08/27] qemu-img: simplify --repair error message Michael Tokarev
2025-05-31 17:15 ` [PATCH 09/27] qemu-img: commit: refresh options/--help Michael Tokarev
2025-05-31 17:15 ` [PATCH 10/27] qemu-img: compare: use helper function for --object Michael Tokarev
2025-05-31 17:15 ` [PATCH 11/27] qemu-img: compare: refresh options/--help Michael Tokarev
2025-05-31 17:15 ` [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change) Michael Tokarev
2025-05-31 17:15 ` [PATCH 13/27] qemu-img: info: refresh options/--help Michael Tokarev
2025-07-15 13:04 ` Kevin Wolf
2025-05-31 17:15 ` [PATCH 14/27] qemu-img: map: " Michael Tokarev
2025-07-15 13:07 ` Kevin Wolf
2025-07-15 13:50 ` Michael Tokarev
2025-05-31 17:15 ` [PATCH 15/27] qemu-img: snapshot: allow specifying -f fmt Michael Tokarev
2025-05-31 17:15 ` [PATCH 16/27] qemu-img: snapshot: make -l (list) the default, simplify option handling Michael Tokarev
2025-05-31 17:15 ` [PATCH 17/27] qemu-img: snapshot: refresh options/--help Michael Tokarev
2025-05-31 17:16 ` [PATCH 18/27] qemu-img: rebase: refresh options/--help (short option change) Michael Tokarev
2025-05-31 17:16 ` [PATCH 19/27] qemu-img: resize: do not always eat last argument Michael Tokarev
2025-05-31 17:16 ` [PATCH 20/27] qemu-img: resize: refresh options/--help Michael Tokarev
2025-05-31 17:16 ` [PATCH 21/27] qemu-img: amend: " Michael Tokarev
2025-05-31 17:16 ` [PATCH 22/27] qemu-img: bench: " Michael Tokarev
2025-05-31 17:16 ` [PATCH 23/27] qemu-img: bitmap: " Michael Tokarev
2025-05-31 17:16 ` [PATCH 24/27] qemu-img: dd: " Michael Tokarev
2025-05-31 17:16 ` [PATCH 25/27] qemu-img: measure: " Michael Tokarev
2025-05-31 17:16 ` [PATCH 26/27] qemu-img: implement short --help, remove global help() function Michael Tokarev
2025-05-31 17:16 ` [PATCH 27/27] qemu-img: extend cvtnum() and use it in more places Michael Tokarev
2025-06-23 9:15 ` [PATCH v4 00/27] refresh qemu-img options handling Michael Tokarev
2025-07-15 14:07 ` [PATCH 12/27] qemu-img: convert: refresh options/--help (short option change) Michael Tokarev
2025-07-15 14:09 ` [PATCH 14/27] qemu-img: map: refresh options/--help Michael Tokarev
2025-07-15 18:42 ` [PATCH v4 00/27] refresh qemu-img options handling Kevin Wolf
2025-07-17 8:27 ` Michael Tokarev
2025-07-17 16:01 ` Kevin Wolf
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).