[PATCH 22/23] qemu-img: implement short --help, remove global help() function

Michael Tokarev posted 23 patches 7 months, 4 weeks ago
Maintainers: Kevin Wolf <kwolf@redhat.com>, Hanna Reitz <hreitz@redhat.com>
[PATCH 22/23] qemu-img: implement short --help, remove global help() function
Posted by Michael Tokarev 7 months, 4 weeks ago
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 74 chars.

Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
---
 qemu-img.c | 148 +++++++++++------------------------------------------
 1 file changed, 30 insertions(+), 118 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index e2c8855ff5..d9c5c6078b 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -94,11 +94,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 G_GNUC_PRINTF(2, 3)
 void error_exit(const img_cmd_t *ccmd, const char *fmt, ...)
 {
@@ -154,114 +149,6 @@ static OutputFormat parse_output_format(const img_cmd_t *ccmd, 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 ','.
@@ -5866,6 +5753,16 @@ static const img_cmd_t img_cmds[] = {
     { NULL, NULL, },
 };
 
+static void format_print(void *opaque, const char *name)
+{
+    int *np = opaque;
+    *np += printf(" %s", name);
+    if (*np > 74) {
+        printf("\n ");
+        *np = 1;
+    }
+}
+
 int main(int argc, char **argv)
 {
     const img_cmd_t *cmd;
@@ -5893,10 +5790,6 @@ int main(int argc, char **argv)
 
     module_call_init(MODULE_INIT_QOM);
     bdrv_init();
-    if (argc < 2) {
-        error_exit(NULL, "Not enough arguments");
-    }
-
     qemu_add_opts(&qemu_source_opts);
     qemu_add_opts(&qemu_trace_opts);
 
@@ -5909,7 +5802,22 @@ int main(int argc, char **argv)
             unrecognized_option(NULL, argv[optind - 1]);
             return 0;
         case 'h':
-            help();
+            printf(
+QEMU_IMG_VERSION
+"QEMU disk image utility\n"
+"usage: qemu-img [standard options] command [--help | command options]\n"
+"Standard options:\n"
+" -h|--help - display this help and exit\n"
+" -V|--version - display version info and exit\n"
+" -T|--trace TRACE - specify tracing options:\n"
+"   [[enable=]<pattern>][,events=<file>][,file=<file>]\n"
+"Recognized commands (run qemu-img command --help for command-specific help):\n");
+            for (cmd = img_cmds; cmd->name != NULL; cmd++) {
+                printf("  %s\n", cmd->name);
+            }
+            c = printf("Supported image formats:");
+            bdrv_iterate_format(format_print, &c, false);
+            printf("\n" QEMU_HELP_BOTTOM "\n");
             return 0;
         case 'V':
             printf(QEMU_IMG_VERSION);
@@ -5920,6 +5828,10 @@ int main(int argc, char **argv)
         }
     }
 
+    if (argc < 2) {
+        error_exit(NULL, "Not enough arguments");
+    }
+
     cmdname = argv[optind];
 
     /* reset getopt_long scanning */
-- 
2.39.2
Re: [PATCH 22/23] qemu-img: implement short --help, remove global help() function
Posted by Daniel P. Berrangé 7 months, 2 weeks ago
On Sat, Feb 10, 2024 at 12:22:43AM +0300, Michael Tokarev wrote:
> 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 74 chars.
> 
> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
> ---
>  qemu-img.c | 148 +++++++++++------------------------------------------
>  1 file changed, 30 insertions(+), 118 deletions(-)
> 
> diff --git a/qemu-img.c b/qemu-img.c
> index e2c8855ff5..d9c5c6078b 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -94,11 +94,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 G_GNUC_PRINTF(2, 3)
>  void error_exit(const img_cmd_t *ccmd, const char *fmt, ...)
>  {
> @@ -154,114 +149,6 @@ static OutputFormat parse_output_format(const img_cmd_t *ccmd, 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 ','.
> @@ -5866,6 +5753,16 @@ static const img_cmd_t img_cmds[] = {
>      { NULL, NULL, },
>  };
>  
> +static void format_print(void *opaque, const char *name)
> +{
> +    int *np = opaque;
> +    *np += printf(" %s", name);
> +    if (*np > 74) {
> +        printf("\n ");
> +        *np = 1;
> +    }
> +}
> +
>  int main(int argc, char **argv)
>  {
>      const img_cmd_t *cmd;
> @@ -5893,10 +5790,6 @@ int main(int argc, char **argv)
>  
>      module_call_init(MODULE_INIT_QOM);
>      bdrv_init();
> -    if (argc < 2) {
> -        error_exit(NULL, "Not enough arguments");
> -    }
> -
>      qemu_add_opts(&qemu_source_opts);
>      qemu_add_opts(&qemu_trace_opts);
>  
> @@ -5909,7 +5802,22 @@ int main(int argc, char **argv)
>              unrecognized_option(NULL, argv[optind - 1]);
>              return 0;
>          case 'h':
> -            help();
> +            printf(
> +QEMU_IMG_VERSION
> +"QEMU disk image utility\n"

Add '\n'

> +"usage: qemu-img [standard options] command [--help | command options]\n"

Add '\n'

> +"Standard options:\n"

Add '\n'

> +" -h|--help - display this help and exit\n"
> +" -V|--version - display version info and exit\n"
> +" -T|--trace TRACE - specify tracing options:\n"
> +"   [[enable=]<pattern>][,events=<file>][,file=<file>]\n"

Similar to sub-command help, I tink it reads better as

 "  -h|--help\n"
 "      display this help and exit\n"
 "\n"
 "  -V|--version\n"
 "      display version info and exit\n"
 "\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");
> +            for (cmd = img_cmds; cmd->name != NULL; cmd++) {
> +                printf("  %s\n", cmd->name);
> +            }

An extra "\n"

> +            c = printf("Supported image formats:");

Add a trailing "\n"

> +            bdrv_iterate_format(format_print, &c, false);
> +            printf("\n" QEMU_HELP_BOTTOM "\n");
>              return 0;
>          case 'V':
>              printf(QEMU_IMG_VERSION);
> @@ -5920,6 +5828,10 @@ int main(int argc, char **argv)
>          }
>      }
>  
> +    if (argc < 2) {
> +        error_exit(NULL, "Not enough arguments");
> +    }
> +
>      cmdname = argv[optind];
>  
>      /* reset getopt_long scanning */

Basically as an end result we get



qemu-img version 8.2.50 (v8.2.0-1219-g51870ffcbb)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
QEMU disk image utility

usage: qemu-img [standard options] command [--help | command options]

Standard options:

  -h|--help
      display this help and exit
  -V|--version
      display version info and exit
  -T|--trace TRACE
      specify tracing options:
      [[enable=]<pattern>][,events=<file>][,file=<file>]

Recognized commands (run qemu-img command --help for command-specific help):

  amend - Update format-specific options of the image
  bench - Run simple image benchmark
  bitmap - Perform modifications of the persistent bitmap in the image
  check - Check basic image integrity
  commit - Commit image to its backing file
  compare - Check if two images have the same contents
  convert - Copy one image to another with optional format conversion
  create - Create and format new image file
  dd - Copy input to output with optional format conversion
  info - Display information about image
  map - Dump image metadata
  measure - Calculate file size requred for a new image
  rebase - Change backing file of the image
  resize - Resize the image to the new size
  snapshot - List or manipulate snapshots within image

Supported image formats:
  blkdebug blklogwrites blkverify bochs cloop compress copy-before-write
  copy-on-read dmg file ftp ftps gluster host_cdrom host_device http
  https io_uring iscsi iser luks nbd nfs null-aio null-co nvme nvme-io_uring
  parallels preallocate qcow qcow2 qed quorum raw rbd replication snapshot-access
  ssh throttle vdi vhdx virtio-blk-vfio-pci virtio-blk-vhost-user virtio-blk-vhost-vdpa
  vmdk vpc vvfat

See <https://qemu.org/contribute/report-a-bug> for how to report bugs.
More information on the QEMU project at <https://qemu.org>.


With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|