提交 3babeb15 编写于 作者: D Daniel P. Berrange 提交者: Kevin Wolf

qemu-img: add support for --object command line arg

Allow creation of user creatable object types with qemu-img
via a new --object command line arg. This will be used to supply
passwords and/or encryption keys to the various block driver
backends via the recently added 'secret' object type.

 # printf letmein > mypasswd.txt
 # qemu-img info --object secret,id=sec0,file=mypasswd.txt \
      ...other info args...
Reviewed-by: NEric Blake <eblake@redhat.com>
Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
Signed-off-by: NKevin Wolf <kwolf@redhat.com>
上级 9ba371b6
...@@ -10,68 +10,68 @@ STEXI ...@@ -10,68 +10,68 @@ STEXI
ETEXI ETEXI
DEF("check", img_check, DEF("check", img_check,
"check [-q] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename") "check [-q] [--object objectdef] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
STEXI STEXI
@item check [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename} @item check [--object @var{objectdef}] [-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] [-f fmt] [-o options] filename [size]") "create [-q] [--object objectdef] [-f fmt] [-o options] filename [size]")
STEXI STEXI
@item create [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}] @item create [--object @var{objectdef}] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
ETEXI ETEXI
DEF("commit", img_commit, DEF("commit", img_commit,
"commit [-q] [-f fmt] [-t cache] [-b base] [-d] [-p] filename") "commit [-q] [--object objectdef] [-f fmt] [-t cache] [-b base] [-d] [-p] filename")
STEXI STEXI
@item commit [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename} @item commit [--object @var{objectdef}] [-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 [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2") "compare [--object objectdef] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2")
STEXI STEXI
@item compare [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2} @item compare [--object @var{objectdef}] [-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 [-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] [-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 [-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}] [-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 [-f fmt] [--output=ofmt] [--backing-chain] filename") "info [--object objectdef] [-f fmt] [--output=ofmt] [--backing-chain] filename")
STEXI STEXI
@item info [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename} @item info [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename}
ETEXI ETEXI
DEF("map", img_map, DEF("map", img_map,
"map [-f fmt] [--output=ofmt] filename") "map [--object objectdef] [-f fmt] [--output=ofmt] filename")
STEXI STEXI
@item map [-f @var{fmt}] [--output=@var{ofmt}] @var{filename} @item map [--object @var{objectdef}] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
ETEXI ETEXI
DEF("snapshot", img_snapshot, DEF("snapshot", img_snapshot,
"snapshot [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename") "snapshot [--object objectdef] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
STEXI STEXI
@item snapshot [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename} @item snapshot [--object @var{objectdef}] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename}
ETEXI ETEXI
DEF("rebase", img_rebase, DEF("rebase", img_rebase,
"rebase [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename") "rebase [--object objectdef] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
STEXI STEXI
@item rebase [-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}] [-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 [-q] filename [+ | -]size") "resize [--object objectdef] [-q] filename [+ | -]size")
STEXI STEXI
@item resize [-q] @var{filename} [+ | -]@var{size} @item resize [--object @var{objectdef}] [-q] @var{filename} [+ | -]@var{size}
ETEXI ETEXI
DEF("amend", img_amend, DEF("amend", img_amend,
"amend [-p] [-q] [-f fmt] [-t cache] -o options filename") "amend [--object objectdef] [-p] [-q] [-f fmt] [-t cache] -o options filename")
STEXI STEXI
@item amend [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename} @item amend [--object @var{objectdef}] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
@end table @end table
ETEXI ETEXI
...@@ -27,8 +27,10 @@ ...@@ -27,8 +27,10 @@
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "qemu/config-file.h"
#include "qemu/option.h" #include "qemu/option.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qom/object_interfaces.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "block/block_int.h" #include "block/block_int.h"
...@@ -47,6 +49,7 @@ typedef struct img_cmd_t { ...@@ -47,6 +49,7 @@ typedef struct img_cmd_t {
enum { enum {
OPTION_OUTPUT = 256, OPTION_OUTPUT = 256,
OPTION_BACKING_CHAIN = 257, OPTION_BACKING_CHAIN = 257,
OPTION_OBJECT = 258,
}; };
typedef enum OutputFormat { typedef enum OutputFormat {
...@@ -94,6 +97,10 @@ static void QEMU_NORETURN help(void) ...@@ -94,6 +97,10 @@ static void QEMU_NORETURN help(void)
"\n" "\n"
"Command parameters:\n" "Command parameters:\n"
" 'filename' is a disk image filename\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" " '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" " '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" " options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
...@@ -154,6 +161,15 @@ static void QEMU_NORETURN help(void) ...@@ -154,6 +161,15 @@ static void QEMU_NORETURN help(void)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
static QemuOptsList qemu_object_opts = {
.name = "object",
.implied_opt_name = "qom-type",
.head = QTAILQ_HEAD_INITIALIZER(qemu_object_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;
...@@ -275,7 +291,13 @@ static int img_create(int argc, char **argv) ...@@ -275,7 +291,13 @@ static int img_create(int argc, char **argv)
bool quiet = false; bool quiet = false;
for(;;) { for(;;) {
c = getopt(argc, argv, "F:b:f:he6o:q"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "F:b:f:he6o:q",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -317,6 +339,14 @@ static int img_create(int argc, char **argv) ...@@ -317,6 +339,14 @@ static int img_create(int argc, char **argv)
case 'q': case 'q':
quiet = true; quiet = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
goto fail;
}
} break;
} }
} }
...@@ -332,6 +362,13 @@ static int img_create(int argc, char **argv) ...@@ -332,6 +362,13 @@ static int img_create(int argc, char **argv)
} }
optind++; optind++;
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
goto fail;
}
/* Get image size, if specified */ /* Get image size, if specified */
if (optind < argc) { if (optind < argc) {
int64_t sval; int64_t sval;
...@@ -489,6 +526,7 @@ static int img_check(int argc, char **argv) ...@@ -489,6 +526,7 @@ static int img_check(int argc, char **argv)
int flags = BDRV_O_FLAGS | BDRV_O_CHECK; int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
ImageCheck *check; ImageCheck *check;
bool quiet = false; bool quiet = false;
Error *local_err = NULL;
fmt = NULL; fmt = NULL;
output = NULL; output = NULL;
...@@ -500,6 +538,7 @@ static int img_check(int argc, char **argv) ...@@ -500,6 +538,7 @@ static int img_check(int argc, char **argv)
{"format", required_argument, 0, 'f'}, {"format", required_argument, 0, 'f'},
{"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},
{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",
...@@ -536,6 +575,14 @@ static int img_check(int argc, char **argv) ...@@ -536,6 +575,14 @@ static int img_check(int argc, char **argv)
case 'q': case 'q':
quiet = true; quiet = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
return 1;
}
} break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
...@@ -552,6 +599,13 @@ static int img_check(int argc, char **argv) ...@@ -552,6 +599,13 @@ static int img_check(int argc, char **argv)
return 1; return 1;
} }
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
return 1;
}
ret = bdrv_parse_cache_flags(cache, &flags); ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) { if (ret < 0) {
error_report("Invalid source cache option: %s", cache); error_report("Invalid source cache option: %s", cache);
...@@ -675,7 +729,13 @@ static int img_commit(int argc, char **argv) ...@@ -675,7 +729,13 @@ static int img_commit(int argc, char **argv)
cache = BDRV_DEFAULT_CACHE; cache = BDRV_DEFAULT_CACHE;
base = NULL; base = NULL;
for(;;) { for(;;) {
c = getopt(argc, argv, "f:ht:b:dpq"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "f:ht:b:dpq",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -704,6 +764,14 @@ static int img_commit(int argc, char **argv) ...@@ -704,6 +764,14 @@ static int img_commit(int argc, char **argv)
case 'q': case 'q':
quiet = true; quiet = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
return 1;
}
} break;
} }
} }
...@@ -717,6 +785,13 @@ static int img_commit(int argc, char **argv) ...@@ -717,6 +785,13 @@ static int img_commit(int argc, char **argv)
} }
filename = argv[optind++]; filename = argv[optind++];
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
return 1;
}
flags = BDRV_O_RDWR | BDRV_O_UNMAP; flags = BDRV_O_RDWR | BDRV_O_UNMAP;
ret = bdrv_parse_cache_flags(cache, &flags); ret = bdrv_parse_cache_flags(cache, &flags);
if (ret < 0) { if (ret < 0) {
...@@ -973,10 +1048,17 @@ static int img_compare(int argc, char **argv) ...@@ -973,10 +1048,17 @@ static int img_compare(int argc, char **argv)
int64_t nb_sectors; int64_t nb_sectors;
int c, pnum; int c, pnum;
uint64_t progress_base; uint64_t progress_base;
Error *local_err = NULL;
cache = BDRV_DEFAULT_CACHE; cache = BDRV_DEFAULT_CACHE;
for (;;) { for (;;) {
c = getopt(argc, argv, "hf:F:T:pqs"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hf:F:T:pqs",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -1003,6 +1085,15 @@ static int img_compare(int argc, char **argv) ...@@ -1003,6 +1085,15 @@ static int img_compare(int argc, char **argv)
case 's': case 's':
strict = true; strict = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
ret = 2;
goto out4;
}
} break;
} }
} }
...@@ -1018,6 +1109,14 @@ static int img_compare(int argc, char **argv) ...@@ -1018,6 +1109,14 @@ static int img_compare(int argc, char **argv)
filename1 = argv[optind++]; filename1 = argv[optind++];
filename2 = argv[optind++]; filename2 = argv[optind++];
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
ret = 2;
goto out4;
}
/* Initialize before goto out */ /* Initialize before goto out */
qemu_progress_init(progress, 2.0); qemu_progress_init(progress, 2.0);
...@@ -1225,6 +1324,7 @@ out2: ...@@ -1225,6 +1324,7 @@ out2:
blk_unref(blk1); blk_unref(blk1);
out3: out3:
qemu_progress_end(); qemu_progress_end();
out4:
return ret; return ret;
} }
...@@ -1555,7 +1655,13 @@ static int img_convert(int argc, char **argv) ...@@ -1555,7 +1655,13 @@ static int img_convert(int argc, char **argv)
compress = 0; compress = 0;
skip_create = 0; skip_create = 0;
for(;;) { for(;;) {
c = getopt(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -1646,9 +1752,23 @@ static int img_convert(int argc, char **argv) ...@@ -1646,9 +1752,23 @@ static int img_convert(int argc, char **argv)
case 'n': case 'n':
skip_create = 1; skip_create = 1;
break; break;
case OPTION_OBJECT:
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
goto fail_getopt;
}
break;
} }
} }
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
goto fail_getopt;
}
/* Initialize before goto out */ /* Initialize before goto out */
if (quiet) { if (quiet) {
progress = 0; progress = 0;
...@@ -2077,6 +2197,7 @@ static int img_info(int argc, char **argv) ...@@ -2077,6 +2197,7 @@ static int img_info(int argc, char **argv)
bool chain = false; bool chain = false;
const char *filename, *fmt, *output; const char *filename, *fmt, *output;
ImageInfoList *list; ImageInfoList *list;
Error *local_err = NULL;
fmt = NULL; fmt = NULL;
output = NULL; output = NULL;
...@@ -2087,6 +2208,7 @@ static int img_info(int argc, char **argv) ...@@ -2087,6 +2208,7 @@ static int img_info(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},
{"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN}, {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "f:h", c = getopt_long(argc, argv, "f:h",
...@@ -2108,6 +2230,14 @@ static int img_info(int argc, char **argv) ...@@ -2108,6 +2230,14 @@ static int img_info(int argc, char **argv)
case OPTION_BACKING_CHAIN: case OPTION_BACKING_CHAIN:
chain = true; chain = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
return 1;
}
} break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
...@@ -2124,6 +2254,13 @@ static int img_info(int argc, char **argv) ...@@ -2124,6 +2254,13 @@ static int img_info(int argc, char **argv)
return 1; return 1;
} }
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
return 1;
}
list = collect_image_info_list(filename, fmt, chain); list = collect_image_info_list(filename, fmt, chain);
if (!list) { if (!list) {
return 1; return 1;
...@@ -2269,6 +2406,7 @@ static int img_map(int argc, char **argv) ...@@ -2269,6 +2406,7 @@ static int img_map(int argc, char **argv)
int64_t length; int64_t length;
MapEntry curr = { .length = 0 }, next; MapEntry curr = { .length = 0 }, next;
int ret = 0; int ret = 0;
Error *local_err = NULL;
fmt = NULL; fmt = NULL;
output = NULL; output = NULL;
...@@ -2278,6 +2416,7 @@ static int img_map(int argc, char **argv) ...@@ -2278,6 +2416,7 @@ static int img_map(int argc, char **argv)
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"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},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
c = getopt_long(argc, argv, "f:h", c = getopt_long(argc, argv, "f:h",
...@@ -2296,6 +2435,14 @@ static int img_map(int argc, char **argv) ...@@ -2296,6 +2435,14 @@ static int img_map(int argc, char **argv)
case OPTION_OUTPUT: case OPTION_OUTPUT:
output = optarg; output = optarg;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
return 1;
}
} break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
...@@ -2312,6 +2459,13 @@ static int img_map(int argc, char **argv) ...@@ -2312,6 +2459,13 @@ static int img_map(int argc, char **argv)
return 1; return 1;
} }
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
return 1;
}
blk = img_open("image", filename, fmt, BDRV_O_FLAGS, true, false); blk = img_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
if (!blk) { if (!blk) {
return 1; return 1;
...@@ -2378,7 +2532,13 @@ static int img_snapshot(int argc, char **argv) ...@@ -2378,7 +2532,13 @@ static int img_snapshot(int argc, char **argv)
bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR; bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
/* Parse commandline parameters */ /* Parse commandline parameters */
for(;;) { for(;;) {
c = getopt(argc, argv, "la:c:d:hq"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "la:c:d:hq",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -2422,6 +2582,14 @@ static int img_snapshot(int argc, char **argv) ...@@ -2422,6 +2582,14 @@ static int img_snapshot(int argc, char **argv)
case 'q': case 'q':
quiet = true; quiet = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
return 1;
}
} break;
} }
} }
...@@ -2430,6 +2598,13 @@ static int img_snapshot(int argc, char **argv) ...@@ -2430,6 +2598,13 @@ static int img_snapshot(int argc, char **argv)
} }
filename = argv[optind++]; filename = argv[optind++];
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &err)) {
error_report_err(err);
return 1;
}
/* Open the image */ /* Open the image */
blk = img_open("image", filename, NULL, bdrv_oflags, true, quiet); blk = img_open("image", filename, NULL, bdrv_oflags, true, quiet);
if (!blk) { if (!blk) {
...@@ -2503,7 +2678,13 @@ static int img_rebase(int argc, char **argv) ...@@ -2503,7 +2678,13 @@ static int img_rebase(int argc, char **argv)
out_baseimg = NULL; out_baseimg = NULL;
out_basefmt = NULL; out_basefmt = NULL;
for(;;) { for(;;) {
c = getopt(argc, argv, "hf:F:b:upt:T:q"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hf:F:b:upt:T:q",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -2536,6 +2717,14 @@ static int img_rebase(int argc, char **argv) ...@@ -2536,6 +2717,14 @@ static int img_rebase(int argc, char **argv)
case 'q': case 'q':
quiet = true; quiet = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
return 1;
}
} break;
} }
} }
...@@ -2551,6 +2740,13 @@ static int img_rebase(int argc, char **argv) ...@@ -2551,6 +2740,13 @@ static int img_rebase(int argc, char **argv)
} }
filename = argv[optind++]; filename = argv[optind++];
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
return 1;
}
qemu_progress_init(progress, 2.0); qemu_progress_init(progress, 2.0);
qemu_progress_print(0, 100); qemu_progress_print(0, 100);
...@@ -2811,6 +3007,8 @@ static int img_resize(int argc, char **argv) ...@@ -2811,6 +3007,8 @@ static int img_resize(int argc, char **argv)
bool quiet = false; bool quiet = false;
BlockBackend *blk = NULL; BlockBackend *blk = NULL;
QemuOpts *param; QemuOpts *param;
Error *local_err = NULL;
static QemuOptsList resize_options = { static QemuOptsList resize_options = {
.name = "resize_options", .name = "resize_options",
.head = QTAILQ_HEAD_INITIALIZER(resize_options.head), .head = QTAILQ_HEAD_INITIALIZER(resize_options.head),
...@@ -2837,7 +3035,13 @@ static int img_resize(int argc, char **argv) ...@@ -2837,7 +3035,13 @@ static int img_resize(int argc, char **argv)
/* Parse getopt arguments */ /* Parse getopt arguments */
fmt = NULL; fmt = NULL;
for(;;) { for(;;) {
c = getopt(argc, argv, "f:hq"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "f:hq",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -2852,6 +3056,14 @@ static int img_resize(int argc, char **argv) ...@@ -2852,6 +3056,14 @@ static int img_resize(int argc, char **argv)
case 'q': case 'q':
quiet = true; quiet = true;
break; break;
case OPTION_OBJECT: {
QemuOpts *opts;
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
return 1;
}
} break;
} }
} }
if (optind != argc - 1) { if (optind != argc - 1) {
...@@ -2859,6 +3071,13 @@ static int img_resize(int argc, char **argv) ...@@ -2859,6 +3071,13 @@ static int img_resize(int argc, char **argv)
} }
filename = argv[optind++]; filename = argv[optind++];
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
return 1;
}
/* Choose grow, shrink, or absolute resize mode */ /* Choose grow, shrink, or absolute resize mode */
switch (size[0]) { switch (size[0]) {
case '+': case '+':
...@@ -2946,10 +3165,17 @@ static int img_amend(int argc, char **argv) ...@@ -2946,10 +3165,17 @@ static int img_amend(int argc, char **argv)
bool quiet = false, progress = false; bool quiet = false, progress = false;
BlockBackend *blk = NULL; BlockBackend *blk = NULL;
BlockDriverState *bs = NULL; BlockDriverState *bs = NULL;
Error *local_err = NULL;
cache = BDRV_DEFAULT_CACHE; cache = BDRV_DEFAULT_CACHE;
for (;;) { for (;;) {
c = getopt(argc, argv, "ho:f:t:pq"); static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "ho:f:t:pq",
long_options, NULL);
if (c == -1) { if (c == -1) {
break; break;
} }
...@@ -2985,6 +3211,14 @@ static int img_amend(int argc, char **argv) ...@@ -2985,6 +3211,14 @@ static int img_amend(int argc, char **argv)
case 'q': case 'q':
quiet = true; quiet = true;
break; break;
case OPTION_OBJECT:
opts = qemu_opts_parse_noisily(&qemu_object_opts,
optarg, true);
if (!opts) {
ret = -1;
goto out_no_progress;
}
break;
} }
} }
...@@ -2992,6 +3226,14 @@ static int img_amend(int argc, char **argv) ...@@ -2992,6 +3226,14 @@ static int img_amend(int argc, char **argv)
error_exit("Must specify options (-o)"); error_exit("Must specify options (-o)");
} }
if (qemu_opts_foreach(&qemu_object_opts,
user_creatable_add_opts_foreach,
NULL, &local_err)) {
error_report_err(local_err);
ret = -1;
goto out_no_progress;
}
if (quiet) { if (quiet) {
progress = false; progress = false;
} }
...@@ -3115,6 +3357,8 @@ int main(int argc, char **argv) ...@@ -3115,6 +3357,8 @@ int main(int argc, char **argv)
} }
cmdname = argv[1]; cmdname = argv[1];
qemu_add_opts(&qemu_object_opts);
/* find the command */ /* find the command */
for (cmd = img_cmds; cmd->name != NULL; cmd++) { for (cmd = img_cmds; cmd->name != NULL; cmd++) {
if (!strcmp(cmdname, cmd->name)) { if (!strcmp(cmdname, cmd->name)) {
......
...@@ -24,6 +24,14 @@ Command parameters: ...@@ -24,6 +24,14 @@ Command parameters:
@table @var @table @var
@item filename @item filename
is a disk image filename is a disk image filename
@item --object @var{objectdef}
is a QEMU user creatable object definition. See the @code{qemu(1)} manual
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
keys.
@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.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册