#include "block/block_int.h"
#include "block/qapi.h"
#include <getopt.h>
+#include <glib.h>
+
+#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION \
+ ", Copyright (c) 2004-2008 Fabrice Bellard\n"
typedef struct img_cmd_t {
const char *name;
#define BDRV_O_FLAGS BDRV_O_CACHE_WB
#define BDRV_DEFAULT_CACHE "writeback"
-static void format_print(void *opaque, const char *name)
+static gint compare_data(gconstpointer a, gconstpointer b, gpointer user)
+{
+ return g_strcmp0(a, b);
+}
+
+static void print_format(gpointer data, gpointer user)
+{
+ printf(" %s", (char *)data);
+}
+
+static void add_format_to_seq(void *opaque, const char *fmt_name)
{
- printf(" %s", name);
+ GSequence *seq = opaque;
+
+ g_sequence_insert_sorted(seq, (gpointer)fmt_name,
+ compare_data, NULL);
}
static void QEMU_NORETURN GCC_FMT_ATTR(1, 2) error_exit(const char *fmt, ...)
static void QEMU_NORETURN help(void)
{
const char *help_msg =
- "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
+ QEMU_IMG_VERSION
"usage: qemu-img command [command options]\n"
"QEMU disk image utility\n"
"\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";
+ GSequence *seq;
printf("%s\nSupported formats:", help_msg);
- bdrv_iterate_format(format_print, NULL);
+ seq = g_sequence_new(NULL);
+ bdrv_iterate_format(add_format_to_seq, seq);
+ g_sequence_foreach(seq, print_format, NULL);
printf("\n");
+ g_sequence_free(seq);
+
exit(EXIT_SUCCESS);
}
static int print_block_option_help(const char *filename, const char *fmt)
{
BlockDriver *drv, *proto_drv;
- QEMUOptionParameter *create_options = NULL;
+ QemuOptsList *create_opts = NULL;
/* Find driver and parse its options */
drv = bdrv_find_format(fmt);
return 1;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
-
+ create_opts = qemu_opts_append(create_opts, drv->create_opts);
if (filename) {
proto_drv = bdrv_find_protocol(filename, true);
if (!proto_drv) {
error_report("Unknown protocol '%s'", filename);
+ qemu_opts_free(create_opts);
return 1;
}
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
}
- print_option_help(create_options);
- free_option_parameters(create_options);
+ qemu_opts_print_help(create_opts);
+ qemu_opts_free(create_opts);
return 0;
}
return NULL;
}
-static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
+static int add_old_style_options(const char *fmt, QemuOpts *opts,
const char *base_filename,
const char *base_fmt)
{
if (base_filename) {
- if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FILE, base_filename)) {
error_report("Backing file not supported for file format '%s'",
fmt);
return -1;
}
}
if (base_fmt) {
- if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
+ if (qemu_opt_set(opts, BLOCK_OPT_BACKING_FMT, base_fmt)) {
error_report("Backing file format not supported for file "
"format '%s'", fmt);
return -1;
/*
* Checks an image for consistency. Exit codes:
*
- * 0 - Check completed, image is good
- * 1 - Check not completed because of internal errors
- * 2 - Check completed, image is corrupted
- * 3 - Check completed, image has leaked clusters, but is good otherwise
+ * 0 - Check completed, image is good
+ * 1 - Check not completed because of internal errors
+ * 2 - Check completed, image is corrupted
+ * 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)
{
ret = collect_image_check(bs, check, filename, fmt, fix);
if (ret == -ENOTSUP) {
- if (output_format == OFORMAT_HUMAN) {
- error_report("This image format does not support checks");
- }
+ error_report("This image format does not support checks");
ret = 63;
goto fail;
}
size_t bufsectors = IO_BUF_SIZE / BDRV_SECTOR_SIZE;
const uint8_t *buf1;
BlockDriverInfo bdi;
- QEMUOptionParameter *param = NULL, *create_options = NULL;
- QEMUOptionParameter *out_baseimg_param;
+ QemuOpts *opts = NULL;
+ QemuOptsList *create_opts = NULL;
+ const char *out_baseimg_param;
char *options = NULL;
const char *snapshot_name = NULL;
int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
goto out;
}
- create_options = append_option_parameters(create_options,
- drv->create_options);
- create_options = append_option_parameters(create_options,
- proto_drv->create_options);
+ create_opts = qemu_opts_append(create_opts, drv->create_opts);
+ create_opts = qemu_opts_append(create_opts, proto_drv->create_opts);
- if (options) {
- param = parse_option_parameters(options, create_options, param);
- if (param == NULL) {
- error_report("Invalid options for file format '%s'.", out_fmt);
- ret = -1;
- goto out;
- }
- } else {
- param = parse_option_parameters("", create_options, param);
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ if (options && qemu_opts_do_parse(opts, options, NULL)) {
+ error_report("Invalid options for file format '%s'", out_fmt);
+ ret = -1;
+ goto out;
}
- set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
- ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
+ qemu_opt_set_number(opts, BLOCK_OPT_SIZE, total_sectors * 512);
+ ret = add_old_style_options(out_fmt, opts, out_baseimg, NULL);
if (ret < 0) {
goto out;
}
/* Get backing file name if -o backing_file was used */
- out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
+ out_baseimg_param = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
if (out_baseimg_param) {
- out_baseimg = out_baseimg_param->value.s;
+ out_baseimg = out_baseimg_param;
}
/* Check if compression is supported */
if (compress) {
- QEMUOptionParameter *encryption =
- get_option_parameter(param, BLOCK_OPT_ENCRYPT);
- QEMUOptionParameter *preallocation =
- get_option_parameter(param, BLOCK_OPT_PREALLOC);
+ bool encryption =
+ qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT, false);
+ const char *preallocation =
+ qemu_opt_get(opts, BLOCK_OPT_PREALLOC);
if (!drv->bdrv_write_compressed) {
error_report("Compression not supported for this file format");
goto out;
}
- if (encryption && encryption->value.n) {
+ if (encryption) {
error_report("Compression and encryption not supported at "
"the same time");
ret = -1;
goto out;
}
- if (preallocation && preallocation->value.s
- && strcmp(preallocation->value.s, "off"))
+ if (preallocation
+ && strcmp(preallocation, "off"))
{
error_report("Compression and preallocation not supported at "
"the same time");
if (!skip_create) {
/* Create the new image */
- ret = bdrv_create(drv, out_filename, param, &local_err);
+ ret = bdrv_create(drv, out_filename, opts, &local_err);
if (ret < 0) {
error_report("%s: error while converting %s: %s",
out_filename, out_fmt, error_get_pretty(local_err));
ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) {
error_report("Invalid cache option: %s", cache);
- return -1;
+ goto out;
}
out_bs = bdrv_new_open("target", out_filename, out_fmt, flags, true, quiet);
goto out;
}
} else {
+ compress = compress || bdi.needs_compressed_writes;
cluster_sectors = bdi.cluster_size / BDRV_SECTOR_SIZE;
}
qemu_progress_print(100, 0);
}
qemu_progress_end();
- free_option_parameters(create_options);
- free_option_parameters(param);
+ qemu_opts_del(opts);
+ qemu_opts_free(create_opts);
qemu_vfree(buf);
if (sn_opts) {
qemu_opts_del(sn_opts);
{
int c, ret = 0;
char *options = NULL;
- QEMUOptionParameter *create_options = NULL, *options_param = NULL;
+ QemuOptsList *create_opts = NULL;
+ QemuOpts *opts = NULL;
const char *fmt = NULL, *filename;
bool quiet = false;
BlockDriverState *bs = NULL;
goto out;
}
- create_options = append_option_parameters(create_options,
- bs->drv->create_options);
- options_param = parse_option_parameters(options, create_options,
- options_param);
- if (options_param == NULL) {
+ create_opts = qemu_opts_append(create_opts, bs->drv->create_opts);
+ opts = qemu_opts_create(create_opts, NULL, 0, &error_abort);
+ if (options && qemu_opts_do_parse(opts, options, NULL)) {
error_report("Invalid options for file format '%s'", fmt);
ret = -1;
goto out;
}
- ret = bdrv_amend_options(bs, options_param);
+ ret = bdrv_amend_options(bs, opts);
if (ret < 0) {
error_report("Error while amending options: %s", strerror(-ret));
goto out;
if (bs) {
bdrv_unref(bs);
}
- free_option_parameters(create_options);
- free_option_parameters(options_param);
+ qemu_opts_del(opts);
+ qemu_opts_free(create_opts);
g_free(options);
if (ret) {
{
const img_cmd_t *cmd;
const char *cmdname;
+ int c;
+ static const struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
#ifdef CONFIG_POSIX
signal(SIGPIPE, SIG_IGN);
error_exit("Not enough arguments");
}
cmdname = argv[1];
- argc--; argv++;
/* find the command */
- for(cmd = img_cmds; cmd->name != NULL; cmd++) {
+ for (cmd = img_cmds; cmd->name != NULL; cmd++) {
if (!strcmp(cmdname, cmd->name)) {
- return cmd->handler(argc, argv);
+ return cmd->handler(argc - 1, argv + 1);
}
}
+ c = getopt_long(argc, argv, "h", long_options, NULL);
+
+ if (c == 'h') {
+ help();
+ }
+ if (c == 'v') {
+ printf(QEMU_IMG_VERSION);
+ return 0;
+ }
+
/* not found */
error_exit("Command not found: %s", cmdname);
}