qemu-img: allow specifying image as a set of options args

Currently qemu-img allows an image filename to be passed on the
command line, but unless using the JSON format, it does not have
a way to set any options except the format eg

   qemu-img info https://127.0.0.1/images/centos7.iso

This adds a --image-opts arg that indicates that the positional
filename should be interpreted as a full option string, not
just a filename.

   qemu-img info --image-opts driver=https,url=https://127.0.0.1/images,sslverify=off

This flag is mutually exclusive with the '-f' / '-F' flags.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
Daniel P. Berrange 2016-02-17 10:10:20 +00:00 committed by Kevin Wolf
parent 77c9aaefd7
commit eb769f7420
3 changed files with 195 additions and 60 deletions

View file

@ -10,68 +10,68 @@ STEXI
ETEXI ETEXI
DEF("check", img_check, DEF("check", img_check,
"check [-q] [--object objectdef] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename") "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
STEXI STEXI
@item check [--object @var{objectdef}] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename} @item check [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
ETEXI ETEXI
DEF("create", img_create, DEF("create", img_create,
"create [-q] [--object objectdef] [-f fmt] [-o options] filename [size]") "create [-q] [--object objectdef] [--image-opts] [-f fmt] [-o options] filename [size]")
STEXI STEXI
@item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] @item create [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
ETEXI ETEXI
DEF("commit", img_commit, DEF("commit", img_commit,
"commit [-q] [--object objectdef] [-f fmt] [-t cache] [-b base] [-d] [-p] filename") "commit [-q] [--object objectdef] [--image-opts] [-f fmt] [-t cache] [-b base] [-d] [-p] filename")
STEXI STEXI
@item commit [--object @var{objectdef}] [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename} @item commit [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename}
ETEXI ETEXI
DEF("compare", img_compare, DEF("compare", img_compare,
"compare [--object objectdef] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2") "compare [--object objectdef] [--image-opts] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2")
STEXI STEXI
@item compare [--object @var{objectdef}] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2} @item compare [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2}
ETEXI ETEXI
DEF("convert", img_convert, DEF("convert", img_convert,
"convert [--object objectdef] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename") "convert [--object objectdef] [--image-opts] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename")
STEXI STEXI
@item convert [--object @var{objectdef}] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename} @item convert [--object @var{objectdef}] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
ETEXI ETEXI
DEF("info", img_info, DEF("info", img_info,
"info [--object objectdef] [-f fmt] [--output=ofmt] [--backing-chain] filename") "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] filename")
STEXI STEXI
@item info [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} @item info [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename}
ETEXI ETEXI
DEF("map", img_map, DEF("map", img_map,
"map [--object objectdef] [-f fmt] [--output=ofmt] filename") "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] filename")
STEXI STEXI
@item map [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} @item map [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
ETEXI ETEXI
DEF("snapshot", img_snapshot, DEF("snapshot", img_snapshot,
"snapshot [--object objectdef] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") "snapshot [--object objectdef] [--image-opts] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
STEXI STEXI
@item snapshot [--object @var{objectdef}] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename} @item snapshot [--object @var{objectdef}] [--image-opts] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename}
ETEXI ETEXI
DEF("rebase", img_rebase, DEF("rebase", img_rebase,
"rebase [--object objectdef] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") "rebase [--object objectdef] [--image-opts] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
STEXI STEXI
@item rebase [--object @var{objectdef}] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename} @item rebase [--object @var{objectdef}] [--image-opts] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
ETEXI ETEXI
DEF("resize", img_resize, DEF("resize", img_resize,
"resize [--object objectdef] [-q] filename [+ | -]size") "resize [--object objectdef] [--image-opts] [-q] filename [+ | -]size")
STEXI STEXI
@item resize [--object @var{objectdef}] [-q] @var{filename} [+ | -]@var{size} @item resize [--object @var{objectdef}] [--image-opts] [-q] @var{filename} [+ | -]@var{size}
ETEXI ETEXI
DEF("amend", img_amend, DEF("amend", img_amend,
"amend [--object objectdef] [-p] [-q] [-f fmt] [-t cache] -o options filename") "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename")
STEXI STEXI
@item amend [--object @var{objectdef}] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} @item amend [--object @var{objectdef}] [--image-opts] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
@end table @end table
ETEXI ETEXI

View file

@ -50,6 +50,7 @@ enum {
OPTION_OUTPUT = 256, OPTION_OUTPUT = 256,
OPTION_BACKING_CHAIN = 257, OPTION_BACKING_CHAIN = 257,
OPTION_OBJECT = 258, OPTION_OBJECT = 258,
OPTION_IMAGE_OPTS = 259,
}; };
typedef enum OutputFormat { typedef enum OutputFormat {
@ -170,6 +171,15 @@ static QemuOptsList qemu_object_opts = {
}, },
}; };
static QemuOptsList qemu_source_opts = {
.name = "source",
.implied_opt_name = "file",
.head = QTAILQ_HEAD_INITIALIZER(qemu_source_opts.head),
.desc = {
{ }
},
};
static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...) static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
{ {
int ret = 0; int ret = 0;
@ -212,13 +222,56 @@ static int print_block_option_help(const char *filename, const char *fmt)
return 0; return 0;
} }
static BlockBackend *img_open(const char *id, const char *filename,
const char *fmt, int flags, static int img_open_password(BlockBackend *blk, const char *filename,
bool require_io, bool quiet) bool require_io, bool quiet)
{ {
BlockBackend *blk;
BlockDriverState *bs; BlockDriverState *bs;
char password[256]; char password[256];
bs = blk_bs(blk);
if (bdrv_is_encrypted(bs) && require_io) {
qprintf(quiet, "Disk image '%s' is encrypted.\n", filename);
if (qemu_read_password(password, sizeof(password)) < 0) {
error_report("No password given");
return -1;
}
if (bdrv_set_key(bs, password) < 0) {
error_report("invalid password");
return -1;
}
}
return 0;
}
static BlockBackend *img_open_opts(const char *id,
const char *optstr,
QemuOpts *opts, int flags,
bool require_io, bool quiet)
{
QDict *options;
Error *local_err = NULL;
BlockBackend *blk;
options = qemu_opts_to_qdict(opts, NULL);
blk = blk_new_open(id, NULL, NULL, options, flags, &local_err);
if (!blk) {
error_reportf_err(local_err, "Could not open '%s'", optstr);
return NULL;
}
if (img_open_password(blk, optstr, require_io, quiet) < 0) {
blk_unref(blk);
return NULL;
}
return blk;
}
static BlockBackend *img_open_file(const char *id, const char *filename,
const char *fmt, int flags,
bool require_io, bool quiet)
{
BlockBackend *blk;
Error *local_err = NULL; Error *local_err = NULL;
QDict *options = NULL; QDict *options = NULL;
@ -230,27 +283,43 @@ static BlockBackend *img_open(const char *id, const char *filename,
blk = blk_new_open(id, filename, NULL, options, flags, &local_err); blk = blk_new_open(id, filename, NULL, options, flags, &local_err);
if (!blk) { if (!blk) {
error_reportf_err(local_err, "Could not open '%s': ", filename); error_reportf_err(local_err, "Could not open '%s': ", filename);
goto fail; return NULL;
} }
bs = blk_bs(blk); if (img_open_password(blk, filename, require_io, quiet) < 0) {
if (bdrv_is_encrypted(bs) && require_io) { blk_unref(blk);
qprintf(quiet, "Disk image '%s' is encrypted.\n", filename); return NULL;
if (qemu_read_password(password, sizeof(password)) < 0) {
error_report("No password given");
goto fail;
}
if (bdrv_set_key(bs, password) < 0) {
error_report("invalid password");
goto fail;
}
} }
return blk; return blk;
fail:
blk_unref(blk);
return NULL;
} }
static BlockBackend *img_open(const char *id,
bool image_opts,
const char *filename,
const char *fmt, int flags,
bool require_io, bool quiet)
{
BlockBackend *blk;
if (image_opts) {
QemuOpts *opts;
if (fmt) {
error_report("--image-opts and --format are mutually exclusive");
return NULL;
}
opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
filename, true);
if (!opts) {
return NULL;
}
blk = img_open_opts(id, filename, opts, flags, true, quiet);
} else {
blk = img_open_file(id, filename, fmt, flags, true, quiet);
}
return blk;
}
static int add_old_style_options(const char *fmt, QemuOpts *opts, static int add_old_style_options(const char *fmt, QemuOpts *opts,
const char *base_filename, const char *base_filename,
const char *base_fmt) const char *base_fmt)
@ -527,6 +596,7 @@ static int img_check(int argc, char **argv)
ImageCheck *check; ImageCheck *check;
bool quiet = false; bool quiet = false;
Error *local_err = NULL; Error *local_err = NULL;
bool image_opts = false;
fmt = NULL; fmt = NULL;
output = NULL; output = NULL;
@ -539,6 +609,7 @@ static int img_check(int argc, char **argv)
{"repair", required_argument, 0, 'r'}, {"repair", required_argument, 0, 'r'},
{"output", required_argument, 0, OPTION_OUTPUT}, {"output", required_argument, 0, OPTION_OUTPUT},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "hf:r:T:q", c = getopt_long(argc, argv, "hf:r:T:q",
@ -583,6 +654,9 @@ static int img_check(int argc, char **argv)
return 1; return 1;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
@ -612,7 +686,7 @@ static int img_check(int argc, char **argv)
return 1; return 1;
} }
blk = img_open("image", filename, fmt, flags, true, quiet); blk = img_open("image", image_opts, filename, fmt, flags, true, quiet);
if (!blk) { if (!blk) {
return 1; return 1;
} }
@ -724,6 +798,7 @@ static int img_commit(int argc, char **argv)
bool progress = false, quiet = false, drop = false; bool progress = false, quiet = false, drop = false;
Error *local_err = NULL; Error *local_err = NULL;
CommonBlockJobCBInfo cbi; CommonBlockJobCBInfo cbi;
bool image_opts = false;
fmt = NULL; fmt = NULL;
cache = BDRV_DEFAULT_CACHE; cache = BDRV_DEFAULT_CACHE;
@ -732,6 +807,7 @@ static int img_commit(int argc, char **argv)
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "f:ht:b:dpq", c = getopt_long(argc, argv, "f:ht:b:dpq",
@ -772,6 +848,9 @@ static int img_commit(int argc, char **argv)
return 1; return 1;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
@ -799,7 +878,7 @@ static int img_commit(int argc, char **argv)
return 1; return 1;
} }
blk = img_open("image", filename, fmt, flags, true, quiet); blk = img_open("image", image_opts, filename, fmt, flags, true, quiet);
if (!blk) { if (!blk) {
return 1; return 1;
} }
@ -1049,12 +1128,14 @@ static int img_compare(int argc, char **argv)
int c, pnum; int c, pnum;
uint64_t progress_base; uint64_t progress_base;
Error *local_err = NULL; Error *local_err = NULL;
bool image_opts = false;
cache = BDRV_DEFAULT_CACHE; cache = BDRV_DEFAULT_CACHE;
for (;;) { for (;;) {
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "hf:F:T:pqs", c = getopt_long(argc, argv, "hf:F:T:pqs",
@ -1094,6 +1175,9 @@ static int img_compare(int argc, char **argv)
goto out4; goto out4;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
@ -1128,18 +1212,18 @@ static int img_compare(int argc, char **argv)
goto out3; goto out3;
} }
blk1 = img_open("image_1", filename1, fmt1, flags, true, quiet); blk1 = img_open("image_1", image_opts, filename1, fmt1, flags, true, quiet);
if (!blk1) { if (!blk1) {
ret = 2; ret = 2;
goto out3; goto out3;
} }
bs1 = blk_bs(blk1);
blk2 = img_open("image_2", filename2, fmt2, flags, true, quiet); blk2 = img_open("image_2", image_opts, filename2, fmt2, flags, true, quiet);
if (!blk2) { if (!blk2) {
ret = 2; ret = 2;
goto out2; goto out2;
} }
bs1 = blk_bs(blk1);
bs2 = blk_bs(blk2); bs2 = blk_bs(blk2);
buf1 = blk_blockalign(blk1, IO_BUF_SIZE); buf1 = blk_blockalign(blk1, IO_BUF_SIZE);
@ -1646,6 +1730,7 @@ static int img_convert(int argc, char **argv)
Error *local_err = NULL; Error *local_err = NULL;
QemuOpts *sn_opts = NULL; QemuOpts *sn_opts = NULL;
ImgConvertState state; ImgConvertState state;
bool image_opts = false;
fmt = NULL; fmt = NULL;
out_fmt = "raw"; out_fmt = "raw";
@ -1658,6 +1743,7 @@ static int img_convert(int argc, char **argv)
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn", c = getopt_long(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn",
@ -1759,6 +1845,9 @@ static int img_convert(int argc, char **argv)
goto fail_getopt; goto fail_getopt;
} }
break; break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
@ -1775,7 +1864,6 @@ static int img_convert(int argc, char **argv)
} }
qemu_progress_init(progress, 1.0); qemu_progress_init(progress, 1.0);
bs_n = argc - optind - 1; bs_n = argc - optind - 1;
out_filename = bs_n >= 1 ? argv[argc - 1] : NULL; out_filename = bs_n >= 1 ? argv[argc - 1] : NULL;
@ -1813,8 +1901,8 @@ static int img_convert(int argc, char **argv)
for (bs_i = 0; bs_i < bs_n; bs_i++) { for (bs_i = 0; bs_i < bs_n; bs_i++) {
char *id = bs_n > 1 ? g_strdup_printf("source_%d", bs_i) char *id = bs_n > 1 ? g_strdup_printf("source_%d", bs_i)
: g_strdup("source"); : g_strdup("source");
blk[bs_i] = img_open(id, argv[optind + bs_i], fmt, src_flags, blk[bs_i] = img_open(id, image_opts, argv[optind + bs_i],
true, quiet); fmt, src_flags, true, quiet);
g_free(id); g_free(id);
if (!blk[bs_i]) { if (!blk[bs_i]) {
ret = -1; ret = -1;
@ -1955,7 +2043,13 @@ static int img_convert(int argc, char **argv)
goto out; goto out;
} }
out_blk = img_open("target", out_filename, out_fmt, flags, true, quiet); /* XXX we should allow --image-opts to trigger use of
* img_open() here, but then we have trouble with
* the bdrv_create() call which takes different params.
* Not critical right now, so fix can wait...
*/
out_blk = img_open_file("target", out_filename,
out_fmt, flags, true, quiet);
if (!out_blk) { if (!out_blk) {
ret = -1; ret = -1;
goto out; goto out;
@ -2121,7 +2215,8 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
* image file. If there was an error a message will have been printed to * image file. If there was an error a message will have been printed to
* stderr. * stderr.
*/ */
static ImageInfoList *collect_image_info_list(const char *filename, static ImageInfoList *collect_image_info_list(bool image_opts,
const char *filename,
const char *fmt, const char *fmt,
bool chain) bool chain)
{ {
@ -2145,8 +2240,9 @@ static ImageInfoList *collect_image_info_list(const char *filename,
} }
g_hash_table_insert(filenames, (gpointer)filename, NULL); g_hash_table_insert(filenames, (gpointer)filename, NULL);
blk = img_open("image", filename, fmt, blk = img_open("image", image_opts, filename, fmt,
BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false); BDRV_O_FLAGS | BDRV_O_NO_BACKING,
false, false);
if (!blk) { if (!blk) {
goto err; goto err;
} }
@ -2198,6 +2294,7 @@ static int img_info(int argc, char **argv)
const char *filename, *fmt, *output; const char *filename, *fmt, *output;
ImageInfoList *list; ImageInfoList *list;
Error *local_err = NULL; Error *local_err = NULL;
bool image_opts = false;
fmt = NULL; fmt = NULL;
output = NULL; output = NULL;
@ -2209,6 +2306,7 @@ static int img_info(int argc, char **argv)
{"output", required_argument, 0, OPTION_OUTPUT}, {"output", required_argument, 0, OPTION_OUTPUT},
{"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN}, {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "f:h", c = getopt_long(argc, argv, "f:h",
@ -2238,6 +2336,9 @@ static int img_info(int argc, char **argv)
return 1; return 1;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
@ -2261,7 +2362,7 @@ static int img_info(int argc, char **argv)
return 1; return 1;
} }
list = collect_image_info_list(filename, fmt, chain); list = collect_image_info_list(image_opts, filename, fmt, chain);
if (!list) { if (!list) {
return 1; return 1;
} }
@ -2407,6 +2508,7 @@ static int img_map(int argc, char **argv)
MapEntry curr = { .length = 0 }, next; MapEntry curr = { .length = 0 }, next;
int ret = 0; int ret = 0;
Error *local_err = NULL; Error *local_err = NULL;
bool image_opts = false;
fmt = NULL; fmt = NULL;
output = NULL; output = NULL;
@ -2417,6 +2519,7 @@ static int img_map(int argc, char **argv)
{"format", required_argument, 0, 'f'}, {"format", required_argument, 0, 'f'},
{"output", required_argument, 0, OPTION_OUTPUT}, {"output", required_argument, 0, OPTION_OUTPUT},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "f:h", c = getopt_long(argc, argv, "f:h",
@ -2443,6 +2546,9 @@ static int img_map(int argc, char **argv)
return 1; return 1;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
@ -2466,7 +2572,8 @@ static int img_map(int argc, char **argv)
return 1; return 1;
} }
blk = img_open("image", filename, fmt, BDRV_O_FLAGS, true, false); blk = img_open("image", image_opts, filename, fmt,
BDRV_O_FLAGS, true, false);
if (!blk) { if (!blk) {
return 1; return 1;
} }
@ -2528,6 +2635,7 @@ static int img_snapshot(int argc, char **argv)
qemu_timeval tv; qemu_timeval tv;
bool quiet = false; bool quiet = false;
Error *err = NULL; Error *err = NULL;
bool image_opts = false;
bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR; bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
/* Parse commandline parameters */ /* Parse commandline parameters */
@ -2535,6 +2643,7 @@ static int img_snapshot(int argc, char **argv)
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "la:c:d:hq", c = getopt_long(argc, argv, "la:c:d:hq",
@ -2590,6 +2699,9 @@ static int img_snapshot(int argc, char **argv)
return 1; return 1;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
@ -2606,7 +2718,8 @@ static int img_snapshot(int argc, char **argv)
} }
/* Open the image */ /* Open the image */
blk = img_open("image", filename, NULL, bdrv_oflags, true, quiet); blk = img_open("image", image_opts, filename, NULL,
bdrv_oflags, true, quiet);
if (!blk) { if (!blk) {
return 1; return 1;
} }
@ -2670,6 +2783,7 @@ static int img_rebase(int argc, char **argv)
int progress = 0; int progress = 0;
bool quiet = false; bool quiet = false;
Error *local_err = NULL; Error *local_err = NULL;
bool image_opts = false;
/* Parse commandline parameters */ /* Parse commandline parameters */
fmt = NULL; fmt = NULL;
@ -2681,6 +2795,7 @@ static int img_rebase(int argc, char **argv)
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "hf:F:b:upt:T:q", c = getopt_long(argc, argv, "hf:F:b:upt:T:q",
@ -2725,6 +2840,9 @@ static int img_rebase(int argc, char **argv)
return 1; return 1;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
@ -2770,7 +2888,7 @@ static int img_rebase(int argc, char **argv)
* Ignore the old backing file for unsafe rebase in case we want to correct * Ignore the old backing file for unsafe rebase in case we want to correct
* the reference to a renamed or moved backing file. * the reference to a renamed or moved backing file.
*/ */
blk = img_open("image", filename, fmt, flags, true, quiet); blk = img_open("image", image_opts, filename, fmt, flags, true, quiet);
if (!blk) { if (!blk) {
ret = -1; ret = -1;
goto out; goto out;
@ -3022,6 +3140,7 @@ static int img_resize(int argc, char **argv)
} }
}, },
}; };
bool image_opts = false;
/* Remove size from argv manually so that negative numbers are not treated /* Remove size from argv manually so that negative numbers are not treated
* as options by getopt. */ * as options by getopt. */
@ -3038,6 +3157,7 @@ static int img_resize(int argc, char **argv)
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "f:hq", c = getopt_long(argc, argv, "f:hq",
@ -3064,6 +3184,9 @@ static int img_resize(int argc, char **argv)
return 1; return 1;
} }
} break; } break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
@ -3105,8 +3228,8 @@ static int img_resize(int argc, char **argv)
n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0); n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
qemu_opts_del(param); qemu_opts_del(param);
blk = img_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, blk = img_open("image", image_opts, filename, fmt,
true, quiet); BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
if (!blk) { if (!blk) {
ret = -1; ret = -1;
goto out; goto out;
@ -3166,12 +3289,14 @@ static int img_amend(int argc, char **argv)
BlockBackend *blk = NULL; BlockBackend *blk = NULL;
BlockDriverState *bs = NULL; BlockDriverState *bs = NULL;
Error *local_err = NULL; Error *local_err = NULL;
bool image_opts = false;
cache = BDRV_DEFAULT_CACHE; cache = BDRV_DEFAULT_CACHE;
for (;;) { for (;;) {
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT}, {"object", required_argument, 0, OPTION_OBJECT},
{"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "ho:f:t:pq", c = getopt_long(argc, argv, "ho:f:t:pq",
@ -3219,6 +3344,9 @@ static int img_amend(int argc, char **argv)
goto out_no_progress; goto out_no_progress;
} }
break; break;
case OPTION_IMAGE_OPTS:
image_opts = true;
break;
} }
} }
@ -3260,7 +3388,7 @@ static int img_amend(int argc, char **argv)
goto out; goto out;
} }
blk = img_open("image", filename, fmt, flags, true, quiet); blk = img_open("image", image_opts, filename, fmt, flags, true, quiet);
if (!blk) { if (!blk) {
ret = -1; ret = -1;
goto out; goto out;
@ -3358,6 +3486,7 @@ int main(int argc, char **argv)
cmdname = argv[1]; cmdname = argv[1];
qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_object_opts);
qemu_add_opts(&qemu_source_opts);
/* find the command */ /* find the command */
for (cmd = img_cmds; cmd->name != NULL; cmd++) { for (cmd = img_cmds; cmd->name != NULL; cmd++) {

View file

@ -32,6 +32,12 @@ page for a description of the object properties. The most common object
type is a @code{secret}, which is used to supply passwords and/or encryption type is a @code{secret}, which is used to supply passwords and/or encryption
keys. keys.
@item --image-opts
Indicates that the @var{filename} parameter is to be interpreted as a
full option string, not a plain filename. This parameter is mutually
exclusive with the @var{-f} and @var{-F} parameters.
@item fmt @item fmt
is the disk image format. It is guessed automatically in most cases. See below is the disk image format. It is guessed automatically in most cases. See below
for a description of the supported disk formats. for a description of the supported disk formats.