blob: 30e33c7b6cbe92d4e729b36480cadb99a7f54daf [file] [log] [blame]
bellardea2384d2004-08-01 21:59:26 +00001/*
bellardfb43f4d2006-08-07 21:34:46 +00002 * QEMU disk image utility
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard68d0f702008-01-06 17:21:48 +00004 * Copyright (c) 2003-2008 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
bellardea2384d2004-08-01 21:59:26 +00006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
Benoît Canetc054b3f2012-09-05 13:09:02 +020024#include "qapi-visit.h"
25#include "qapi/qmp-output-visitor.h"
26#include "qjson.h"
pbrookfaf07962007-11-11 02:51:17 +000027#include "qemu-common.h"
Kevin Wolf9ea2ea72009-05-18 16:42:11 +020028#include "qemu-option.h"
Kevin Wolf53f76e52010-12-16 15:10:32 +010029#include "qemu-error.h"
aliguorif7b4a942009-01-07 17:40:15 +000030#include "osdep.h"
Jes Sorensendc786bc2010-10-26 10:39:23 +020031#include "sysemu.h"
thsec36ba12007-09-16 21:59:02 +000032#include "block_int.h"
Benoît Canetc054b3f2012-09-05 13:09:02 +020033#include <getopt.h>
aliguori9230eaf2009-03-28 17:55:19 +000034#include <stdio.h>
bellardea2384d2004-08-01 21:59:26 +000035
bellarde8445332006-06-14 15:32:10 +000036#ifdef _WIN32
37#include <windows.h>
38#endif
39
Anthony Liguoric227f092009-10-01 16:12:16 -050040typedef struct img_cmd_t {
Stuart Brady153859b2009-06-07 00:42:17 +010041 const char *name;
42 int (*handler)(int argc, char **argv);
Anthony Liguoric227f092009-10-01 16:12:16 -050043} img_cmd_t;
Stuart Brady153859b2009-06-07 00:42:17 +010044
aurel32137519c2008-11-30 19:12:49 +000045/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
Stefan Hajnocziadfe0782010-04-13 10:29:35 +010046#define BDRV_O_FLAGS BDRV_O_CACHE_WB
Federico Simoncelli661a0f72011-06-20 12:48:19 -040047#define BDRV_DEFAULT_CACHE "writeback"
aurel32137519c2008-11-30 19:12:49 +000048
bellardea2384d2004-08-01 21:59:26 +000049static void format_print(void *opaque, const char *name)
50{
51 printf(" %s", name);
52}
53
blueswir1d2c639d2009-01-24 18:19:25 +000054/* Please keep in synch with qemu-img.texi */
pbrook3f379ab2007-11-11 03:33:13 +000055static void help(void)
bellardea2384d2004-08-01 21:59:26 +000056{
Paolo Bonzinie00291c2010-02-04 16:49:56 +010057 const char *help_msg =
58 "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
malc3f020d72010-02-08 12:04:56 +030059 "usage: qemu-img command [command options]\n"
60 "QEMU disk image utility\n"
61 "\n"
62 "Command syntax:\n"
Stuart Brady153859b2009-06-07 00:42:17 +010063#define DEF(option, callback, arg_string) \
64 " " arg_string "\n"
65#include "qemu-img-cmds.h"
66#undef DEF
67#undef GEN_DOCS
malc3f020d72010-02-08 12:04:56 +030068 "\n"
69 "Command parameters:\n"
70 " 'filename' is a disk image filename\n"
71 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
Federico Simoncelli661a0f72011-06-20 12:48:19 -040072 " 'cache' is the cache mode used to write the output disk image, the valid\n"
Liu Yuan80ccf932012-04-20 17:10:56 +080073 " options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
74 " 'directsync' and 'unsafe' (default for convert)\n"
malc3f020d72010-02-08 12:04:56 +030075 " 'size' is the disk image size in bytes. Optional suffixes\n"
76 " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
77 " and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
78 " 'output_filename' is the destination disk image filename\n"
79 " 'output_fmt' is the destination format\n"
80 " 'options' is a comma separated list of format specific options in a\n"
81 " name=value format. Use -o ? for an overview of the options supported by the\n"
82 " used format\n"
83 " '-c' indicates that target image must be compressed (qcow format only)\n"
84 " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
85 " match exactly. The image doesn't need a working backing file before\n"
86 " rebasing in this case (useful for renaming the backing file)\n"
87 " '-h' with or without a command shows this help and lists the supported formats\n"
Jes Sorensen6b837bc2011-03-30 14:16:25 +020088 " '-p' show progress of command (only certain commands)\n"
Kevin Wolfa22f1232011-08-26 15:27:13 +020089 " '-S' indicates the consecutive number of bytes that must contain only zeros\n"
90 " for qemu-img to create a sparse image during conversion\n"
Benoît Canetc054b3f2012-09-05 13:09:02 +020091 " '--output' takes the format in which the output must be done (human or json)\n"
malc3f020d72010-02-08 12:04:56 +030092 "\n"
Kevin Wolf4534ff52012-05-11 16:07:02 +020093 "Parameters to check subcommand:\n"
94 " '-r' tries to repair any inconsistencies that are found during the check.\n"
95 " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
96 " kinds of errors, with a higher risk of choosing the wrong fix or\n"
97 " hiding corruption that has already occured.\n"
98 "\n"
malc3f020d72010-02-08 12:04:56 +030099 "Parameters to snapshot subcommand:\n"
100 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
101 " '-a' applies a snapshot (revert disk to saved state)\n"
102 " '-c' creates a snapshot\n"
103 " '-d' deletes a snapshot\n"
Paolo Bonzinie00291c2010-02-04 16:49:56 +0100104 " '-l' lists all snapshots in the given image\n";
105
106 printf("%s\nSupported formats:", help_msg);
bellardea2384d2004-08-01 21:59:26 +0000107 bdrv_iterate_format(format_print, NULL);
108 printf("\n");
109 exit(1);
110}
111
bellardea2384d2004-08-01 21:59:26 +0000112#if defined(WIN32)
113/* XXX: put correct support for win32 */
114static int read_password(char *buf, int buf_size)
115{
116 int c, i;
117 printf("Password: ");
118 fflush(stdout);
119 i = 0;
120 for(;;) {
121 c = getchar();
122 if (c == '\n')
123 break;
124 if (i < (buf_size - 1))
125 buf[i++] = c;
126 }
127 buf[i] = '\0';
128 return 0;
129}
130
131#else
132
133#include <termios.h>
134
135static struct termios oldtty;
136
137static void term_exit(void)
138{
139 tcsetattr (0, TCSANOW, &oldtty);
140}
141
142static void term_init(void)
143{
144 struct termios tty;
145
146 tcgetattr (0, &tty);
147 oldtty = tty;
148
149 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
150 |INLCR|IGNCR|ICRNL|IXON);
151 tty.c_oflag |= OPOST;
152 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
153 tty.c_cflag &= ~(CSIZE|PARENB);
154 tty.c_cflag |= CS8;
155 tty.c_cc[VMIN] = 1;
156 tty.c_cc[VTIME] = 0;
ths3b46e622007-09-17 08:09:54 +0000157
bellardea2384d2004-08-01 21:59:26 +0000158 tcsetattr (0, TCSANOW, &tty);
159
160 atexit(term_exit);
161}
162
pbrook3f379ab2007-11-11 03:33:13 +0000163static int read_password(char *buf, int buf_size)
bellardea2384d2004-08-01 21:59:26 +0000164{
165 uint8_t ch;
166 int i, ret;
167
168 printf("password: ");
169 fflush(stdout);
170 term_init();
171 i = 0;
172 for(;;) {
173 ret = read(0, &ch, 1);
174 if (ret == -1) {
175 if (errno == EAGAIN || errno == EINTR) {
176 continue;
177 } else {
178 ret = -1;
179 break;
180 }
181 } else if (ret == 0) {
182 ret = -1;
183 break;
184 } else {
185 if (ch == '\r') {
186 ret = 0;
187 break;
188 }
189 if (i < (buf_size - 1))
190 buf[i++] = ch;
191 }
192 }
193 term_exit();
194 buf[i] = '\0';
195 printf("\n");
196 return ret;
197}
198#endif
199
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100200static int print_block_option_help(const char *filename, const char *fmt)
201{
202 BlockDriver *drv, *proto_drv;
203 QEMUOptionParameter *create_options = NULL;
204
205 /* Find driver and parse its options */
206 drv = bdrv_find_format(fmt);
207 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100208 error_report("Unknown file format '%s'", fmt);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100209 return 1;
210 }
211
212 proto_drv = bdrv_find_protocol(filename);
213 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100214 error_report("Unknown protocol '%s'", filename);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100215 return 1;
216 }
217
218 create_options = append_option_parameters(create_options,
219 drv->create_options);
220 create_options = append_option_parameters(create_options,
221 proto_drv->create_options);
222 print_option_help(create_options);
223 free_option_parameters(create_options);
224 return 0;
225}
226
bellard75c23802004-08-27 21:28:58 +0000227static BlockDriverState *bdrv_new_open(const char *filename,
Sheng Yang9bc378c2010-01-29 10:15:06 +0800228 const char *fmt,
Stefan Hajnoczif163d072010-04-13 10:29:34 +0100229 int flags)
bellard75c23802004-08-27 21:28:58 +0000230{
231 BlockDriverState *bs;
232 BlockDriver *drv;
233 char password[256];
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100234 int ret;
bellard75c23802004-08-27 21:28:58 +0000235
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100236 bs = bdrv_new("image");
Kevin Wolfad717132010-12-16 15:37:41 +0100237
bellard75c23802004-08-27 21:28:58 +0000238 if (fmt) {
239 drv = bdrv_find_format(fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900240 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100241 error_report("Unknown file format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900242 goto fail;
243 }
bellard75c23802004-08-27 21:28:58 +0000244 } else {
245 drv = NULL;
246 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100247
248 ret = bdrv_open(bs, filename, flags, drv);
249 if (ret < 0) {
250 error_report("Could not open '%s': %s", filename, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900251 goto fail;
bellard75c23802004-08-27 21:28:58 +0000252 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100253
bellard75c23802004-08-27 21:28:58 +0000254 if (bdrv_is_encrypted(bs)) {
255 printf("Disk image '%s' is encrypted.\n", filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900256 if (read_password(password, sizeof(password)) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100257 error_report("No password given");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900258 goto fail;
259 }
260 if (bdrv_set_key(bs, password) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100261 error_report("invalid password");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900262 goto fail;
263 }
bellard75c23802004-08-27 21:28:58 +0000264 }
265 return bs;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900266fail:
267 if (bs) {
268 bdrv_delete(bs);
269 }
270 return NULL;
bellard75c23802004-08-27 21:28:58 +0000271}
272
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900273static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
Jes Sorenseneec77d92010-12-07 17:44:34 +0100274 const char *base_filename,
275 const char *base_fmt)
Kevin Wolfefa84d42009-05-18 16:42:12 +0200276{
Kevin Wolfefa84d42009-05-18 16:42:12 +0200277 if (base_filename) {
278 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100279 error_report("Backing file not supported for file format '%s'",
280 fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900281 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200282 }
283 }
284 if (base_fmt) {
285 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100286 error_report("Backing file format not supported for file "
287 "format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900288 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200289 }
290 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900291 return 0;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200292}
293
bellardea2384d2004-08-01 21:59:26 +0000294static int img_create(int argc, char **argv)
295{
Jes Sorenseneec77d92010-12-07 17:44:34 +0100296 int c, ret = 0;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100297 uint64_t img_size = -1;
bellardea2384d2004-08-01 21:59:26 +0000298 const char *fmt = "raw";
aliguori9230eaf2009-03-28 17:55:19 +0000299 const char *base_fmt = NULL;
bellardea2384d2004-08-01 21:59:26 +0000300 const char *filename;
301 const char *base_filename = NULL;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200302 char *options = NULL;
ths3b46e622007-09-17 08:09:54 +0000303
bellardea2384d2004-08-01 21:59:26 +0000304 for(;;) {
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200305 c = getopt(argc, argv, "F:b:f:he6o:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100306 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000307 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100308 }
bellardea2384d2004-08-01 21:59:26 +0000309 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100310 case '?':
bellardea2384d2004-08-01 21:59:26 +0000311 case 'h':
312 help();
313 break;
aliguori9230eaf2009-03-28 17:55:19 +0000314 case 'F':
315 base_fmt = optarg;
316 break;
bellardea2384d2004-08-01 21:59:26 +0000317 case 'b':
318 base_filename = optarg;
319 break;
320 case 'f':
321 fmt = optarg;
322 break;
323 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200324 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100325 "encryption\' instead!");
326 return 1;
thsd8871c52007-10-24 16:11:42 +0000327 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200328 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100329 "compat6\' instead!");
330 return 1;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200331 case 'o':
332 options = optarg;
333 break;
bellardea2384d2004-08-01 21:59:26 +0000334 }
335 }
aliguori9230eaf2009-03-28 17:55:19 +0000336
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900337 /* Get the filename */
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100338 if (optind >= argc) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900339 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100340 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900341 filename = argv[optind++];
342
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100343 /* Get image size, if specified */
344 if (optind < argc) {
Jes Sorensen70b4f4b2011-01-05 11:41:02 +0100345 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +0100346 char *end;
347 sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
348 if (sval < 0 || *end) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100349 error_report("Invalid image size specified! You may use k, M, G or "
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100350 "T suffixes for ");
Jes Sorensen15654a62010-12-16 14:31:53 +0100351 error_report("kilobytes, megabytes, gigabytes and terabytes.");
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100352 ret = -1;
353 goto out;
354 }
355 img_size = (uint64_t)sval;
356 }
357
Peter Maydellc8057f92012-08-02 13:45:54 +0100358 if (options && is_help_option(options)) {
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100359 ret = print_block_option_help(filename, fmt);
360 goto out;
361 }
362
Jes Sorensenf88e1a42010-12-16 13:52:15 +0100363 ret = bdrv_img_create(filename, fmt, base_filename, base_fmt,
364 options, img_size, BDRV_O_FLAGS);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900365out:
366 if (ret) {
367 return 1;
368 }
bellardea2384d2004-08-01 21:59:26 +0000369 return 0;
370}
371
Kevin Wolfe076f332010-06-29 11:43:13 +0200372/*
373 * Checks an image for consistency. Exit codes:
374 *
375 * 0 - Check completed, image is good
376 * 1 - Check not completed because of internal errors
377 * 2 - Check completed, image is corrupted
378 * 3 - Check completed, image has leaked clusters, but is good otherwise
379 */
aliguori15859692009-04-21 23:11:53 +0000380static int img_check(int argc, char **argv)
381{
382 int c, ret;
383 const char *filename, *fmt;
aliguori15859692009-04-21 23:11:53 +0000384 BlockDriverState *bs;
Kevin Wolfe076f332010-06-29 11:43:13 +0200385 BdrvCheckResult result;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200386 int fix = 0;
Stefan Hajnoczi058f8f12012-08-09 13:05:56 +0100387 int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
aliguori15859692009-04-21 23:11:53 +0000388
389 fmt = NULL;
390 for(;;) {
Kevin Wolf4534ff52012-05-11 16:07:02 +0200391 c = getopt(argc, argv, "f:hr:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100392 if (c == -1) {
aliguori15859692009-04-21 23:11:53 +0000393 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100394 }
aliguori15859692009-04-21 23:11:53 +0000395 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100396 case '?':
aliguori15859692009-04-21 23:11:53 +0000397 case 'h':
398 help();
399 break;
400 case 'f':
401 fmt = optarg;
402 break;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200403 case 'r':
404 flags |= BDRV_O_RDWR;
405
406 if (!strcmp(optarg, "leaks")) {
407 fix = BDRV_FIX_LEAKS;
408 } else if (!strcmp(optarg, "all")) {
409 fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
410 } else {
411 help();
412 }
413 break;
aliguori15859692009-04-21 23:11:53 +0000414 }
415 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100416 if (optind >= argc) {
aliguori15859692009-04-21 23:11:53 +0000417 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100418 }
aliguori15859692009-04-21 23:11:53 +0000419 filename = argv[optind++];
420
Kevin Wolf4534ff52012-05-11 16:07:02 +0200421 bs = bdrv_new_open(filename, fmt, flags);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900422 if (!bs) {
423 return 1;
424 }
Kevin Wolf4534ff52012-05-11 16:07:02 +0200425 ret = bdrv_check(bs, &result, fix);
Kevin Wolfe076f332010-06-29 11:43:13 +0200426
427 if (ret == -ENOTSUP) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100428 error_report("This image format does not support checks");
Kevin Wolfe076f332010-06-29 11:43:13 +0200429 bdrv_delete(bs);
430 return 1;
431 }
432
Kevin Wolfccf34712012-05-11 18:16:54 +0200433 if (result.corruptions_fixed || result.leaks_fixed) {
434 printf("The following inconsistencies were found and repaired:\n\n"
435 " %d leaked clusters\n"
436 " %d corruptions\n\n"
437 "Double checking the fixed image now...\n",
438 result.leaks_fixed,
439 result.corruptions_fixed);
440 ret = bdrv_check(bs, &result, 0);
441 }
442
Kevin Wolfe076f332010-06-29 11:43:13 +0200443 if (!(result.corruptions || result.leaks || result.check_errors)) {
444 printf("No errors were found on the image.\n");
445 } else {
446 if (result.corruptions) {
447 printf("\n%d errors were found on the image.\n"
448 "Data may be corrupted, or further writes to the image "
449 "may corrupt it.\n",
450 result.corruptions);
aliguori15859692009-04-21 23:11:53 +0000451 }
Kevin Wolfe076f332010-06-29 11:43:13 +0200452
453 if (result.leaks) {
454 printf("\n%d leaked clusters were found on the image.\n"
455 "This means waste of disk space, but no harm to data.\n",
456 result.leaks);
457 }
458
459 if (result.check_errors) {
460 printf("\n%d internal errors have occurred during the check.\n",
461 result.check_errors);
462 }
aliguori15859692009-04-21 23:11:53 +0000463 }
464
Dong Xu Wangf8111c22012-03-15 20:13:31 +0800465 if (result.bfi.total_clusters != 0 && result.bfi.allocated_clusters != 0) {
466 printf("%" PRId64 "/%" PRId64 "= %0.2f%% allocated, %0.2f%% fragmented\n",
467 result.bfi.allocated_clusters, result.bfi.total_clusters,
468 result.bfi.allocated_clusters * 100.0 / result.bfi.total_clusters,
469 result.bfi.fragmented_clusters * 100.0 / result.bfi.allocated_clusters);
470 }
471
aliguori15859692009-04-21 23:11:53 +0000472 bdrv_delete(bs);
Kevin Wolfe076f332010-06-29 11:43:13 +0200473
474 if (ret < 0 || result.check_errors) {
475 printf("\nAn error has occurred during the check: %s\n"
476 "The check is not complete and may have missed error.\n",
477 strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900478 return 1;
479 }
Kevin Wolfe076f332010-06-29 11:43:13 +0200480
481 if (result.corruptions) {
482 return 2;
483 } else if (result.leaks) {
484 return 3;
485 } else {
486 return 0;
487 }
aliguori15859692009-04-21 23:11:53 +0000488}
489
bellardea2384d2004-08-01 21:59:26 +0000490static int img_commit(int argc, char **argv)
491{
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400492 int c, ret, flags;
493 const char *filename, *fmt, *cache;
bellardea2384d2004-08-01 21:59:26 +0000494 BlockDriverState *bs;
495
496 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400497 cache = BDRV_DEFAULT_CACHE;
bellardea2384d2004-08-01 21:59:26 +0000498 for(;;) {
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400499 c = getopt(argc, argv, "f:ht:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100500 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000501 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100502 }
bellardea2384d2004-08-01 21:59:26 +0000503 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100504 case '?':
bellardea2384d2004-08-01 21:59:26 +0000505 case 'h':
506 help();
507 break;
508 case 'f':
509 fmt = optarg;
510 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400511 case 't':
512 cache = optarg;
513 break;
bellardea2384d2004-08-01 21:59:26 +0000514 }
515 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100516 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +0000517 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100518 }
bellardea2384d2004-08-01 21:59:26 +0000519 filename = argv[optind++];
520
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400521 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +0100522 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400523 if (ret < 0) {
524 error_report("Invalid cache option: %s", cache);
525 return -1;
526 }
527
528 bs = bdrv_new_open(filename, fmt, flags);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900529 if (!bs) {
530 return 1;
531 }
bellardea2384d2004-08-01 21:59:26 +0000532 ret = bdrv_commit(bs);
533 switch(ret) {
534 case 0:
535 printf("Image committed.\n");
536 break;
537 case -ENOENT:
Jes Sorensen15654a62010-12-16 14:31:53 +0100538 error_report("No disk inserted");
bellardea2384d2004-08-01 21:59:26 +0000539 break;
540 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +0100541 error_report("Image is read-only");
bellardea2384d2004-08-01 21:59:26 +0000542 break;
543 case -ENOTSUP:
Jes Sorensen15654a62010-12-16 14:31:53 +0100544 error_report("Image is already committed");
bellardea2384d2004-08-01 21:59:26 +0000545 break;
546 default:
Jes Sorensen15654a62010-12-16 14:31:53 +0100547 error_report("Error while committing image");
bellardea2384d2004-08-01 21:59:26 +0000548 break;
549 }
550
551 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900552 if (ret) {
553 return 1;
554 }
bellardea2384d2004-08-01 21:59:26 +0000555 return 0;
556}
557
Dmitry Konishchevf6a00aa2011-05-18 15:03:59 +0400558/*
thsf58c7b32008-06-05 21:53:49 +0000559 * Returns true iff the first sector pointed to by 'buf' contains at least
560 * a non-NUL byte.
561 *
562 * 'pnum' is set to the number of sectors (including and immediately following
563 * the first one) that are known to be in the same allocated/unallocated state.
564 */
bellardea2384d2004-08-01 21:59:26 +0000565static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
566{
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000567 bool is_zero;
568 int i;
bellardea2384d2004-08-01 21:59:26 +0000569
570 if (n <= 0) {
571 *pnum = 0;
572 return 0;
573 }
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000574 is_zero = buffer_is_zero(buf, 512);
bellardea2384d2004-08-01 21:59:26 +0000575 for(i = 1; i < n; i++) {
576 buf += 512;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000577 if (is_zero != buffer_is_zero(buf, 512)) {
bellardea2384d2004-08-01 21:59:26 +0000578 break;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000579 }
bellardea2384d2004-08-01 21:59:26 +0000580 }
581 *pnum = i;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000582 return !is_zero;
bellardea2384d2004-08-01 21:59:26 +0000583}
584
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100585/*
Kevin Wolfa22f1232011-08-26 15:27:13 +0200586 * Like is_allocated_sectors, but if the buffer starts with a used sector,
587 * up to 'min' consecutive sectors containing zeros are ignored. This avoids
588 * breaking up write requests for only small sparse areas.
589 */
590static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
591 int min)
592{
593 int ret;
594 int num_checked, num_used;
595
596 if (n < min) {
597 min = n;
598 }
599
600 ret = is_allocated_sectors(buf, n, pnum);
601 if (!ret) {
602 return ret;
603 }
604
605 num_used = *pnum;
606 buf += BDRV_SECTOR_SIZE * *pnum;
607 n -= *pnum;
608 num_checked = num_used;
609
610 while (n > 0) {
611 ret = is_allocated_sectors(buf, n, pnum);
612
613 buf += BDRV_SECTOR_SIZE * *pnum;
614 n -= *pnum;
615 num_checked += *pnum;
616 if (ret) {
617 num_used = num_checked;
618 } else if (*pnum >= min) {
619 break;
620 }
621 }
622
623 *pnum = num_used;
624 return 1;
625}
626
627/*
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100628 * Compares two buffers sector by sector. Returns 0 if the first sector of both
629 * buffers matches, non-zero otherwise.
630 *
631 * pnum is set to the number of sectors (including and immediately following
632 * the first one) that are known to have the same comparison result
633 */
634static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
635 int *pnum)
636{
637 int res, i;
638
639 if (n <= 0) {
640 *pnum = 0;
641 return 0;
642 }
643
644 res = !!memcmp(buf1, buf2, 512);
645 for(i = 1; i < n; i++) {
646 buf1 += 512;
647 buf2 += 512;
648
649 if (!!memcmp(buf1, buf2, 512) != res) {
650 break;
651 }
652 }
653
654 *pnum = i;
655 return res;
656}
657
Kevin Wolf80ee15a2009-09-15 12:30:43 +0200658#define IO_BUF_SIZE (2 * 1024 * 1024)
bellardea2384d2004-08-01 21:59:26 +0000659
660static int img_convert(int argc, char **argv)
661{
Jes Sorenseneec77d92010-12-07 17:44:34 +0100662 int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400663 int progress = 0, flags;
664 const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900665 BlockDriver *drv, *proto_drv;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900666 BlockDriverState **bs = NULL, *out_bs = NULL;
ths96b8f132007-12-17 01:35:20 +0000667 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
668 uint64_t bs_sectors;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900669 uint8_t * buf = NULL;
bellardea2384d2004-08-01 21:59:26 +0000670 const uint8_t *buf1;
bellardfaea38e2006-08-05 21:31:00 +0000671 BlockDriverInfo bdi;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900672 QEMUOptionParameter *param = NULL, *create_options = NULL;
Kevin Wolfa18953f2010-10-14 15:46:04 +0200673 QEMUOptionParameter *out_baseimg_param;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200674 char *options = NULL;
edison51ef6722010-09-21 19:58:41 -0700675 const char *snapshot_name = NULL;
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200676 float local_progress;
Kevin Wolfa22f1232011-08-26 15:27:13 +0200677 int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
bellardea2384d2004-08-01 21:59:26 +0000678
679 fmt = NULL;
680 out_fmt = "raw";
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400681 cache = "unsafe";
thsf58c7b32008-06-05 21:53:49 +0000682 out_baseimg = NULL;
Jes Sorenseneec77d92010-12-07 17:44:34 +0100683 compress = 0;
bellardea2384d2004-08-01 21:59:26 +0000684 for(;;) {
Kevin Wolfa22f1232011-08-26 15:27:13 +0200685 c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100686 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000687 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100688 }
bellardea2384d2004-08-01 21:59:26 +0000689 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100690 case '?':
bellardea2384d2004-08-01 21:59:26 +0000691 case 'h':
692 help();
693 break;
694 case 'f':
695 fmt = optarg;
696 break;
697 case 'O':
698 out_fmt = optarg;
699 break;
thsf58c7b32008-06-05 21:53:49 +0000700 case 'B':
701 out_baseimg = optarg;
702 break;
bellardea2384d2004-08-01 21:59:26 +0000703 case 'c':
Jes Sorenseneec77d92010-12-07 17:44:34 +0100704 compress = 1;
bellardea2384d2004-08-01 21:59:26 +0000705 break;
706 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200707 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100708 "encryption\' instead!");
709 return 1;
thsec36ba12007-09-16 21:59:02 +0000710 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200711 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100712 "compat6\' instead!");
713 return 1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200714 case 'o':
715 options = optarg;
716 break;
edison51ef6722010-09-21 19:58:41 -0700717 case 's':
718 snapshot_name = optarg;
719 break;
Kevin Wolfa22f1232011-08-26 15:27:13 +0200720 case 'S':
721 {
722 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +0100723 char *end;
724 sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
725 if (sval < 0 || *end) {
Kevin Wolfa22f1232011-08-26 15:27:13 +0200726 error_report("Invalid minimum zero buffer size for sparse output specified");
727 return 1;
728 }
729
730 min_sparse = sval / BDRV_SECTOR_SIZE;
731 break;
732 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200733 case 'p':
734 progress = 1;
735 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400736 case 't':
737 cache = optarg;
738 break;
bellardea2384d2004-08-01 21:59:26 +0000739 }
740 }
ths3b46e622007-09-17 08:09:54 +0000741
balrog926c2d22007-10-31 01:11:44 +0000742 bs_n = argc - optind - 1;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100743 if (bs_n < 1) {
744 help();
745 }
balrog926c2d22007-10-31 01:11:44 +0000746
747 out_filename = argv[argc - 1];
thsf58c7b32008-06-05 21:53:49 +0000748
Charles Arnoldfa170c12012-05-11 10:57:54 -0600749 /* Initialize before goto out */
750 qemu_progress_init(progress, 2.0);
751
Peter Maydellc8057f92012-08-02 13:45:54 +0100752 if (options && is_help_option(options)) {
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100753 ret = print_block_option_help(out_filename, out_fmt);
754 goto out;
755 }
756
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900757 if (bs_n > 1 && out_baseimg) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100758 error_report("-B makes no sense when concatenating multiple input "
759 "images");
Jes Sorensen31ca34b2010-12-06 15:25:36 +0100760 ret = -1;
761 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900762 }
Dong Xu Wangf8111c22012-03-15 20:13:31 +0800763
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200764 qemu_progress_print(0, 100);
765
Anthony Liguori7267c092011-08-20 22:09:37 -0500766 bs = g_malloc0(bs_n * sizeof(BlockDriverState *));
balrog926c2d22007-10-31 01:11:44 +0000767
768 total_sectors = 0;
769 for (bs_i = 0; bs_i < bs_n; bs_i++) {
Stefan Hajnocziadfe0782010-04-13 10:29:35 +0100770 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900771 if (!bs[bs_i]) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100772 error_report("Could not open '%s'", argv[optind + bs_i]);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900773 ret = -1;
774 goto out;
775 }
balrog926c2d22007-10-31 01:11:44 +0000776 bdrv_get_geometry(bs[bs_i], &bs_sectors);
777 total_sectors += bs_sectors;
778 }
bellardea2384d2004-08-01 21:59:26 +0000779
edison51ef6722010-09-21 19:58:41 -0700780 if (snapshot_name != NULL) {
781 if (bs_n > 1) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200782 error_report("No support for concatenating multiple snapshot");
edison51ef6722010-09-21 19:58:41 -0700783 ret = -1;
784 goto out;
785 }
786 if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200787 error_report("Failed to load snapshot");
edison51ef6722010-09-21 19:58:41 -0700788 ret = -1;
789 goto out;
790 }
791 }
792
Kevin Wolfefa84d42009-05-18 16:42:12 +0200793 /* Find driver and parse its options */
bellardea2384d2004-08-01 21:59:26 +0000794 drv = bdrv_find_format(out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900795 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100796 error_report("Unknown file format '%s'", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900797 ret = -1;
798 goto out;
799 }
balrog926c2d22007-10-31 01:11:44 +0000800
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900801 proto_drv = bdrv_find_protocol(out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900802 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100803 error_report("Unknown protocol '%s'", out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900804 ret = -1;
805 goto out;
806 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900807
808 create_options = append_option_parameters(create_options,
809 drv->create_options);
810 create_options = append_option_parameters(create_options,
811 proto_drv->create_options);
Kevin Wolfdb08adf2009-06-04 15:39:38 +0200812
Kevin Wolfefa84d42009-05-18 16:42:12 +0200813 if (options) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900814 param = parse_option_parameters(options, create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +0200815 if (param == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100816 error_report("Invalid options for file format '%s'.", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900817 ret = -1;
818 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200819 }
820 } else {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900821 param = parse_option_parameters("", create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +0200822 }
823
824 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
Jes Sorenseneec77d92010-12-07 17:44:34 +0100825 ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900826 if (ret < 0) {
827 goto out;
828 }
Kevin Wolfefa84d42009-05-18 16:42:12 +0200829
Kevin Wolfa18953f2010-10-14 15:46:04 +0200830 /* Get backing file name if -o backing_file was used */
831 out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
832 if (out_baseimg_param) {
833 out_baseimg = out_baseimg_param->value.s;
834 }
835
Kevin Wolfefa84d42009-05-18 16:42:12 +0200836 /* Check if compression is supported */
Jes Sorenseneec77d92010-12-07 17:44:34 +0100837 if (compress) {
Kevin Wolfefa84d42009-05-18 16:42:12 +0200838 QEMUOptionParameter *encryption =
839 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
Kevin Wolf41521fa2011-10-18 16:19:42 +0200840 QEMUOptionParameter *preallocation =
841 get_option_parameter(param, BLOCK_OPT_PREALLOC);
Kevin Wolfefa84d42009-05-18 16:42:12 +0200842
843 if (!drv->bdrv_write_compressed) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100844 error_report("Compression not supported for this file format");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900845 ret = -1;
846 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200847 }
848
849 if (encryption && encryption->value.n) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100850 error_report("Compression and encryption not supported at "
851 "the same time");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900852 ret = -1;
853 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200854 }
Kevin Wolf41521fa2011-10-18 16:19:42 +0200855
856 if (preallocation && preallocation->value.s
857 && strcmp(preallocation->value.s, "off"))
858 {
859 error_report("Compression and preallocation not supported at "
860 "the same time");
861 ret = -1;
862 goto out;
863 }
Kevin Wolfefa84d42009-05-18 16:42:12 +0200864 }
865
866 /* Create the new image */
867 ret = bdrv_create(drv, out_filename, param);
bellardea2384d2004-08-01 21:59:26 +0000868 if (ret < 0) {
869 if (ret == -ENOTSUP) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100870 error_report("Formatting not supported for file format '%s'",
871 out_fmt);
aurel326e9ea0c2009-04-15 14:42:46 +0000872 } else if (ret == -EFBIG) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100873 error_report("The image size is too large for file format '%s'",
874 out_fmt);
bellardea2384d2004-08-01 21:59:26 +0000875 } else {
Jes Sorensen15654a62010-12-16 14:31:53 +0100876 error_report("%s: error while converting %s: %s",
877 out_filename, out_fmt, strerror(-ret));
bellardea2384d2004-08-01 21:59:26 +0000878 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900879 goto out;
bellardea2384d2004-08-01 21:59:26 +0000880 }
ths3b46e622007-09-17 08:09:54 +0000881
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400882 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +0100883 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400884 if (ret < 0) {
885 error_report("Invalid cache option: %s", cache);
886 return -1;
887 }
888
889 out_bs = bdrv_new_open(out_filename, out_fmt, flags);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900890 if (!out_bs) {
891 ret = -1;
892 goto out;
893 }
bellardea2384d2004-08-01 21:59:26 +0000894
balrog926c2d22007-10-31 01:11:44 +0000895 bs_i = 0;
896 bs_offset = 0;
897 bdrv_get_geometry(bs[0], &bs_sectors);
Kevin Wolfbb1c0592011-08-08 14:09:12 +0200898 buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
balrog926c2d22007-10-31 01:11:44 +0000899
Jes Sorenseneec77d92010-12-07 17:44:34 +0100900 if (compress) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900901 ret = bdrv_get_info(out_bs, &bdi);
902 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100903 error_report("could not get block driver info");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900904 goto out;
905 }
bellardfaea38e2006-08-05 21:31:00 +0000906 cluster_size = bdi.cluster_size;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900907 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100908 error_report("invalid cluster size");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900909 ret = -1;
910 goto out;
911 }
bellardea2384d2004-08-01 21:59:26 +0000912 cluster_sectors = cluster_size >> 9;
913 sector_num = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200914
915 nb_sectors = total_sectors;
916 local_progress = (float)100 /
Jes Sorensen4ee96412011-05-06 11:39:11 +0200917 (nb_sectors / MIN(nb_sectors, cluster_sectors));
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200918
bellardea2384d2004-08-01 21:59:26 +0000919 for(;;) {
balrog926c2d22007-10-31 01:11:44 +0000920 int64_t bs_num;
921 int remainder;
922 uint8_t *buf2;
923
bellardea2384d2004-08-01 21:59:26 +0000924 nb_sectors = total_sectors - sector_num;
925 if (nb_sectors <= 0)
926 break;
927 if (nb_sectors >= cluster_sectors)
928 n = cluster_sectors;
929 else
930 n = nb_sectors;
balrog926c2d22007-10-31 01:11:44 +0000931
932 bs_num = sector_num - bs_offset;
933 assert (bs_num >= 0);
934 remainder = n;
935 buf2 = buf;
936 while (remainder > 0) {
937 int nlow;
938 while (bs_num == bs_sectors) {
939 bs_i++;
940 assert (bs_i < bs_n);
941 bs_offset += bs_sectors;
942 bdrv_get_geometry(bs[bs_i], &bs_sectors);
943 bs_num = 0;
Blue Swirl0bfcd592010-05-22 08:02:12 +0000944 /* printf("changing part: sector_num=%" PRId64 ", "
945 "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
946 "\n", sector_num, bs_i, bs_offset, bs_sectors); */
balrog926c2d22007-10-31 01:11:44 +0000947 }
948 assert (bs_num < bs_sectors);
949
950 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
951
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900952 ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
953 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +0100954 error_report("error while reading sector %" PRId64 ": %s",
955 bs_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900956 goto out;
957 }
balrog926c2d22007-10-31 01:11:44 +0000958
959 buf2 += nlow * 512;
960 bs_num += nlow;
961
962 remainder -= nlow;
963 }
964 assert (remainder == 0);
965
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100966 if (n < cluster_sectors) {
bellardea2384d2004-08-01 21:59:26 +0000967 memset(buf + n * 512, 0, cluster_size - n * 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100968 }
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000969 if (!buffer_is_zero(buf, cluster_size)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900970 ret = bdrv_write_compressed(out_bs, sector_num, buf,
971 cluster_sectors);
972 if (ret != 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +0100973 error_report("error while compressing sector %" PRId64
974 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900975 goto out;
976 }
bellardea2384d2004-08-01 21:59:26 +0000977 }
978 sector_num += n;
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200979 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +0000980 }
bellardfaea38e2006-08-05 21:31:00 +0000981 /* signal EOF to align */
982 bdrv_write_compressed(out_bs, 0, NULL, 0);
bellardea2384d2004-08-01 21:59:26 +0000983 } else {
Kevin Wolff2feebb2010-04-14 17:30:35 +0200984 int has_zero_init = bdrv_has_zero_init(out_bs);
985
thsf58c7b32008-06-05 21:53:49 +0000986 sector_num = 0; // total number of sectors converted so far
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200987 nb_sectors = total_sectors - sector_num;
988 local_progress = (float)100 /
Jes Sorensen4ee96412011-05-06 11:39:11 +0200989 (nb_sectors / MIN(nb_sectors, IO_BUF_SIZE / 512));
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200990
bellardea2384d2004-08-01 21:59:26 +0000991 for(;;) {
992 nb_sectors = total_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100993 if (nb_sectors <= 0) {
bellardea2384d2004-08-01 21:59:26 +0000994 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100995 }
996 if (nb_sectors >= (IO_BUF_SIZE / 512)) {
bellardea2384d2004-08-01 21:59:26 +0000997 n = (IO_BUF_SIZE / 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100998 } else {
bellardea2384d2004-08-01 21:59:26 +0000999 n = nb_sectors;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001000 }
balrog926c2d22007-10-31 01:11:44 +00001001
1002 while (sector_num - bs_offset >= bs_sectors) {
1003 bs_i ++;
1004 assert (bs_i < bs_n);
1005 bs_offset += bs_sectors;
1006 bdrv_get_geometry(bs[bs_i], &bs_sectors);
Blue Swirl0bfcd592010-05-22 08:02:12 +00001007 /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
1008 "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
balrog926c2d22007-10-31 01:11:44 +00001009 sector_num, bs_i, bs_offset, bs_sectors); */
1010 }
1011
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001012 if (n > bs_offset + bs_sectors - sector_num) {
balrog926c2d22007-10-31 01:11:44 +00001013 n = bs_offset + bs_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001014 }
balrog926c2d22007-10-31 01:11:44 +00001015
Kevin Wolff2feebb2010-04-14 17:30:35 +02001016 if (has_zero_init) {
Akkarit Sangpetchd0320442009-07-17 10:02:15 +02001017 /* If the output image is being created as a copy on write image,
1018 assume that sectors which are unallocated in the input image
1019 are present in both the output's and input's base images (no
1020 need to copy them). */
1021 if (out_baseimg) {
1022 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
1023 n, &n1)) {
1024 sector_num += n1;
1025 continue;
1026 }
1027 /* The next 'n1' sectors are allocated in the input image. Copy
1028 only those as they may be followed by unallocated sectors. */
1029 n = n1;
aliguori93c65b42009-04-05 17:40:43 +00001030 }
aliguori93c65b42009-04-05 17:40:43 +00001031 } else {
1032 n1 = n;
thsf58c7b32008-06-05 21:53:49 +00001033 }
1034
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001035 ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
1036 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001037 error_report("error while reading sector %" PRId64 ": %s",
1038 sector_num - bs_offset, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001039 goto out;
1040 }
bellardea2384d2004-08-01 21:59:26 +00001041 /* NOTE: at the same time we convert, we do not write zero
1042 sectors to have a chance to compress the image. Ideally, we
1043 should add a specific call to have the info to go faster */
1044 buf1 = buf;
1045 while (n > 0) {
thsf58c7b32008-06-05 21:53:49 +00001046 /* If the output image is being created as a copy on write image,
1047 copy all sectors even the ones containing only NUL bytes,
aliguori93c65b42009-04-05 17:40:43 +00001048 because they may differ from the sectors in the base image.
1049
1050 If the output is to a host device, we also write out
1051 sectors that are entirely 0, since whatever data was
1052 already there is garbage, not 0s. */
Kevin Wolff2feebb2010-04-14 17:30:35 +02001053 if (!has_zero_init || out_baseimg ||
Kevin Wolfa22f1232011-08-26 15:27:13 +02001054 is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001055 ret = bdrv_write(out_bs, sector_num, buf1, n1);
1056 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001057 error_report("error while writing sector %" PRId64
1058 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001059 goto out;
1060 }
bellardea2384d2004-08-01 21:59:26 +00001061 }
1062 sector_num += n1;
1063 n -= n1;
1064 buf1 += n1 * 512;
1065 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001066 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +00001067 }
1068 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001069out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001070 qemu_progress_end();
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001071 free_option_parameters(create_options);
1072 free_option_parameters(param);
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001073 qemu_vfree(buf);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001074 if (out_bs) {
1075 bdrv_delete(out_bs);
1076 }
Jes Sorensen31ca34b2010-12-06 15:25:36 +01001077 if (bs) {
1078 for (bs_i = 0; bs_i < bs_n; bs_i++) {
1079 if (bs[bs_i]) {
1080 bdrv_delete(bs[bs_i]);
1081 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001082 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001083 g_free(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001084 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001085 if (ret) {
1086 return 1;
1087 }
bellardea2384d2004-08-01 21:59:26 +00001088 return 0;
1089}
1090
bellard57d1a2b2004-08-03 21:15:11 +00001091
bellardfaea38e2006-08-05 21:31:00 +00001092static void dump_snapshots(BlockDriverState *bs)
1093{
1094 QEMUSnapshotInfo *sn_tab, *sn;
1095 int nb_sns, i;
1096 char buf[256];
1097
1098 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1099 if (nb_sns <= 0)
1100 return;
1101 printf("Snapshot list:\n");
1102 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
1103 for(i = 0; i < nb_sns; i++) {
1104 sn = &sn_tab[i];
1105 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
1106 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001107 g_free(sn_tab);
bellardfaea38e2006-08-05 21:31:00 +00001108}
1109
Benoît Canetc054b3f2012-09-05 13:09:02 +02001110static void collect_snapshots(BlockDriverState *bs , ImageInfo *info)
bellardea2384d2004-08-01 21:59:26 +00001111{
Benoît Canetc054b3f2012-09-05 13:09:02 +02001112 int i, sn_count;
1113 QEMUSnapshotInfo *sn_tab = NULL;
1114 SnapshotInfoList *info_list, *cur_item = NULL;
1115 sn_count = bdrv_snapshot_list(bs, &sn_tab);
1116
1117 for (i = 0; i < sn_count; i++) {
1118 info->has_snapshots = true;
1119 info_list = g_new0(SnapshotInfoList, 1);
1120
1121 info_list->value = g_new0(SnapshotInfo, 1);
1122 info_list->value->id = g_strdup(sn_tab[i].id_str);
1123 info_list->value->name = g_strdup(sn_tab[i].name);
1124 info_list->value->vm_state_size = sn_tab[i].vm_state_size;
1125 info_list->value->date_sec = sn_tab[i].date_sec;
1126 info_list->value->date_nsec = sn_tab[i].date_nsec;
1127 info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000;
1128 info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
1129
1130 /* XXX: waiting for the qapi to support qemu-queue.h types */
1131 if (!cur_item) {
1132 info->snapshots = cur_item = info_list;
1133 } else {
1134 cur_item->next = info_list;
1135 cur_item = info_list;
1136 }
1137
1138 }
1139
1140 g_free(sn_tab);
1141}
1142
1143static void dump_json_image_info(ImageInfo *info)
1144{
1145 Error *errp = NULL;
1146 QString *str;
1147 QmpOutputVisitor *ov = qmp_output_visitor_new();
1148 QObject *obj;
1149 visit_type_ImageInfo(qmp_output_get_visitor(ov),
1150 &info, NULL, &errp);
1151 obj = qmp_output_get_qobject(ov);
1152 str = qobject_to_json_pretty(obj);
1153 assert(str != NULL);
1154 printf("%s\n", qstring_get_str(str));
1155 qobject_decref(obj);
1156 qmp_output_visitor_cleanup(ov);
1157 QDECREF(str);
1158}
1159
1160static void collect_image_info(BlockDriverState *bs,
1161 ImageInfo *info,
1162 const char *filename,
1163 const char *fmt)
1164{
ths96b8f132007-12-17 01:35:20 +00001165 uint64_t total_sectors;
bellard93b6b2a2006-08-01 15:51:11 +00001166 char backing_filename[1024];
1167 char backing_filename2[1024];
bellardfaea38e2006-08-05 21:31:00 +00001168 BlockDriverInfo bdi;
bellardea2384d2004-08-01 21:59:26 +00001169
Benoît Canetc054b3f2012-09-05 13:09:02 +02001170 bdrv_get_geometry(bs, &total_sectors);
1171
1172 info->filename = g_strdup(filename);
1173 info->format = g_strdup(bdrv_get_format_name(bs));
1174 info->virtual_size = total_sectors * 512;
1175 info->actual_size = bdrv_get_allocated_file_size(bs);
1176 info->has_actual_size = info->actual_size >= 0;
1177 if (bdrv_is_encrypted(bs)) {
1178 info->encrypted = true;
1179 info->has_encrypted = true;
1180 }
1181 if (bdrv_get_info(bs, &bdi) >= 0) {
1182 if (bdi.cluster_size != 0) {
1183 info->cluster_size = bdi.cluster_size;
1184 info->has_cluster_size = true;
1185 }
1186 info->dirty_flag = bdi.is_dirty;
1187 info->has_dirty_flag = true;
1188 }
1189 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
1190 if (backing_filename[0] != '\0') {
1191 info->backing_filename = g_strdup(backing_filename);
1192 info->has_backing_filename = true;
1193 bdrv_get_full_backing_filename(bs, backing_filename2,
1194 sizeof(backing_filename2));
1195
1196 if (strcmp(backing_filename, backing_filename2) != 0) {
1197 info->full_backing_filename =
1198 g_strdup(backing_filename2);
1199 info->has_full_backing_filename = true;
1200 }
1201
1202 if (bs->backing_format[0]) {
1203 info->backing_filename_format = g_strdup(bs->backing_format);
1204 info->has_backing_filename_format = true;
1205 }
1206 }
1207}
1208
1209static void dump_human_image_info(ImageInfo *info)
1210{
1211 char size_buf[128], dsize_buf[128];
1212 if (!info->has_actual_size) {
1213 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
1214 } else {
1215 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
1216 info->actual_size);
1217 }
1218 get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
1219 printf("image: %s\n"
1220 "file format: %s\n"
1221 "virtual size: %s (%" PRId64 " bytes)\n"
1222 "disk size: %s\n",
1223 info->filename, info->format, size_buf,
1224 info->virtual_size,
1225 dsize_buf);
1226
1227 if (info->has_encrypted && info->encrypted) {
1228 printf("encrypted: yes\n");
1229 }
1230
1231 if (info->has_cluster_size) {
1232 printf("cluster_size: %" PRId64 "\n", info->cluster_size);
1233 }
1234
1235 if (info->has_dirty_flag && info->dirty_flag) {
1236 printf("cleanly shut down: no\n");
1237 }
1238
1239 if (info->has_backing_filename) {
1240 printf("backing file: %s", info->backing_filename);
1241 if (info->has_full_backing_filename) {
1242 printf(" (actual path: %s)", info->full_backing_filename);
1243 }
1244 putchar('\n');
1245 if (info->has_backing_filename_format) {
1246 printf("backing file format: %s\n", info->backing_filename_format);
1247 }
1248 }
1249}
1250
1251enum {OPTION_OUTPUT = 256};
1252
1253typedef enum OutputFormat {
1254 OFORMAT_JSON,
1255 OFORMAT_HUMAN,
1256} OutputFormat;
1257
1258static int img_info(int argc, char **argv)
1259{
1260 int c;
1261 OutputFormat output_format = OFORMAT_HUMAN;
1262 const char *filename, *fmt, *output;
1263 BlockDriverState *bs;
1264 ImageInfo *info;
1265
bellardea2384d2004-08-01 21:59:26 +00001266 fmt = NULL;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001267 output = NULL;
bellardea2384d2004-08-01 21:59:26 +00001268 for(;;) {
Benoît Canetc054b3f2012-09-05 13:09:02 +02001269 int option_index = 0;
1270 static const struct option long_options[] = {
1271 {"help", no_argument, 0, 'h'},
1272 {"format", required_argument, 0, 'f'},
1273 {"output", required_argument, 0, OPTION_OUTPUT},
1274 {0, 0, 0, 0}
1275 };
1276 c = getopt_long(argc, argv, "f:h",
1277 long_options, &option_index);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001278 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001279 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001280 }
bellardea2384d2004-08-01 21:59:26 +00001281 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001282 case '?':
bellardea2384d2004-08-01 21:59:26 +00001283 case 'h':
1284 help();
1285 break;
1286 case 'f':
1287 fmt = optarg;
1288 break;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001289 case OPTION_OUTPUT:
1290 output = optarg;
1291 break;
bellardea2384d2004-08-01 21:59:26 +00001292 }
1293 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001294 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +00001295 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001296 }
bellardea2384d2004-08-01 21:59:26 +00001297 filename = argv[optind++];
1298
Benoît Canetc054b3f2012-09-05 13:09:02 +02001299 if (output && !strcmp(output, "json")) {
1300 output_format = OFORMAT_JSON;
1301 } else if (output && !strcmp(output, "human")) {
1302 output_format = OFORMAT_HUMAN;
1303 } else if (output) {
1304 error_report("--output must be used with human or json as argument.");
1305 return 1;
1306 }
1307
Stefan Hajnocziadfe0782010-04-13 10:29:35 +01001308 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001309 if (!bs) {
1310 return 1;
1311 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001312
1313 info = g_new0(ImageInfo, 1);
1314 collect_image_info(bs, info, filename, fmt);
1315
1316 switch (output_format) {
1317 case OFORMAT_HUMAN:
1318 dump_human_image_info(info);
1319 dump_snapshots(bs);
1320 break;
1321 case OFORMAT_JSON:
1322 collect_snapshots(bs, info);
1323 dump_json_image_info(info);
1324 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001325 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001326
1327 qapi_free_ImageInfo(info);
bellardea2384d2004-08-01 21:59:26 +00001328 bdrv_delete(bs);
1329 return 0;
1330}
1331
aliguorif7b4a942009-01-07 17:40:15 +00001332#define SNAPSHOT_LIST 1
1333#define SNAPSHOT_CREATE 2
1334#define SNAPSHOT_APPLY 3
1335#define SNAPSHOT_DELETE 4
1336
Stuart Brady153859b2009-06-07 00:42:17 +01001337static int img_snapshot(int argc, char **argv)
aliguorif7b4a942009-01-07 17:40:15 +00001338{
1339 BlockDriverState *bs;
1340 QEMUSnapshotInfo sn;
1341 char *filename, *snapshot_name = NULL;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001342 int c, ret = 0, bdrv_oflags;
aliguorif7b4a942009-01-07 17:40:15 +00001343 int action = 0;
1344 qemu_timeval tv;
1345
Kevin Wolf710da702011-01-10 12:33:02 +01001346 bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
aliguorif7b4a942009-01-07 17:40:15 +00001347 /* Parse commandline parameters */
1348 for(;;) {
1349 c = getopt(argc, argv, "la:c:d:h");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001350 if (c == -1) {
aliguorif7b4a942009-01-07 17:40:15 +00001351 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001352 }
aliguorif7b4a942009-01-07 17:40:15 +00001353 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001354 case '?':
aliguorif7b4a942009-01-07 17:40:15 +00001355 case 'h':
1356 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001357 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001358 case 'l':
1359 if (action) {
1360 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001361 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001362 }
1363 action = SNAPSHOT_LIST;
Naphtali Spreif5edb012010-01-17 16:48:13 +02001364 bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
aliguorif7b4a942009-01-07 17:40:15 +00001365 break;
1366 case 'a':
1367 if (action) {
1368 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001369 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001370 }
1371 action = SNAPSHOT_APPLY;
1372 snapshot_name = optarg;
1373 break;
1374 case 'c':
1375 if (action) {
1376 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001377 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001378 }
1379 action = SNAPSHOT_CREATE;
1380 snapshot_name = optarg;
1381 break;
1382 case 'd':
1383 if (action) {
1384 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001385 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001386 }
1387 action = SNAPSHOT_DELETE;
1388 snapshot_name = optarg;
1389 break;
1390 }
1391 }
1392
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001393 if (optind >= argc) {
aliguorif7b4a942009-01-07 17:40:15 +00001394 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001395 }
aliguorif7b4a942009-01-07 17:40:15 +00001396 filename = argv[optind++];
1397
1398 /* Open the image */
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001399 bs = bdrv_new_open(filename, NULL, bdrv_oflags);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001400 if (!bs) {
1401 return 1;
1402 }
aliguorif7b4a942009-01-07 17:40:15 +00001403
1404 /* Perform the requested action */
1405 switch(action) {
1406 case SNAPSHOT_LIST:
1407 dump_snapshots(bs);
1408 break;
1409
1410 case SNAPSHOT_CREATE:
1411 memset(&sn, 0, sizeof(sn));
1412 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1413
1414 qemu_gettimeofday(&tv);
1415 sn.date_sec = tv.tv_sec;
1416 sn.date_nsec = tv.tv_usec * 1000;
1417
1418 ret = bdrv_snapshot_create(bs, &sn);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001419 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001420 error_report("Could not create snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001421 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001422 }
aliguorif7b4a942009-01-07 17:40:15 +00001423 break;
1424
1425 case SNAPSHOT_APPLY:
1426 ret = bdrv_snapshot_goto(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001427 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001428 error_report("Could not apply snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001429 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001430 }
aliguorif7b4a942009-01-07 17:40:15 +00001431 break;
1432
1433 case SNAPSHOT_DELETE:
1434 ret = bdrv_snapshot_delete(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001435 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001436 error_report("Could not delete snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001437 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001438 }
aliguorif7b4a942009-01-07 17:40:15 +00001439 break;
1440 }
1441
1442 /* Cleanup */
1443 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001444 if (ret) {
1445 return 1;
1446 }
Stuart Brady153859b2009-06-07 00:42:17 +01001447 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001448}
1449
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001450static int img_rebase(int argc, char **argv)
1451{
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001452 BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001453 BlockDriver *old_backing_drv, *new_backing_drv;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001454 char *filename;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001455 const char *fmt, *cache, *out_basefmt, *out_baseimg;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001456 int c, flags, ret;
1457 int unsafe = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001458 int progress = 0;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001459
1460 /* Parse commandline parameters */
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001461 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001462 cache = BDRV_DEFAULT_CACHE;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001463 out_baseimg = NULL;
1464 out_basefmt = NULL;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001465 for(;;) {
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001466 c = getopt(argc, argv, "uhf:F:b:pt:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001467 if (c == -1) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001468 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001469 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001470 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001471 case '?':
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001472 case 'h':
1473 help();
1474 return 0;
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001475 case 'f':
1476 fmt = optarg;
1477 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001478 case 'F':
1479 out_basefmt = optarg;
1480 break;
1481 case 'b':
1482 out_baseimg = optarg;
1483 break;
1484 case 'u':
1485 unsafe = 1;
1486 break;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001487 case 'p':
1488 progress = 1;
1489 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001490 case 't':
1491 cache = optarg;
1492 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001493 }
1494 }
1495
Anthony Liguori9a9d9db2011-04-13 15:51:47 +01001496 if ((optind >= argc) || (!unsafe && !out_baseimg)) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001497 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001498 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001499 filename = argv[optind++];
1500
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001501 qemu_progress_init(progress, 2.0);
1502 qemu_progress_print(0, 100);
1503
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001504 flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +01001505 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001506 if (ret < 0) {
1507 error_report("Invalid cache option: %s", cache);
1508 return -1;
1509 }
1510
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001511 /*
1512 * Open the images.
1513 *
1514 * Ignore the old backing file for unsafe rebase in case we want to correct
1515 * the reference to a renamed or moved backing file.
1516 */
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001517 bs = bdrv_new_open(filename, fmt, flags);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001518 if (!bs) {
1519 return 1;
1520 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001521
1522 /* Find the right drivers for the backing files */
1523 old_backing_drv = NULL;
1524 new_backing_drv = NULL;
1525
1526 if (!unsafe && bs->backing_format[0] != '\0') {
1527 old_backing_drv = bdrv_find_format(bs->backing_format);
1528 if (old_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001529 error_report("Invalid format name: '%s'", bs->backing_format);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001530 ret = -1;
1531 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001532 }
1533 }
1534
1535 if (out_basefmt != NULL) {
1536 new_backing_drv = bdrv_find_format(out_basefmt);
1537 if (new_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001538 error_report("Invalid format name: '%s'", out_basefmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001539 ret = -1;
1540 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001541 }
1542 }
1543
1544 /* For safe rebasing we need to compare old and new backing file */
1545 if (unsafe) {
1546 /* Make the compiler happy */
1547 bs_old_backing = NULL;
1548 bs_new_backing = NULL;
1549 } else {
1550 char backing_name[1024];
1551
1552 bs_old_backing = bdrv_new("old_backing");
1553 bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001554 ret = bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,
1555 old_backing_drv);
1556 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001557 error_report("Could not open old backing file '%s'", backing_name);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001558 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001559 }
1560
1561 bs_new_backing = bdrv_new("new_backing");
Kevin Wolfcdbae852010-08-17 18:58:55 +02001562 ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001563 new_backing_drv);
1564 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001565 error_report("Could not open new backing file '%s'", out_baseimg);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001566 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001567 }
1568 }
1569
1570 /*
1571 * Check each unallocated cluster in the COW file. If it is unallocated,
1572 * accesses go to the backing file. We must therefore compare this cluster
1573 * in the old and new backing file, and if they differ we need to copy it
1574 * from the old backing file into the COW file.
1575 *
1576 * If qemu-img crashes during this step, no harm is done. The content of
1577 * the image is the same as the original one at any time.
1578 */
1579 if (!unsafe) {
1580 uint64_t num_sectors;
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01001581 uint64_t old_backing_num_sectors;
1582 uint64_t new_backing_num_sectors;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001583 uint64_t sector;
Kevin Wolfcc60e322010-04-29 14:47:48 +02001584 int n;
TeLeMand6771bf2010-02-08 16:20:00 +08001585 uint8_t * buf_old;
1586 uint8_t * buf_new;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001587 float local_progress;
TeLeMand6771bf2010-02-08 16:20:00 +08001588
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001589 buf_old = qemu_blockalign(bs, IO_BUF_SIZE);
1590 buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001591
1592 bdrv_get_geometry(bs, &num_sectors);
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01001593 bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
1594 bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001595
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001596 local_progress = (float)100 /
Jes Sorensen4ee96412011-05-06 11:39:11 +02001597 (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001598 for (sector = 0; sector < num_sectors; sector += n) {
1599
1600 /* How many sectors can we handle with the next read? */
1601 if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
1602 n = (IO_BUF_SIZE / 512);
1603 } else {
1604 n = num_sectors - sector;
1605 }
1606
1607 /* If the cluster is allocated, we don't need to take action */
Kevin Wolfcc60e322010-04-29 14:47:48 +02001608 ret = bdrv_is_allocated(bs, sector, n, &n);
1609 if (ret) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001610 continue;
1611 }
1612
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01001613 /*
1614 * Read old and new backing file and take into consideration that
1615 * backing files may be smaller than the COW image.
1616 */
1617 if (sector >= old_backing_num_sectors) {
1618 memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
1619 } else {
1620 if (sector + n > old_backing_num_sectors) {
1621 n = old_backing_num_sectors - sector;
1622 }
1623
1624 ret = bdrv_read(bs_old_backing, sector, buf_old, n);
1625 if (ret < 0) {
1626 error_report("error while reading from old backing file");
1627 goto out;
1628 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001629 }
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01001630
1631 if (sector >= new_backing_num_sectors) {
1632 memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
1633 } else {
1634 if (sector + n > new_backing_num_sectors) {
1635 n = new_backing_num_sectors - sector;
1636 }
1637
1638 ret = bdrv_read(bs_new_backing, sector, buf_new, n);
1639 if (ret < 0) {
1640 error_report("error while reading from new backing file");
1641 goto out;
1642 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001643 }
1644
1645 /* If they differ, we need to write to the COW file */
1646 uint64_t written = 0;
1647
1648 while (written < n) {
1649 int pnum;
1650
1651 if (compare_sectors(buf_old + written * 512,
Kevin Wolf60b1bd42010-02-17 12:32:59 +01001652 buf_new + written * 512, n - written, &pnum))
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001653 {
1654 ret = bdrv_write(bs, sector + written,
1655 buf_old + written * 512, pnum);
1656 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001657 error_report("Error while writing to COW image: %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001658 strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001659 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001660 }
1661 }
1662
1663 written += pnum;
1664 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001665 qemu_progress_print(local_progress, 100);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001666 }
TeLeMand6771bf2010-02-08 16:20:00 +08001667
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001668 qemu_vfree(buf_old);
1669 qemu_vfree(buf_new);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001670 }
1671
1672 /*
1673 * Change the backing file. All clusters that are different from the old
1674 * backing file are overwritten in the COW file now, so the visible content
1675 * doesn't change when we switch the backing file.
1676 */
1677 ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
1678 if (ret == -ENOSPC) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001679 error_report("Could not change the backing file to '%s': No "
1680 "space left in the file header", out_baseimg);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001681 } else if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001682 error_report("Could not change the backing file to '%s': %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001683 out_baseimg, strerror(-ret));
1684 }
1685
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001686 qemu_progress_print(100, 0);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001687 /*
1688 * TODO At this point it is possible to check if any clusters that are
1689 * allocated in the COW file are the same in the backing file. If so, they
1690 * could be dropped from the COW file. Don't do this before switching the
1691 * backing file, in case of a crash this would lead to corruption.
1692 */
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001693out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001694 qemu_progress_end();
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001695 /* Cleanup */
1696 if (!unsafe) {
Kevin Wolfeb863ad2011-03-31 12:39:51 +02001697 if (bs_old_backing != NULL) {
1698 bdrv_delete(bs_old_backing);
1699 }
1700 if (bs_new_backing != NULL) {
1701 bdrv_delete(bs_new_backing);
1702 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001703 }
1704
1705 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001706 if (ret) {
1707 return 1;
1708 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001709 return 0;
1710}
1711
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001712static int img_resize(int argc, char **argv)
1713{
1714 int c, ret, relative;
1715 const char *filename, *fmt, *size;
1716 int64_t n, total_size;
Jes Sorensen2a819982010-12-06 17:08:31 +01001717 BlockDriverState *bs = NULL;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08001718 QemuOpts *param;
1719 static QemuOptsList resize_options = {
1720 .name = "resize_options",
1721 .head = QTAILQ_HEAD_INITIALIZER(resize_options.head),
1722 .desc = {
1723 {
1724 .name = BLOCK_OPT_SIZE,
1725 .type = QEMU_OPT_SIZE,
1726 .help = "Virtual disk size"
1727 }, {
1728 /* end of list */
1729 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001730 },
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001731 };
1732
Kevin Wolfe80fec72011-04-29 10:58:12 +02001733 /* Remove size from argv manually so that negative numbers are not treated
1734 * as options by getopt. */
1735 if (argc < 3) {
1736 help();
1737 return 1;
1738 }
1739
1740 size = argv[--argc];
1741
1742 /* Parse getopt arguments */
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001743 fmt = NULL;
1744 for(;;) {
1745 c = getopt(argc, argv, "f:h");
1746 if (c == -1) {
1747 break;
1748 }
1749 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001750 case '?':
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001751 case 'h':
1752 help();
1753 break;
1754 case 'f':
1755 fmt = optarg;
1756 break;
1757 }
1758 }
Kevin Wolfe80fec72011-04-29 10:58:12 +02001759 if (optind >= argc) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001760 help();
1761 }
1762 filename = argv[optind++];
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001763
1764 /* Choose grow, shrink, or absolute resize mode */
1765 switch (size[0]) {
1766 case '+':
1767 relative = 1;
1768 size++;
1769 break;
1770 case '-':
1771 relative = -1;
1772 size++;
1773 break;
1774 default:
1775 relative = 0;
1776 break;
1777 }
1778
1779 /* Parse size */
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08001780 param = qemu_opts_create(&resize_options, NULL, 0, NULL);
1781 if (qemu_opt_set(param, BLOCK_OPT_SIZE, size)) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001782 /* Error message already printed when size parsing fails */
Jes Sorensen2a819982010-12-06 17:08:31 +01001783 ret = -1;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08001784 qemu_opts_del(param);
Jes Sorensen2a819982010-12-06 17:08:31 +01001785 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001786 }
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08001787 n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
1788 qemu_opts_del(param);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001789
1790 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001791 if (!bs) {
Jes Sorensen2a819982010-12-06 17:08:31 +01001792 ret = -1;
1793 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001794 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001795
1796 if (relative) {
1797 total_size = bdrv_getlength(bs) + n * relative;
1798 } else {
1799 total_size = n;
1800 }
1801 if (total_size <= 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001802 error_report("New image size must be positive");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001803 ret = -1;
1804 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001805 }
1806
1807 ret = bdrv_truncate(bs, total_size);
1808 switch (ret) {
1809 case 0:
1810 printf("Image resized.\n");
1811 break;
1812 case -ENOTSUP:
Kevin Wolf259b2172012-03-06 12:44:45 +01001813 error_report("This image does not support resize");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001814 break;
1815 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +01001816 error_report("Image is read-only");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001817 break;
1818 default:
Jes Sorensen15654a62010-12-16 14:31:53 +01001819 error_report("Error resizing image (%d)", -ret);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001820 break;
1821 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001822out:
Jes Sorensen2a819982010-12-06 17:08:31 +01001823 if (bs) {
1824 bdrv_delete(bs);
1825 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001826 if (ret) {
1827 return 1;
1828 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001829 return 0;
1830}
1831
Anthony Liguoric227f092009-10-01 16:12:16 -05001832static const img_cmd_t img_cmds[] = {
Stuart Brady153859b2009-06-07 00:42:17 +01001833#define DEF(option, callback, arg_string) \
1834 { option, callback },
1835#include "qemu-img-cmds.h"
1836#undef DEF
1837#undef GEN_DOCS
1838 { NULL, NULL, },
1839};
1840
bellardea2384d2004-08-01 21:59:26 +00001841int main(int argc, char **argv)
1842{
Anthony Liguoric227f092009-10-01 16:12:16 -05001843 const img_cmd_t *cmd;
Stuart Brady153859b2009-06-07 00:42:17 +01001844 const char *cmdname;
bellardea2384d2004-08-01 21:59:26 +00001845
Kevin Wolf53f76e52010-12-16 15:10:32 +01001846 error_set_progname(argv[0]);
1847
bellardea2384d2004-08-01 21:59:26 +00001848 bdrv_init();
1849 if (argc < 2)
1850 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001851 cmdname = argv[1];
aurel328f9b1572009-02-09 18:14:31 +00001852 argc--; argv++;
Stuart Brady153859b2009-06-07 00:42:17 +01001853
Zhi Yong Wu67d384e2012-02-19 22:24:35 +08001854 qemu_init_main_loop();
1855
Stuart Brady153859b2009-06-07 00:42:17 +01001856 /* find the command */
1857 for(cmd = img_cmds; cmd->name != NULL; cmd++) {
1858 if (!strcmp(cmdname, cmd->name)) {
1859 return cmd->handler(argc, argv);
1860 }
bellardea2384d2004-08-01 21:59:26 +00001861 }
Stuart Brady153859b2009-06-07 00:42:17 +01001862
1863 /* not found */
1864 help();
bellardea2384d2004-08-01 21:59:26 +00001865 return 0;
1866}