@@ -69,8 +69,8 @@ enum {
};
typedef enum OutputFormat {
- OFORMAT_JSON,
OFORMAT_HUMAN,
+ OFORMAT_JSON,
} OutputFormat;
/* Default to cache=writeback as data integrity is not important for qemu-img */
@@ -2728,96 +2728,122 @@ static inline bool entry_mergeable(const MapEntry *curr, const MapEntry *next)
return true;
}
+typedef struct CommonOpts {
+ OutputFormat output_format;
+ const char *filename;
+ const char *fmt;
+ bool force_share;
+ bool image_opts;
+} CommonOpts;
+
+static int parse_opts_common(CommonOpts *opts, int argc, char **argv)
+{
+ int c;
+
+ 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'},
+ {0, 0, 0, 0}
+ };
+ c = getopt_long(argc, argv, ":f:hU",
+ 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();
+ break;
+ case 'f':
+ opts->fmt = optarg;
+ break;
+ case 'U':
+ opts->force_share = true;
+ break;
+ case OPTION_OUTPUT:
+ if (optarg && !strcmp(optarg, "json")) {
+ opts->output_format = OFORMAT_JSON;
+ } else if (optarg && !strcmp(optarg, "human")) {
+ opts->output_format = OFORMAT_HUMAN;
+ } else {
+ error_report("--output must be used with human or json as argument.");
+ return -EINVAL;
+ }
+ break;
+ case OPTION_OBJECT: {
+ QemuOpts *opts;
+ opts = qemu_opts_parse_noisily(&qemu_object_opts,
+ optarg, true);
+ if (!opts) {
+ return -EINVAL;
+ }
+ } break;
+ case OPTION_IMAGE_OPTS:
+ opts->image_opts = true;
+ break;
+ }
+ }
+ if (qemu_opts_foreach(&qemu_object_opts,
+ user_creatable_add_opts_foreach,
+ NULL, NULL)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void parse_positional(int argc, char *argv[],
+ bool opt, const char **str, const char *name) {
+ if (!opt && optind >= argc) {
+ error_exit("Expecting '%s' positional parameter", name);
+ } else if (optind < argc) {
+ *str = argv[optind++];
+ }
+}
+
+static void parse_unexpected(int argc, char *argv[]) {
+ if (optind != argc) {
+ error_exit("Unexpected argument '%s'\n", argv[optind]);
+ }
+}
+
static int img_map(int argc, char **argv)
{
- int c;
- OutputFormat output_format = OFORMAT_HUMAN;
BlockBackend *blk;
BlockDriverState *bs;
- const char *filename, *fmt, *output;
int64_t length;
+ int ret = 0;
MapEntry curr = { .length = 0 }, next;
- int ret = 0;
- bool image_opts = false;
- bool force_share = false;
+ CommonOpts *opts;
- fmt = NULL;
- output = 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'},
- {0, 0, 0, 0}
- };
- c = getopt_long(argc, argv, ":f:hU",
- 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();
- break;
- case 'f':
- fmt = optarg;
- break;
- case 'U':
- force_share = true;
- break;
- case OPTION_OUTPUT:
- output = optarg;
- break;
- case OPTION_OBJECT: {
- QemuOpts *opts;
- opts = qemu_opts_parse_noisily(&qemu_object_opts,
- optarg, true);
- if (!opts) {
- return 1;
- }
- } break;
- case OPTION_IMAGE_OPTS:
- image_opts = true;
- break;
- }
- }
- if (optind != argc - 1) {
- error_exit("Expecting one image file name");
- }
- 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;
- }
-
- if (qemu_opts_foreach(&qemu_object_opts,
- user_creatable_add_opts_foreach,
- NULL, NULL)) {
- return 1;
+ opts = g_new0(CommonOpts, 1);
+ if (parse_opts_common(opts, argc, argv)) {
+ return EXIT_FAILURE;
}
+ parse_positional(argc, argv, 0, &opts->filename, "filename");
+ parse_unexpected(argc, argv);
- blk = img_open(image_opts, filename, fmt, 0, false, false, force_share);
+ blk = img_open(opts->image_opts, opts->filename, opts->fmt, 0,
+ false, false, opts->force_share);
if (!blk) {
- return 1;
+ ret = -1;
+ goto out1;
}
bs = blk_bs(blk);
- if (output_format == OFORMAT_HUMAN) {
+ if (opts->output_format == OFORMAT_HUMAN) {
printf("%-16s%-16s%-16s%s\n", "Offset", "Length", "Mapped to", "File");
}
@@ -2832,7 +2858,7 @@ static int img_map(int argc, char **argv)
if (ret < 0) {
error_report("Could not read file metadata: %s", strerror(-ret));
- goto out;
+ goto out2;
}
if (entry_mergeable(&curr, &next)) {
@@ -2841,15 +2867,17 @@ static int img_map(int argc, char **argv)
}
if (curr.length > 0) {
- dump_map_entry(output_format, &curr, &next);
+ dump_map_entry(opts->output_format, &curr, &next);
}
curr = next;
}
- dump_map_entry(output_format, &curr, NULL);
+ dump_map_entry(opts->output_format, &curr, NULL);
-out:
+out2:
blk_unref(blk);
+out1:
+ g_free(opts);
return ret < 0;
}
It will be re-used for a bitmap listing command. Signed-off-by: John Snow <jsnow@redhat.com> --- qemu-img.c | 192 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 110 insertions(+), 82 deletions(-)