blob: dece1b3a3aeda8cbf47a290399d44181f980a54b [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"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010026#include "qapi/qmp/qjson.h"
pbrookfaf07962007-11-11 02:51:17 +000027#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010028#include "qemu/option.h"
29#include "qemu/error-report.h"
30#include "qemu/osdep.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010031#include "sysemu/sysemu.h"
Paolo Bonzini737e1502012-12-17 18:19:44 +010032#include "block/block_int.h"
Wenchao Xiaf364ec62013-05-25 11:09:44 +080033#include "block/qapi.h"
Benoît Canetc054b3f2012-09-05 13:09:02 +020034#include <getopt.h>
aliguori9230eaf2009-03-28 17:55:19 +000035#include <stdio.h>
Miroslav Rezaninaf382d432013-02-13 09:09:40 +010036#include <stdarg.h>
bellardea2384d2004-08-01 21:59:26 +000037
bellarde8445332006-06-14 15:32:10 +000038#ifdef _WIN32
39#include <windows.h>
40#endif
41
Anthony Liguoric227f092009-10-01 16:12:16 -050042typedef struct img_cmd_t {
Stuart Brady153859b2009-06-07 00:42:17 +010043 const char *name;
44 int (*handler)(int argc, char **argv);
Anthony Liguoric227f092009-10-01 16:12:16 -050045} img_cmd_t;
Stuart Brady153859b2009-06-07 00:42:17 +010046
Federico Simoncelli8599ea42013-01-28 06:59:47 -050047enum {
48 OPTION_OUTPUT = 256,
49 OPTION_BACKING_CHAIN = 257,
50};
51
52typedef enum OutputFormat {
53 OFORMAT_JSON,
54 OFORMAT_HUMAN,
55} OutputFormat;
56
aurel32137519c2008-11-30 19:12:49 +000057/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
Stefan Hajnocziadfe0782010-04-13 10:29:35 +010058#define BDRV_O_FLAGS BDRV_O_CACHE_WB
Federico Simoncelli661a0f72011-06-20 12:48:19 -040059#define BDRV_DEFAULT_CACHE "writeback"
aurel32137519c2008-11-30 19:12:49 +000060
bellardea2384d2004-08-01 21:59:26 +000061static void format_print(void *opaque, const char *name)
62{
63 printf(" %s", name);
64}
65
blueswir1d2c639d2009-01-24 18:19:25 +000066/* Please keep in synch with qemu-img.texi */
pbrook3f379ab2007-11-11 03:33:13 +000067static void help(void)
bellardea2384d2004-08-01 21:59:26 +000068{
Paolo Bonzinie00291c2010-02-04 16:49:56 +010069 const char *help_msg =
70 "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
malc3f020d72010-02-08 12:04:56 +030071 "usage: qemu-img command [command options]\n"
72 "QEMU disk image utility\n"
73 "\n"
74 "Command syntax:\n"
Stuart Brady153859b2009-06-07 00:42:17 +010075#define DEF(option, callback, arg_string) \
76 " " arg_string "\n"
77#include "qemu-img-cmds.h"
78#undef DEF
79#undef GEN_DOCS
malc3f020d72010-02-08 12:04:56 +030080 "\n"
81 "Command parameters:\n"
82 " 'filename' is a disk image filename\n"
83 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
Federico Simoncelli661a0f72011-06-20 12:48:19 -040084 " 'cache' is the cache mode used to write the output disk image, the valid\n"
Liu Yuan80ccf932012-04-20 17:10:56 +080085 " options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
86 " 'directsync' and 'unsafe' (default for convert)\n"
malc3f020d72010-02-08 12:04:56 +030087 " 'size' is the disk image size in bytes. Optional suffixes\n"
Kevin Wolf5e009842013-06-05 14:19:27 +020088 " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M),\n"
89 " 'T' (terabyte, 1024G), 'P' (petabyte, 1024T) and 'E' (exabyte, 1024P) are\n"
90 " supported. 'b' is ignored.\n"
malc3f020d72010-02-08 12:04:56 +030091 " 'output_filename' is the destination disk image filename\n"
92 " 'output_fmt' is the destination format\n"
93 " 'options' is a comma separated list of format specific options in a\n"
94 " name=value format. Use -o ? for an overview of the options supported by the\n"
95 " used format\n"
96 " '-c' indicates that target image must be compressed (qcow format only)\n"
97 " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
98 " match exactly. The image doesn't need a working backing file before\n"
99 " rebasing in this case (useful for renaming the backing file)\n"
100 " '-h' with or without a command shows this help and lists the supported formats\n"
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200101 " '-p' show progress of command (only certain commands)\n"
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100102 " '-q' use Quiet mode - do not print any output (except errors)\n"
Kevin Wolfa22f1232011-08-26 15:27:13 +0200103 " '-S' indicates the consecutive number of bytes that must contain only zeros\n"
104 " for qemu-img to create a sparse image during conversion\n"
Benoît Canetc054b3f2012-09-05 13:09:02 +0200105 " '--output' takes the format in which the output must be done (human or json)\n"
malc3f020d72010-02-08 12:04:56 +0300106 "\n"
Kevin Wolf4534ff52012-05-11 16:07:02 +0200107 "Parameters to check subcommand:\n"
108 " '-r' tries to repair any inconsistencies that are found during the check.\n"
109 " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
110 " kinds of errors, with a higher risk of choosing the wrong fix or\n"
Stefan Weil0546b8c2012-08-10 22:03:25 +0200111 " hiding corruption that has already occurred.\n"
Kevin Wolf4534ff52012-05-11 16:07:02 +0200112 "\n"
malc3f020d72010-02-08 12:04:56 +0300113 "Parameters to snapshot subcommand:\n"
114 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
115 " '-a' applies a snapshot (revert disk to saved state)\n"
116 " '-c' creates a snapshot\n"
117 " '-d' deletes a snapshot\n"
Miroslav Rezaninad14ed182013-02-13 09:09:41 +0100118 " '-l' lists all snapshots in the given image\n"
119 "\n"
120 "Parameters to compare subcommand:\n"
121 " '-f' first image format\n"
122 " '-F' second image format\n"
123 " '-s' run in Strict mode - fail on different image size or sector allocation\n";
Paolo Bonzinie00291c2010-02-04 16:49:56 +0100124
125 printf("%s\nSupported formats:", help_msg);
bellardea2384d2004-08-01 21:59:26 +0000126 bdrv_iterate_format(format_print, NULL);
127 printf("\n");
128 exit(1);
129}
130
Stefan Weil7c30f652013-06-16 17:01:05 +0200131static int GCC_FMT_ATTR(2, 3) qprintf(bool quiet, const char *fmt, ...)
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100132{
133 int ret = 0;
134 if (!quiet) {
135 va_list args;
136 va_start(args, fmt);
137 ret = vprintf(fmt, args);
138 va_end(args);
139 }
140 return ret;
141}
142
bellardea2384d2004-08-01 21:59:26 +0000143#if defined(WIN32)
144/* XXX: put correct support for win32 */
145static int read_password(char *buf, int buf_size)
146{
147 int c, i;
148 printf("Password: ");
149 fflush(stdout);
150 i = 0;
151 for(;;) {
152 c = getchar();
153 if (c == '\n')
154 break;
155 if (i < (buf_size - 1))
156 buf[i++] = c;
157 }
158 buf[i] = '\0';
159 return 0;
160}
161
162#else
163
164#include <termios.h>
165
166static struct termios oldtty;
167
168static void term_exit(void)
169{
170 tcsetattr (0, TCSANOW, &oldtty);
171}
172
173static void term_init(void)
174{
175 struct termios tty;
176
177 tcgetattr (0, &tty);
178 oldtty = tty;
179
180 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
181 |INLCR|IGNCR|ICRNL|IXON);
182 tty.c_oflag |= OPOST;
183 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
184 tty.c_cflag &= ~(CSIZE|PARENB);
185 tty.c_cflag |= CS8;
186 tty.c_cc[VMIN] = 1;
187 tty.c_cc[VTIME] = 0;
ths3b46e622007-09-17 08:09:54 +0000188
bellardea2384d2004-08-01 21:59:26 +0000189 tcsetattr (0, TCSANOW, &tty);
190
191 atexit(term_exit);
192}
193
pbrook3f379ab2007-11-11 03:33:13 +0000194static int read_password(char *buf, int buf_size)
bellardea2384d2004-08-01 21:59:26 +0000195{
196 uint8_t ch;
197 int i, ret;
198
199 printf("password: ");
200 fflush(stdout);
201 term_init();
202 i = 0;
203 for(;;) {
204 ret = read(0, &ch, 1);
205 if (ret == -1) {
206 if (errno == EAGAIN || errno == EINTR) {
207 continue;
208 } else {
209 ret = -1;
210 break;
211 }
212 } else if (ret == 0) {
213 ret = -1;
214 break;
215 } else {
216 if (ch == '\r') {
217 ret = 0;
218 break;
219 }
220 if (i < (buf_size - 1))
221 buf[i++] = ch;
222 }
223 }
224 term_exit();
225 buf[i] = '\0';
226 printf("\n");
227 return ret;
228}
229#endif
230
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100231static int print_block_option_help(const char *filename, const char *fmt)
232{
233 BlockDriver *drv, *proto_drv;
234 QEMUOptionParameter *create_options = NULL;
235
236 /* Find driver and parse its options */
237 drv = bdrv_find_format(fmt);
238 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100239 error_report("Unknown file format '%s'", fmt);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100240 return 1;
241 }
242
Kevin Wolf98289622013-07-10 15:47:39 +0200243 proto_drv = bdrv_find_protocol(filename, true);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100244 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100245 error_report("Unknown protocol '%s'", filename);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100246 return 1;
247 }
248
249 create_options = append_option_parameters(create_options,
250 drv->create_options);
251 create_options = append_option_parameters(create_options,
252 proto_drv->create_options);
253 print_option_help(create_options);
254 free_option_parameters(create_options);
255 return 0;
256}
257
bellard75c23802004-08-27 21:28:58 +0000258static BlockDriverState *bdrv_new_open(const char *filename,
Sheng Yang9bc378c2010-01-29 10:15:06 +0800259 const char *fmt,
Daniel P. Berrangef0536bb2012-09-10 12:11:31 +0100260 int flags,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100261 bool require_io,
262 bool quiet)
bellard75c23802004-08-27 21:28:58 +0000263{
264 BlockDriverState *bs;
265 BlockDriver *drv;
266 char password[256];
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100267 int ret;
bellard75c23802004-08-27 21:28:58 +0000268
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100269 bs = bdrv_new("image");
Kevin Wolfad717132010-12-16 15:37:41 +0100270
bellard75c23802004-08-27 21:28:58 +0000271 if (fmt) {
272 drv = bdrv_find_format(fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900273 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100274 error_report("Unknown file format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900275 goto fail;
276 }
bellard75c23802004-08-27 21:28:58 +0000277 } else {
278 drv = NULL;
279 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100280
Kevin Wolfde9c0ce2013-03-15 10:35:02 +0100281 ret = bdrv_open(bs, filename, NULL, flags, drv);
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100282 if (ret < 0) {
283 error_report("Could not open '%s': %s", filename, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900284 goto fail;
bellard75c23802004-08-27 21:28:58 +0000285 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100286
Daniel P. Berrangef0536bb2012-09-10 12:11:31 +0100287 if (bdrv_is_encrypted(bs) && require_io) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100288 qprintf(quiet, "Disk image '%s' is encrypted.\n", filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900289 if (read_password(password, sizeof(password)) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100290 error_report("No password given");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900291 goto fail;
292 }
293 if (bdrv_set_key(bs, password) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100294 error_report("invalid password");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900295 goto fail;
296 }
bellard75c23802004-08-27 21:28:58 +0000297 }
298 return bs;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900299fail:
300 if (bs) {
301 bdrv_delete(bs);
302 }
303 return NULL;
bellard75c23802004-08-27 21:28:58 +0000304}
305
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900306static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
Jes Sorenseneec77d92010-12-07 17:44:34 +0100307 const char *base_filename,
308 const char *base_fmt)
Kevin Wolfefa84d42009-05-18 16:42:12 +0200309{
Kevin Wolfefa84d42009-05-18 16:42:12 +0200310 if (base_filename) {
311 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100312 error_report("Backing file not supported for file format '%s'",
313 fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900314 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200315 }
316 }
317 if (base_fmt) {
318 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100319 error_report("Backing file format not supported for file "
320 "format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900321 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200322 }
323 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900324 return 0;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200325}
326
bellardea2384d2004-08-01 21:59:26 +0000327static int img_create(int argc, char **argv)
328{
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200329 int c;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100330 uint64_t img_size = -1;
bellardea2384d2004-08-01 21:59:26 +0000331 const char *fmt = "raw";
aliguori9230eaf2009-03-28 17:55:19 +0000332 const char *base_fmt = NULL;
bellardea2384d2004-08-01 21:59:26 +0000333 const char *filename;
334 const char *base_filename = NULL;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200335 char *options = NULL;
Luiz Capitulino9b375252012-11-30 10:52:05 -0200336 Error *local_err = NULL;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100337 bool quiet = false;
ths3b46e622007-09-17 08:09:54 +0000338
bellardea2384d2004-08-01 21:59:26 +0000339 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100340 c = getopt(argc, argv, "F:b:f:he6o:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100341 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000342 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100343 }
bellardea2384d2004-08-01 21:59:26 +0000344 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100345 case '?':
bellardea2384d2004-08-01 21:59:26 +0000346 case 'h':
347 help();
348 break;
aliguori9230eaf2009-03-28 17:55:19 +0000349 case 'F':
350 base_fmt = optarg;
351 break;
bellardea2384d2004-08-01 21:59:26 +0000352 case 'b':
353 base_filename = optarg;
354 break;
355 case 'f':
356 fmt = optarg;
357 break;
358 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200359 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100360 "encryption\' instead!");
361 return 1;
thsd8871c52007-10-24 16:11:42 +0000362 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200363 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100364 "compat6\' instead!");
365 return 1;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200366 case 'o':
367 options = optarg;
368 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100369 case 'q':
370 quiet = true;
371 break;
bellardea2384d2004-08-01 21:59:26 +0000372 }
373 }
aliguori9230eaf2009-03-28 17:55:19 +0000374
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900375 /* Get the filename */
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100376 if (optind >= argc) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900377 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100378 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900379 filename = argv[optind++];
380
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100381 /* Get image size, if specified */
382 if (optind < argc) {
Jes Sorensen70b4f4b2011-01-05 11:41:02 +0100383 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +0100384 char *end;
385 sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
386 if (sval < 0 || *end) {
liguang79443392012-12-17 09:49:23 +0800387 if (sval == -ERANGE) {
388 error_report("Image size must be less than 8 EiB!");
389 } else {
390 error_report("Invalid image size specified! You may use k, M, "
Kevin Wolf5e009842013-06-05 14:19:27 +0200391 "G, T, P or E suffixes for ");
392 error_report("kilobytes, megabytes, gigabytes, terabytes, "
393 "petabytes and exabytes.");
liguang79443392012-12-17 09:49:23 +0800394 }
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200395 return 1;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100396 }
397 img_size = (uint64_t)sval;
398 }
Kevin Wolffc11eb22013-08-05 10:53:04 +0200399 if (optind != argc) {
400 help();
401 }
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100402
Peter Maydellc8057f92012-08-02 13:45:54 +0100403 if (options && is_help_option(options)) {
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200404 return print_block_option_help(filename, fmt);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100405 }
406
Luiz Capitulino9b375252012-11-30 10:52:05 -0200407 bdrv_img_create(filename, fmt, base_filename, base_fmt,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100408 options, img_size, BDRV_O_FLAGS, &local_err, quiet);
Luiz Capitulino9b375252012-11-30 10:52:05 -0200409 if (error_is_set(&local_err)) {
410 error_report("%s", error_get_pretty(local_err));
411 error_free(local_err);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900412 return 1;
413 }
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200414
bellardea2384d2004-08-01 21:59:26 +0000415 return 0;
416}
417
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100418static void dump_json_image_check(ImageCheck *check, bool quiet)
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500419{
420 Error *errp = NULL;
421 QString *str;
422 QmpOutputVisitor *ov = qmp_output_visitor_new();
423 QObject *obj;
424 visit_type_ImageCheck(qmp_output_get_visitor(ov),
425 &check, NULL, &errp);
426 obj = qmp_output_get_qobject(ov);
427 str = qobject_to_json_pretty(obj);
428 assert(str != NULL);
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100429 qprintf(quiet, "%s\n", qstring_get_str(str));
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500430 qobject_decref(obj);
431 qmp_output_visitor_cleanup(ov);
432 QDECREF(str);
433}
434
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100435static void dump_human_image_check(ImageCheck *check, bool quiet)
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500436{
437 if (!(check->corruptions || check->leaks || check->check_errors)) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100438 qprintf(quiet, "No errors were found on the image.\n");
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500439 } else {
440 if (check->corruptions) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100441 qprintf(quiet, "\n%" PRId64 " errors were found on the image.\n"
442 "Data may be corrupted, or further writes to the image "
443 "may corrupt it.\n",
444 check->corruptions);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500445 }
446
447 if (check->leaks) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100448 qprintf(quiet,
449 "\n%" PRId64 " leaked clusters were found on the image.\n"
450 "This means waste of disk space, but no harm to data.\n",
451 check->leaks);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500452 }
453
454 if (check->check_errors) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100455 qprintf(quiet,
456 "\n%" PRId64
457 " internal errors have occurred during the check.\n",
458 check->check_errors);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500459 }
460 }
461
462 if (check->total_clusters != 0 && check->allocated_clusters != 0) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100463 qprintf(quiet, "%" PRId64 "/%" PRId64 " = %0.2f%% allocated, "
464 "%0.2f%% fragmented, %0.2f%% compressed clusters\n",
465 check->allocated_clusters, check->total_clusters,
466 check->allocated_clusters * 100.0 / check->total_clusters,
467 check->fragmented_clusters * 100.0 / check->allocated_clusters,
468 check->compressed_clusters * 100.0 /
469 check->allocated_clusters);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500470 }
471
472 if (check->image_end_offset) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100473 qprintf(quiet,
474 "Image end offset: %" PRId64 "\n", check->image_end_offset);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500475 }
476}
477
478static int collect_image_check(BlockDriverState *bs,
479 ImageCheck *check,
480 const char *filename,
481 const char *fmt,
482 int fix)
483{
484 int ret;
485 BdrvCheckResult result;
486
487 ret = bdrv_check(bs, &result, fix);
488 if (ret < 0) {
489 return ret;
490 }
491
492 check->filename = g_strdup(filename);
493 check->format = g_strdup(bdrv_get_format_name(bs));
494 check->check_errors = result.check_errors;
495 check->corruptions = result.corruptions;
496 check->has_corruptions = result.corruptions != 0;
497 check->leaks = result.leaks;
498 check->has_leaks = result.leaks != 0;
499 check->corruptions_fixed = result.corruptions_fixed;
500 check->has_corruptions_fixed = result.corruptions != 0;
501 check->leaks_fixed = result.leaks_fixed;
502 check->has_leaks_fixed = result.leaks != 0;
503 check->image_end_offset = result.image_end_offset;
504 check->has_image_end_offset = result.image_end_offset != 0;
505 check->total_clusters = result.bfi.total_clusters;
506 check->has_total_clusters = result.bfi.total_clusters != 0;
507 check->allocated_clusters = result.bfi.allocated_clusters;
508 check->has_allocated_clusters = result.bfi.allocated_clusters != 0;
509 check->fragmented_clusters = result.bfi.fragmented_clusters;
510 check->has_fragmented_clusters = result.bfi.fragmented_clusters != 0;
Stefan Hajnoczie6439d72013-02-07 17:15:04 +0100511 check->compressed_clusters = result.bfi.compressed_clusters;
512 check->has_compressed_clusters = result.bfi.compressed_clusters != 0;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500513
514 return 0;
515}
516
Kevin Wolfe076f332010-06-29 11:43:13 +0200517/*
518 * Checks an image for consistency. Exit codes:
519 *
520 * 0 - Check completed, image is good
521 * 1 - Check not completed because of internal errors
522 * 2 - Check completed, image is corrupted
523 * 3 - Check completed, image has leaked clusters, but is good otherwise
524 */
aliguori15859692009-04-21 23:11:53 +0000525static int img_check(int argc, char **argv)
526{
527 int c, ret;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500528 OutputFormat output_format = OFORMAT_HUMAN;
529 const char *filename, *fmt, *output;
aliguori15859692009-04-21 23:11:53 +0000530 BlockDriverState *bs;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200531 int fix = 0;
Stefan Hajnoczi058f8f12012-08-09 13:05:56 +0100532 int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500533 ImageCheck *check;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100534 bool quiet = false;
aliguori15859692009-04-21 23:11:53 +0000535
536 fmt = NULL;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500537 output = NULL;
aliguori15859692009-04-21 23:11:53 +0000538 for(;;) {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500539 int option_index = 0;
540 static const struct option long_options[] = {
541 {"help", no_argument, 0, 'h'},
542 {"format", required_argument, 0, 'f'},
543 {"repair", no_argument, 0, 'r'},
544 {"output", required_argument, 0, OPTION_OUTPUT},
545 {0, 0, 0, 0}
546 };
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100547 c = getopt_long(argc, argv, "f:hr:q",
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500548 long_options, &option_index);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100549 if (c == -1) {
aliguori15859692009-04-21 23:11:53 +0000550 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100551 }
aliguori15859692009-04-21 23:11:53 +0000552 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100553 case '?':
aliguori15859692009-04-21 23:11:53 +0000554 case 'h':
555 help();
556 break;
557 case 'f':
558 fmt = optarg;
559 break;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200560 case 'r':
561 flags |= BDRV_O_RDWR;
562
563 if (!strcmp(optarg, "leaks")) {
564 fix = BDRV_FIX_LEAKS;
565 } else if (!strcmp(optarg, "all")) {
566 fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
567 } else {
568 help();
569 }
570 break;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500571 case OPTION_OUTPUT:
572 output = optarg;
573 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100574 case 'q':
575 quiet = true;
576 break;
aliguori15859692009-04-21 23:11:53 +0000577 }
578 }
Kevin Wolffc11eb22013-08-05 10:53:04 +0200579 if (optind != argc - 1) {
aliguori15859692009-04-21 23:11:53 +0000580 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100581 }
aliguori15859692009-04-21 23:11:53 +0000582 filename = argv[optind++];
583
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500584 if (output && !strcmp(output, "json")) {
585 output_format = OFORMAT_JSON;
586 } else if (output && !strcmp(output, "human")) {
587 output_format = OFORMAT_HUMAN;
588 } else if (output) {
589 error_report("--output must be used with human or json as argument.");
590 return 1;
591 }
592
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100593 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900594 if (!bs) {
595 return 1;
596 }
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500597
598 check = g_new0(ImageCheck, 1);
599 ret = collect_image_check(bs, check, filename, fmt, fix);
Kevin Wolfe076f332010-06-29 11:43:13 +0200600
601 if (ret == -ENOTSUP) {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500602 if (output_format == OFORMAT_HUMAN) {
603 error_report("This image format does not support checks");
604 }
605 ret = 1;
606 goto fail;
Kevin Wolfe076f332010-06-29 11:43:13 +0200607 }
608
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500609 if (check->corruptions_fixed || check->leaks_fixed) {
610 int corruptions_fixed, leaks_fixed;
611
612 leaks_fixed = check->leaks_fixed;
613 corruptions_fixed = check->corruptions_fixed;
614
615 if (output_format == OFORMAT_HUMAN) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100616 qprintf(quiet,
617 "The following inconsistencies were found and repaired:\n\n"
618 " %" PRId64 " leaked clusters\n"
619 " %" PRId64 " corruptions\n\n"
620 "Double checking the fixed image now...\n",
621 check->leaks_fixed,
622 check->corruptions_fixed);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500623 }
624
625 ret = collect_image_check(bs, check, filename, fmt, 0);
626
627 check->leaks_fixed = leaks_fixed;
628 check->corruptions_fixed = corruptions_fixed;
Kevin Wolfccf34712012-05-11 18:16:54 +0200629 }
630
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500631 switch (output_format) {
632 case OFORMAT_HUMAN:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100633 dump_human_image_check(check, quiet);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500634 break;
635 case OFORMAT_JSON:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100636 dump_json_image_check(check, quiet);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500637 break;
638 }
639
640 if (ret || check->check_errors) {
641 ret = 1;
642 goto fail;
643 }
644
645 if (check->corruptions) {
646 ret = 2;
647 } else if (check->leaks) {
648 ret = 3;
Kevin Wolfe076f332010-06-29 11:43:13 +0200649 } else {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500650 ret = 0;
aliguori15859692009-04-21 23:11:53 +0000651 }
652
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500653fail:
654 qapi_free_ImageCheck(check);
aliguori15859692009-04-21 23:11:53 +0000655 bdrv_delete(bs);
Kevin Wolfe076f332010-06-29 11:43:13 +0200656
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500657 return ret;
aliguori15859692009-04-21 23:11:53 +0000658}
659
bellardea2384d2004-08-01 21:59:26 +0000660static int img_commit(int argc, char **argv)
661{
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400662 int c, ret, flags;
663 const char *filename, *fmt, *cache;
bellardea2384d2004-08-01 21:59:26 +0000664 BlockDriverState *bs;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100665 bool quiet = false;
bellardea2384d2004-08-01 21:59:26 +0000666
667 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400668 cache = BDRV_DEFAULT_CACHE;
bellardea2384d2004-08-01 21:59:26 +0000669 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100670 c = getopt(argc, argv, "f:ht:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100671 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000672 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100673 }
bellardea2384d2004-08-01 21:59:26 +0000674 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100675 case '?':
bellardea2384d2004-08-01 21:59:26 +0000676 case 'h':
677 help();
678 break;
679 case 'f':
680 fmt = optarg;
681 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400682 case 't':
683 cache = optarg;
684 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100685 case 'q':
686 quiet = true;
687 break;
bellardea2384d2004-08-01 21:59:26 +0000688 }
689 }
Kevin Wolffc11eb22013-08-05 10:53:04 +0200690 if (optind != argc - 1) {
bellardea2384d2004-08-01 21:59:26 +0000691 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100692 }
bellardea2384d2004-08-01 21:59:26 +0000693 filename = argv[optind++];
694
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400695 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +0100696 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400697 if (ret < 0) {
698 error_report("Invalid cache option: %s", cache);
699 return -1;
700 }
701
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100702 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900703 if (!bs) {
704 return 1;
705 }
bellardea2384d2004-08-01 21:59:26 +0000706 ret = bdrv_commit(bs);
707 switch(ret) {
708 case 0:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100709 qprintf(quiet, "Image committed.\n");
bellardea2384d2004-08-01 21:59:26 +0000710 break;
711 case -ENOENT:
Jes Sorensen15654a62010-12-16 14:31:53 +0100712 error_report("No disk inserted");
bellardea2384d2004-08-01 21:59:26 +0000713 break;
714 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +0100715 error_report("Image is read-only");
bellardea2384d2004-08-01 21:59:26 +0000716 break;
717 case -ENOTSUP:
Jes Sorensen15654a62010-12-16 14:31:53 +0100718 error_report("Image is already committed");
bellardea2384d2004-08-01 21:59:26 +0000719 break;
720 default:
Jes Sorensen15654a62010-12-16 14:31:53 +0100721 error_report("Error while committing image");
bellardea2384d2004-08-01 21:59:26 +0000722 break;
723 }
724
725 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900726 if (ret) {
727 return 1;
728 }
bellardea2384d2004-08-01 21:59:26 +0000729 return 0;
730}
731
Dmitry Konishchevf6a00aa2011-05-18 15:03:59 +0400732/*
thsf58c7b32008-06-05 21:53:49 +0000733 * Returns true iff the first sector pointed to by 'buf' contains at least
734 * a non-NUL byte.
735 *
736 * 'pnum' is set to the number of sectors (including and immediately following
737 * the first one) that are known to be in the same allocated/unallocated state.
738 */
bellardea2384d2004-08-01 21:59:26 +0000739static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
740{
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000741 bool is_zero;
742 int i;
bellardea2384d2004-08-01 21:59:26 +0000743
744 if (n <= 0) {
745 *pnum = 0;
746 return 0;
747 }
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000748 is_zero = buffer_is_zero(buf, 512);
bellardea2384d2004-08-01 21:59:26 +0000749 for(i = 1; i < n; i++) {
750 buf += 512;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000751 if (is_zero != buffer_is_zero(buf, 512)) {
bellardea2384d2004-08-01 21:59:26 +0000752 break;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000753 }
bellardea2384d2004-08-01 21:59:26 +0000754 }
755 *pnum = i;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000756 return !is_zero;
bellardea2384d2004-08-01 21:59:26 +0000757}
758
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100759/*
Kevin Wolfa22f1232011-08-26 15:27:13 +0200760 * Like is_allocated_sectors, but if the buffer starts with a used sector,
761 * up to 'min' consecutive sectors containing zeros are ignored. This avoids
762 * breaking up write requests for only small sparse areas.
763 */
764static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
765 int min)
766{
767 int ret;
768 int num_checked, num_used;
769
770 if (n < min) {
771 min = n;
772 }
773
774 ret = is_allocated_sectors(buf, n, pnum);
775 if (!ret) {
776 return ret;
777 }
778
779 num_used = *pnum;
780 buf += BDRV_SECTOR_SIZE * *pnum;
781 n -= *pnum;
782 num_checked = num_used;
783
784 while (n > 0) {
785 ret = is_allocated_sectors(buf, n, pnum);
786
787 buf += BDRV_SECTOR_SIZE * *pnum;
788 n -= *pnum;
789 num_checked += *pnum;
790 if (ret) {
791 num_used = num_checked;
792 } else if (*pnum >= min) {
793 break;
794 }
795 }
796
797 *pnum = num_used;
798 return 1;
799}
800
801/*
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100802 * Compares two buffers sector by sector. Returns 0 if the first sector of both
803 * buffers matches, non-zero otherwise.
804 *
805 * pnum is set to the number of sectors (including and immediately following
806 * the first one) that are known to have the same comparison result
807 */
808static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
809 int *pnum)
810{
811 int res, i;
812
813 if (n <= 0) {
814 *pnum = 0;
815 return 0;
816 }
817
818 res = !!memcmp(buf1, buf2, 512);
819 for(i = 1; i < n; i++) {
820 buf1 += 512;
821 buf2 += 512;
822
823 if (!!memcmp(buf1, buf2, 512) != res) {
824 break;
825 }
826 }
827
828 *pnum = i;
829 return res;
830}
831
Kevin Wolf80ee15a2009-09-15 12:30:43 +0200832#define IO_BUF_SIZE (2 * 1024 * 1024)
bellardea2384d2004-08-01 21:59:26 +0000833
Miroslav Rezaninad14ed182013-02-13 09:09:41 +0100834static int64_t sectors_to_bytes(int64_t sectors)
835{
836 return sectors << BDRV_SECTOR_BITS;
837}
838
839static int64_t sectors_to_process(int64_t total, int64_t from)
840{
841 return MIN(total - from, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
842}
843
844/*
845 * Check if passed sectors are empty (not allocated or contain only 0 bytes)
846 *
847 * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero
848 * data and negative value on error.
849 *
850 * @param bs: Driver used for accessing file
851 * @param sect_num: Number of first sector to check
852 * @param sect_count: Number of sectors to check
853 * @param filename: Name of disk file we are checking (logging purpose)
854 * @param buffer: Allocated buffer for storing read data
855 * @param quiet: Flag for quiet mode
856 */
857static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
858 int sect_count, const char *filename,
859 uint8_t *buffer, bool quiet)
860{
861 int pnum, ret = 0;
862 ret = bdrv_read(bs, sect_num, buffer, sect_count);
863 if (ret < 0) {
864 error_report("Error while reading offset %" PRId64 " of %s: %s",
865 sectors_to_bytes(sect_num), filename, strerror(-ret));
866 return ret;
867 }
868 ret = is_allocated_sectors(buffer, sect_count, &pnum);
869 if (ret || pnum != sect_count) {
870 qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
871 sectors_to_bytes(ret ? sect_num : sect_num + pnum));
872 return 1;
873 }
874
875 return 0;
876}
877
878/*
879 * Compares two images. Exit codes:
880 *
881 * 0 - Images are identical
882 * 1 - Images differ
883 * >1 - Error occurred
884 */
885static int img_compare(int argc, char **argv)
886{
887 const char *fmt1 = NULL, *fmt2 = NULL, *filename1, *filename2;
888 BlockDriverState *bs1, *bs2;
889 int64_t total_sectors1, total_sectors2;
890 uint8_t *buf1 = NULL, *buf2 = NULL;
891 int pnum1, pnum2;
892 int allocated1, allocated2;
893 int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
894 bool progress = false, quiet = false, strict = false;
895 int64_t total_sectors;
896 int64_t sector_num = 0;
897 int64_t nb_sectors;
898 int c, pnum;
899 uint64_t bs_sectors;
900 uint64_t progress_base;
901
902 for (;;) {
903 c = getopt(argc, argv, "hpf:F:sq");
904 if (c == -1) {
905 break;
906 }
907 switch (c) {
908 case '?':
909 case 'h':
910 help();
911 break;
912 case 'f':
913 fmt1 = optarg;
914 break;
915 case 'F':
916 fmt2 = optarg;
917 break;
918 case 'p':
919 progress = true;
920 break;
921 case 'q':
922 quiet = true;
923 break;
924 case 's':
925 strict = true;
926 break;
927 }
928 }
929
930 /* Progress is not shown in Quiet mode */
931 if (quiet) {
932 progress = false;
933 }
934
935
Kevin Wolffc11eb22013-08-05 10:53:04 +0200936 if (optind != argc - 2) {
Miroslav Rezaninad14ed182013-02-13 09:09:41 +0100937 help();
938 }
939 filename1 = argv[optind++];
940 filename2 = argv[optind++];
941
942 /* Initialize before goto out */
943 qemu_progress_init(progress, 2.0);
944
945 bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
946 if (!bs1) {
947 error_report("Can't open file %s", filename1);
948 ret = 2;
949 goto out3;
950 }
951
952 bs2 = bdrv_new_open(filename2, fmt2, BDRV_O_FLAGS, true, quiet);
953 if (!bs2) {
954 error_report("Can't open file %s", filename2);
955 ret = 2;
956 goto out2;
957 }
958
959 buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
960 buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
961 bdrv_get_geometry(bs1, &bs_sectors);
962 total_sectors1 = bs_sectors;
963 bdrv_get_geometry(bs2, &bs_sectors);
964 total_sectors2 = bs_sectors;
965 total_sectors = MIN(total_sectors1, total_sectors2);
966 progress_base = MAX(total_sectors1, total_sectors2);
967
968 qemu_progress_print(0, 100);
969
970 if (strict && total_sectors1 != total_sectors2) {
971 ret = 1;
972 qprintf(quiet, "Strict mode: Image size mismatch!\n");
973 goto out;
974 }
975
976 for (;;) {
977 nb_sectors = sectors_to_process(total_sectors, sector_num);
978 if (nb_sectors <= 0) {
979 break;
980 }
981 allocated1 = bdrv_is_allocated_above(bs1, NULL, sector_num, nb_sectors,
982 &pnum1);
983 if (allocated1 < 0) {
984 ret = 3;
985 error_report("Sector allocation test failed for %s", filename1);
986 goto out;
987 }
988
989 allocated2 = bdrv_is_allocated_above(bs2, NULL, sector_num, nb_sectors,
990 &pnum2);
991 if (allocated2 < 0) {
992 ret = 3;
993 error_report("Sector allocation test failed for %s", filename2);
994 goto out;
995 }
996 nb_sectors = MIN(pnum1, pnum2);
997
998 if (allocated1 == allocated2) {
999 if (allocated1) {
1000 ret = bdrv_read(bs1, sector_num, buf1, nb_sectors);
1001 if (ret < 0) {
1002 error_report("Error while reading offset %" PRId64 " of %s:"
1003 " %s", sectors_to_bytes(sector_num), filename1,
1004 strerror(-ret));
1005 ret = 4;
1006 goto out;
1007 }
1008 ret = bdrv_read(bs2, sector_num, buf2, nb_sectors);
1009 if (ret < 0) {
1010 error_report("Error while reading offset %" PRId64
1011 " of %s: %s", sectors_to_bytes(sector_num),
1012 filename2, strerror(-ret));
1013 ret = 4;
1014 goto out;
1015 }
1016 ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
1017 if (ret || pnum != nb_sectors) {
1018 ret = 1;
1019 qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
1020 sectors_to_bytes(
1021 ret ? sector_num : sector_num + pnum));
1022 goto out;
1023 }
1024 }
1025 } else {
1026 if (strict) {
1027 ret = 1;
1028 qprintf(quiet, "Strict mode: Offset %" PRId64
1029 " allocation mismatch!\n",
1030 sectors_to_bytes(sector_num));
1031 goto out;
1032 }
1033
1034 if (allocated1) {
1035 ret = check_empty_sectors(bs1, sector_num, nb_sectors,
1036 filename1, buf1, quiet);
1037 } else {
1038 ret = check_empty_sectors(bs2, sector_num, nb_sectors,
1039 filename2, buf1, quiet);
1040 }
1041 if (ret) {
1042 if (ret < 0) {
1043 ret = 4;
1044 error_report("Error while reading offset %" PRId64 ": %s",
1045 sectors_to_bytes(sector_num), strerror(-ret));
1046 }
1047 goto out;
1048 }
1049 }
1050 sector_num += nb_sectors;
1051 qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
1052 }
1053
1054 if (total_sectors1 != total_sectors2) {
1055 BlockDriverState *bs_over;
1056 int64_t total_sectors_over;
1057 const char *filename_over;
1058
1059 qprintf(quiet, "Warning: Image size mismatch!\n");
1060 if (total_sectors1 > total_sectors2) {
1061 total_sectors_over = total_sectors1;
1062 bs_over = bs1;
1063 filename_over = filename1;
1064 } else {
1065 total_sectors_over = total_sectors2;
1066 bs_over = bs2;
1067 filename_over = filename2;
1068 }
1069
1070 for (;;) {
1071 nb_sectors = sectors_to_process(total_sectors_over, sector_num);
1072 if (nb_sectors <= 0) {
1073 break;
1074 }
1075 ret = bdrv_is_allocated_above(bs_over, NULL, sector_num,
1076 nb_sectors, &pnum);
1077 if (ret < 0) {
1078 ret = 3;
1079 error_report("Sector allocation test failed for %s",
1080 filename_over);
1081 goto out;
1082
1083 }
1084 nb_sectors = pnum;
1085 if (ret) {
1086 ret = check_empty_sectors(bs_over, sector_num, nb_sectors,
1087 filename_over, buf1, quiet);
1088 if (ret) {
1089 if (ret < 0) {
1090 ret = 4;
1091 error_report("Error while reading offset %" PRId64
1092 " of %s: %s", sectors_to_bytes(sector_num),
1093 filename_over, strerror(-ret));
1094 }
1095 goto out;
1096 }
1097 }
1098 sector_num += nb_sectors;
1099 qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
1100 }
1101 }
1102
1103 qprintf(quiet, "Images are identical.\n");
1104 ret = 0;
1105
1106out:
1107 bdrv_delete(bs2);
1108 qemu_vfree(buf1);
1109 qemu_vfree(buf2);
1110out2:
1111 bdrv_delete(bs1);
1112out3:
1113 qemu_progress_end();
1114 return ret;
1115}
1116
bellardea2384d2004-08-01 21:59:26 +00001117static int img_convert(int argc, char **argv)
1118{
Jes Sorenseneec77d92010-12-07 17:44:34 +01001119 int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001120 int progress = 0, flags;
1121 const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001122 BlockDriver *drv, *proto_drv;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001123 BlockDriverState **bs = NULL, *out_bs = NULL;
ths96b8f132007-12-17 01:35:20 +00001124 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
1125 uint64_t bs_sectors;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001126 uint8_t * buf = NULL;
bellardea2384d2004-08-01 21:59:26 +00001127 const uint8_t *buf1;
bellardfaea38e2006-08-05 21:31:00 +00001128 BlockDriverInfo bdi;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001129 QEMUOptionParameter *param = NULL, *create_options = NULL;
Kevin Wolfa18953f2010-10-14 15:46:04 +02001130 QEMUOptionParameter *out_baseimg_param;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001131 char *options = NULL;
edison51ef6722010-09-21 19:58:41 -07001132 const char *snapshot_name = NULL;
Kevin Wolf1f710492012-10-12 14:29:18 +02001133 float local_progress = 0;
Kevin Wolfa22f1232011-08-26 15:27:13 +02001134 int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001135 bool quiet = false;
bellardea2384d2004-08-01 21:59:26 +00001136
1137 fmt = NULL;
1138 out_fmt = "raw";
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001139 cache = "unsafe";
thsf58c7b32008-06-05 21:53:49 +00001140 out_baseimg = NULL;
Jes Sorenseneec77d92010-12-07 17:44:34 +01001141 compress = 0;
bellardea2384d2004-08-01 21:59:26 +00001142 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001143 c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001144 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001145 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001146 }
bellardea2384d2004-08-01 21:59:26 +00001147 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001148 case '?':
bellardea2384d2004-08-01 21:59:26 +00001149 case 'h':
1150 help();
1151 break;
1152 case 'f':
1153 fmt = optarg;
1154 break;
1155 case 'O':
1156 out_fmt = optarg;
1157 break;
thsf58c7b32008-06-05 21:53:49 +00001158 case 'B':
1159 out_baseimg = optarg;
1160 break;
bellardea2384d2004-08-01 21:59:26 +00001161 case 'c':
Jes Sorenseneec77d92010-12-07 17:44:34 +01001162 compress = 1;
bellardea2384d2004-08-01 21:59:26 +00001163 break;
1164 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +02001165 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +01001166 "encryption\' instead!");
1167 return 1;
thsec36ba12007-09-16 21:59:02 +00001168 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +02001169 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +01001170 "compat6\' instead!");
1171 return 1;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001172 case 'o':
1173 options = optarg;
1174 break;
edison51ef6722010-09-21 19:58:41 -07001175 case 's':
1176 snapshot_name = optarg;
1177 break;
Kevin Wolfa22f1232011-08-26 15:27:13 +02001178 case 'S':
1179 {
1180 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +01001181 char *end;
1182 sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
1183 if (sval < 0 || *end) {
Kevin Wolfa22f1232011-08-26 15:27:13 +02001184 error_report("Invalid minimum zero buffer size for sparse output specified");
1185 return 1;
1186 }
1187
1188 min_sparse = sval / BDRV_SECTOR_SIZE;
1189 break;
1190 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001191 case 'p':
1192 progress = 1;
1193 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001194 case 't':
1195 cache = optarg;
1196 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001197 case 'q':
1198 quiet = true;
1199 break;
bellardea2384d2004-08-01 21:59:26 +00001200 }
1201 }
ths3b46e622007-09-17 08:09:54 +00001202
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001203 if (quiet) {
1204 progress = 0;
1205 }
1206
balrog926c2d22007-10-31 01:11:44 +00001207 bs_n = argc - optind - 1;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001208 if (bs_n < 1) {
1209 help();
1210 }
balrog926c2d22007-10-31 01:11:44 +00001211
1212 out_filename = argv[argc - 1];
thsf58c7b32008-06-05 21:53:49 +00001213
Charles Arnoldfa170c12012-05-11 10:57:54 -06001214 /* Initialize before goto out */
1215 qemu_progress_init(progress, 2.0);
1216
Peter Maydellc8057f92012-08-02 13:45:54 +01001217 if (options && is_help_option(options)) {
Jes Sorensen4ac8aac2010-12-06 15:25:38 +01001218 ret = print_block_option_help(out_filename, out_fmt);
1219 goto out;
1220 }
1221
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001222 if (bs_n > 1 && out_baseimg) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001223 error_report("-B makes no sense when concatenating multiple input "
1224 "images");
Jes Sorensen31ca34b2010-12-06 15:25:36 +01001225 ret = -1;
1226 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001227 }
Dong Xu Wangf8111c22012-03-15 20:13:31 +08001228
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001229 qemu_progress_print(0, 100);
1230
Anthony Liguori7267c092011-08-20 22:09:37 -05001231 bs = g_malloc0(bs_n * sizeof(BlockDriverState *));
balrog926c2d22007-10-31 01:11:44 +00001232
1233 total_sectors = 0;
1234 for (bs_i = 0; bs_i < bs_n; bs_i++) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001235 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true,
1236 quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001237 if (!bs[bs_i]) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001238 error_report("Could not open '%s'", argv[optind + bs_i]);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001239 ret = -1;
1240 goto out;
1241 }
balrog926c2d22007-10-31 01:11:44 +00001242 bdrv_get_geometry(bs[bs_i], &bs_sectors);
1243 total_sectors += bs_sectors;
1244 }
bellardea2384d2004-08-01 21:59:26 +00001245
edison51ef6722010-09-21 19:58:41 -07001246 if (snapshot_name != NULL) {
1247 if (bs_n > 1) {
Markus Armbruster6daf1942011-06-22 14:03:54 +02001248 error_report("No support for concatenating multiple snapshot");
edison51ef6722010-09-21 19:58:41 -07001249 ret = -1;
1250 goto out;
1251 }
1252 if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +02001253 error_report("Failed to load snapshot");
edison51ef6722010-09-21 19:58:41 -07001254 ret = -1;
1255 goto out;
1256 }
1257 }
1258
Kevin Wolfefa84d42009-05-18 16:42:12 +02001259 /* Find driver and parse its options */
bellardea2384d2004-08-01 21:59:26 +00001260 drv = bdrv_find_format(out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001261 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001262 error_report("Unknown file format '%s'", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001263 ret = -1;
1264 goto out;
1265 }
balrog926c2d22007-10-31 01:11:44 +00001266
Kevin Wolf98289622013-07-10 15:47:39 +02001267 proto_drv = bdrv_find_protocol(out_filename, true);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001268 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001269 error_report("Unknown protocol '%s'", out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001270 ret = -1;
1271 goto out;
1272 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001273
1274 create_options = append_option_parameters(create_options,
1275 drv->create_options);
1276 create_options = append_option_parameters(create_options,
1277 proto_drv->create_options);
Kevin Wolfdb08adf2009-06-04 15:39:38 +02001278
Kevin Wolfefa84d42009-05-18 16:42:12 +02001279 if (options) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001280 param = parse_option_parameters(options, create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001281 if (param == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001282 error_report("Invalid options for file format '%s'.", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001283 ret = -1;
1284 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001285 }
1286 } else {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001287 param = parse_option_parameters("", create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001288 }
1289
1290 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
Jes Sorenseneec77d92010-12-07 17:44:34 +01001291 ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001292 if (ret < 0) {
1293 goto out;
1294 }
Kevin Wolfefa84d42009-05-18 16:42:12 +02001295
Kevin Wolfa18953f2010-10-14 15:46:04 +02001296 /* Get backing file name if -o backing_file was used */
1297 out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
1298 if (out_baseimg_param) {
1299 out_baseimg = out_baseimg_param->value.s;
1300 }
1301
Kevin Wolfefa84d42009-05-18 16:42:12 +02001302 /* Check if compression is supported */
Jes Sorenseneec77d92010-12-07 17:44:34 +01001303 if (compress) {
Kevin Wolfefa84d42009-05-18 16:42:12 +02001304 QEMUOptionParameter *encryption =
1305 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
Kevin Wolf41521fa2011-10-18 16:19:42 +02001306 QEMUOptionParameter *preallocation =
1307 get_option_parameter(param, BLOCK_OPT_PREALLOC);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001308
1309 if (!drv->bdrv_write_compressed) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001310 error_report("Compression not supported for this file format");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001311 ret = -1;
1312 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001313 }
1314
1315 if (encryption && encryption->value.n) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001316 error_report("Compression and encryption not supported at "
1317 "the same time");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001318 ret = -1;
1319 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001320 }
Kevin Wolf41521fa2011-10-18 16:19:42 +02001321
1322 if (preallocation && preallocation->value.s
1323 && strcmp(preallocation->value.s, "off"))
1324 {
1325 error_report("Compression and preallocation not supported at "
1326 "the same time");
1327 ret = -1;
1328 goto out;
1329 }
Kevin Wolfefa84d42009-05-18 16:42:12 +02001330 }
1331
1332 /* Create the new image */
1333 ret = bdrv_create(drv, out_filename, param);
bellardea2384d2004-08-01 21:59:26 +00001334 if (ret < 0) {
1335 if (ret == -ENOTSUP) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001336 error_report("Formatting not supported for file format '%s'",
1337 out_fmt);
aurel326e9ea0c2009-04-15 14:42:46 +00001338 } else if (ret == -EFBIG) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001339 error_report("The image size is too large for file format '%s'",
1340 out_fmt);
bellardea2384d2004-08-01 21:59:26 +00001341 } else {
Jes Sorensen15654a62010-12-16 14:31:53 +01001342 error_report("%s: error while converting %s: %s",
1343 out_filename, out_fmt, strerror(-ret));
bellardea2384d2004-08-01 21:59:26 +00001344 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001345 goto out;
bellardea2384d2004-08-01 21:59:26 +00001346 }
ths3b46e622007-09-17 08:09:54 +00001347
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001348 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +01001349 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001350 if (ret < 0) {
1351 error_report("Invalid cache option: %s", cache);
1352 return -1;
1353 }
1354
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001355 out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001356 if (!out_bs) {
1357 ret = -1;
1358 goto out;
1359 }
bellardea2384d2004-08-01 21:59:26 +00001360
balrog926c2d22007-10-31 01:11:44 +00001361 bs_i = 0;
1362 bs_offset = 0;
1363 bdrv_get_geometry(bs[0], &bs_sectors);
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001364 buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
balrog926c2d22007-10-31 01:11:44 +00001365
Jes Sorenseneec77d92010-12-07 17:44:34 +01001366 if (compress) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001367 ret = bdrv_get_info(out_bs, &bdi);
1368 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001369 error_report("could not get block driver info");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001370 goto out;
1371 }
bellardfaea38e2006-08-05 21:31:00 +00001372 cluster_size = bdi.cluster_size;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001373 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001374 error_report("invalid cluster size");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001375 ret = -1;
1376 goto out;
1377 }
bellardea2384d2004-08-01 21:59:26 +00001378 cluster_sectors = cluster_size >> 9;
1379 sector_num = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001380
1381 nb_sectors = total_sectors;
Kevin Wolf1f710492012-10-12 14:29:18 +02001382 if (nb_sectors != 0) {
1383 local_progress = (float)100 /
1384 (nb_sectors / MIN(nb_sectors, cluster_sectors));
1385 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001386
bellardea2384d2004-08-01 21:59:26 +00001387 for(;;) {
balrog926c2d22007-10-31 01:11:44 +00001388 int64_t bs_num;
1389 int remainder;
1390 uint8_t *buf2;
1391
bellardea2384d2004-08-01 21:59:26 +00001392 nb_sectors = total_sectors - sector_num;
1393 if (nb_sectors <= 0)
1394 break;
1395 if (nb_sectors >= cluster_sectors)
1396 n = cluster_sectors;
1397 else
1398 n = nb_sectors;
balrog926c2d22007-10-31 01:11:44 +00001399
1400 bs_num = sector_num - bs_offset;
1401 assert (bs_num >= 0);
1402 remainder = n;
1403 buf2 = buf;
1404 while (remainder > 0) {
1405 int nlow;
1406 while (bs_num == bs_sectors) {
1407 bs_i++;
1408 assert (bs_i < bs_n);
1409 bs_offset += bs_sectors;
1410 bdrv_get_geometry(bs[bs_i], &bs_sectors);
1411 bs_num = 0;
Blue Swirl0bfcd592010-05-22 08:02:12 +00001412 /* printf("changing part: sector_num=%" PRId64 ", "
1413 "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
1414 "\n", sector_num, bs_i, bs_offset, bs_sectors); */
balrog926c2d22007-10-31 01:11:44 +00001415 }
1416 assert (bs_num < bs_sectors);
1417
1418 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
1419
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001420 ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
1421 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001422 error_report("error while reading sector %" PRId64 ": %s",
1423 bs_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001424 goto out;
1425 }
balrog926c2d22007-10-31 01:11:44 +00001426
1427 buf2 += nlow * 512;
1428 bs_num += nlow;
1429
1430 remainder -= nlow;
1431 }
1432 assert (remainder == 0);
1433
Stefan Hajnoczi54f106d2013-04-15 17:17:33 +02001434 if (!buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)) {
1435 ret = bdrv_write_compressed(out_bs, sector_num, buf, n);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001436 if (ret != 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001437 error_report("error while compressing sector %" PRId64
1438 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001439 goto out;
1440 }
bellardea2384d2004-08-01 21:59:26 +00001441 }
1442 sector_num += n;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001443 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +00001444 }
bellardfaea38e2006-08-05 21:31:00 +00001445 /* signal EOF to align */
1446 bdrv_write_compressed(out_bs, 0, NULL, 0);
bellardea2384d2004-08-01 21:59:26 +00001447 } else {
Kevin Wolff2feebb2010-04-14 17:30:35 +02001448 int has_zero_init = bdrv_has_zero_init(out_bs);
1449
thsf58c7b32008-06-05 21:53:49 +00001450 sector_num = 0; // total number of sectors converted so far
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001451 nb_sectors = total_sectors - sector_num;
Kevin Wolf1f710492012-10-12 14:29:18 +02001452 if (nb_sectors != 0) {
1453 local_progress = (float)100 /
1454 (nb_sectors / MIN(nb_sectors, IO_BUF_SIZE / 512));
1455 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001456
bellardea2384d2004-08-01 21:59:26 +00001457 for(;;) {
1458 nb_sectors = total_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001459 if (nb_sectors <= 0) {
bellardea2384d2004-08-01 21:59:26 +00001460 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001461 }
1462 if (nb_sectors >= (IO_BUF_SIZE / 512)) {
bellardea2384d2004-08-01 21:59:26 +00001463 n = (IO_BUF_SIZE / 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001464 } else {
bellardea2384d2004-08-01 21:59:26 +00001465 n = nb_sectors;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001466 }
balrog926c2d22007-10-31 01:11:44 +00001467
1468 while (sector_num - bs_offset >= bs_sectors) {
1469 bs_i ++;
1470 assert (bs_i < bs_n);
1471 bs_offset += bs_sectors;
1472 bdrv_get_geometry(bs[bs_i], &bs_sectors);
Blue Swirl0bfcd592010-05-22 08:02:12 +00001473 /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
1474 "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
balrog926c2d22007-10-31 01:11:44 +00001475 sector_num, bs_i, bs_offset, bs_sectors); */
1476 }
1477
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001478 if (n > bs_offset + bs_sectors - sector_num) {
balrog926c2d22007-10-31 01:11:44 +00001479 n = bs_offset + bs_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001480 }
balrog926c2d22007-10-31 01:11:44 +00001481
Kevin Wolff2feebb2010-04-14 17:30:35 +02001482 if (has_zero_init) {
Akkarit Sangpetchd0320442009-07-17 10:02:15 +02001483 /* If the output image is being created as a copy on write image,
1484 assume that sectors which are unallocated in the input image
1485 are present in both the output's and input's base images (no
1486 need to copy them). */
1487 if (out_baseimg) {
1488 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
1489 n, &n1)) {
1490 sector_num += n1;
1491 continue;
1492 }
1493 /* The next 'n1' sectors are allocated in the input image. Copy
1494 only those as they may be followed by unallocated sectors. */
1495 n = n1;
aliguori93c65b42009-04-05 17:40:43 +00001496 }
aliguori93c65b42009-04-05 17:40:43 +00001497 } else {
1498 n1 = n;
thsf58c7b32008-06-05 21:53:49 +00001499 }
1500
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001501 ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
1502 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001503 error_report("error while reading sector %" PRId64 ": %s",
1504 sector_num - bs_offset, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001505 goto out;
1506 }
bellardea2384d2004-08-01 21:59:26 +00001507 /* NOTE: at the same time we convert, we do not write zero
1508 sectors to have a chance to compress the image. Ideally, we
1509 should add a specific call to have the info to go faster */
1510 buf1 = buf;
1511 while (n > 0) {
thsf58c7b32008-06-05 21:53:49 +00001512 /* If the output image is being created as a copy on write image,
1513 copy all sectors even the ones containing only NUL bytes,
aliguori93c65b42009-04-05 17:40:43 +00001514 because they may differ from the sectors in the base image.
1515
1516 If the output is to a host device, we also write out
1517 sectors that are entirely 0, since whatever data was
1518 already there is garbage, not 0s. */
Kevin Wolff2feebb2010-04-14 17:30:35 +02001519 if (!has_zero_init || out_baseimg ||
Kevin Wolfa22f1232011-08-26 15:27:13 +02001520 is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001521 ret = bdrv_write(out_bs, sector_num, buf1, n1);
1522 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001523 error_report("error while writing sector %" PRId64
1524 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001525 goto out;
1526 }
bellardea2384d2004-08-01 21:59:26 +00001527 }
1528 sector_num += n1;
1529 n -= n1;
1530 buf1 += n1 * 512;
1531 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001532 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +00001533 }
1534 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001535out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001536 qemu_progress_end();
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001537 free_option_parameters(create_options);
1538 free_option_parameters(param);
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001539 qemu_vfree(buf);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001540 if (out_bs) {
1541 bdrv_delete(out_bs);
1542 }
Jes Sorensen31ca34b2010-12-06 15:25:36 +01001543 if (bs) {
1544 for (bs_i = 0; bs_i < bs_n; bs_i++) {
1545 if (bs[bs_i]) {
1546 bdrv_delete(bs[bs_i]);
1547 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001548 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001549 g_free(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001550 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001551 if (ret) {
1552 return 1;
1553 }
bellardea2384d2004-08-01 21:59:26 +00001554 return 0;
1555}
1556
bellard57d1a2b2004-08-03 21:15:11 +00001557
bellardfaea38e2006-08-05 21:31:00 +00001558static void dump_snapshots(BlockDriverState *bs)
1559{
1560 QEMUSnapshotInfo *sn_tab, *sn;
1561 int nb_sns, i;
bellardfaea38e2006-08-05 21:31:00 +00001562
1563 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1564 if (nb_sns <= 0)
1565 return;
1566 printf("Snapshot list:\n");
Wenchao Xia5b917042013-05-25 11:09:45 +08001567 bdrv_snapshot_dump(fprintf, stdout, NULL);
1568 printf("\n");
bellardfaea38e2006-08-05 21:31:00 +00001569 for(i = 0; i < nb_sns; i++) {
1570 sn = &sn_tab[i];
Wenchao Xia5b917042013-05-25 11:09:45 +08001571 bdrv_snapshot_dump(fprintf, stdout, sn);
1572 printf("\n");
bellardfaea38e2006-08-05 21:31:00 +00001573 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001574 g_free(sn_tab);
bellardfaea38e2006-08-05 21:31:00 +00001575}
1576
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001577static void dump_json_image_info_list(ImageInfoList *list)
1578{
1579 Error *errp = NULL;
1580 QString *str;
1581 QmpOutputVisitor *ov = qmp_output_visitor_new();
1582 QObject *obj;
1583 visit_type_ImageInfoList(qmp_output_get_visitor(ov),
1584 &list, NULL, &errp);
1585 obj = qmp_output_get_qobject(ov);
1586 str = qobject_to_json_pretty(obj);
1587 assert(str != NULL);
1588 printf("%s\n", qstring_get_str(str));
1589 qobject_decref(obj);
1590 qmp_output_visitor_cleanup(ov);
1591 QDECREF(str);
1592}
1593
Benoît Canetc054b3f2012-09-05 13:09:02 +02001594static void dump_json_image_info(ImageInfo *info)
1595{
1596 Error *errp = NULL;
1597 QString *str;
1598 QmpOutputVisitor *ov = qmp_output_visitor_new();
1599 QObject *obj;
1600 visit_type_ImageInfo(qmp_output_get_visitor(ov),
1601 &info, NULL, &errp);
1602 obj = qmp_output_get_qobject(ov);
1603 str = qobject_to_json_pretty(obj);
1604 assert(str != NULL);
1605 printf("%s\n", qstring_get_str(str));
1606 qobject_decref(obj);
1607 qmp_output_visitor_cleanup(ov);
1608 QDECREF(str);
1609}
1610
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001611static void dump_human_image_info_list(ImageInfoList *list)
1612{
1613 ImageInfoList *elem;
1614 bool delim = false;
1615
1616 for (elem = list; elem; elem = elem->next) {
1617 if (delim) {
1618 printf("\n");
1619 }
1620 delim = true;
1621
Wenchao Xia5b917042013-05-25 11:09:45 +08001622 bdrv_image_info_dump(fprintf, stdout, elem->value);
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001623 }
1624}
1625
1626static gboolean str_equal_func(gconstpointer a, gconstpointer b)
1627{
1628 return strcmp(a, b) == 0;
1629}
1630
1631/**
1632 * Open an image file chain and return an ImageInfoList
1633 *
1634 * @filename: topmost image filename
1635 * @fmt: topmost image format (may be NULL to autodetect)
1636 * @chain: true - enumerate entire backing file chain
1637 * false - only topmost image file
1638 *
1639 * Returns a list of ImageInfo objects or NULL if there was an error opening an
1640 * image file. If there was an error a message will have been printed to
1641 * stderr.
1642 */
1643static ImageInfoList *collect_image_info_list(const char *filename,
1644 const char *fmt,
1645 bool chain)
1646{
1647 ImageInfoList *head = NULL;
1648 ImageInfoList **last = &head;
1649 GHashTable *filenames;
Wenchao Xia43526ec2013-06-06 12:27:58 +08001650 Error *err = NULL;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001651
1652 filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
1653
1654 while (filename) {
1655 BlockDriverState *bs;
1656 ImageInfo *info;
1657 ImageInfoList *elem;
1658
1659 if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
1660 error_report("Backing file '%s' creates an infinite loop.",
1661 filename);
1662 goto err;
1663 }
1664 g_hash_table_insert(filenames, (gpointer)filename, NULL);
1665
1666 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001667 false, false);
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001668 if (!bs) {
1669 goto err;
1670 }
1671
Wenchao Xia43526ec2013-06-06 12:27:58 +08001672 bdrv_query_image_info(bs, &info, &err);
1673 if (error_is_set(&err)) {
1674 error_report("%s", error_get_pretty(err));
1675 error_free(err);
1676 goto err;
Wenchao Xiafb0ed452013-06-06 12:27:57 +08001677 }
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001678
1679 elem = g_new0(ImageInfoList, 1);
1680 elem->value = info;
1681 *last = elem;
1682 last = &elem->next;
1683
1684 bdrv_delete(bs);
1685
1686 filename = fmt = NULL;
1687 if (chain) {
1688 if (info->has_full_backing_filename) {
1689 filename = info->full_backing_filename;
1690 } else if (info->has_backing_filename) {
1691 filename = info->backing_filename;
1692 }
1693 if (info->has_backing_filename_format) {
1694 fmt = info->backing_filename_format;
1695 }
1696 }
1697 }
1698 g_hash_table_destroy(filenames);
1699 return head;
1700
1701err:
1702 qapi_free_ImageInfoList(head);
1703 g_hash_table_destroy(filenames);
1704 return NULL;
1705}
1706
Benoît Canetc054b3f2012-09-05 13:09:02 +02001707static int img_info(int argc, char **argv)
1708{
1709 int c;
1710 OutputFormat output_format = OFORMAT_HUMAN;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001711 bool chain = false;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001712 const char *filename, *fmt, *output;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001713 ImageInfoList *list;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001714
bellardea2384d2004-08-01 21:59:26 +00001715 fmt = NULL;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001716 output = NULL;
bellardea2384d2004-08-01 21:59:26 +00001717 for(;;) {
Benoît Canetc054b3f2012-09-05 13:09:02 +02001718 int option_index = 0;
1719 static const struct option long_options[] = {
1720 {"help", no_argument, 0, 'h'},
1721 {"format", required_argument, 0, 'f'},
1722 {"output", required_argument, 0, OPTION_OUTPUT},
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001723 {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
Benoît Canetc054b3f2012-09-05 13:09:02 +02001724 {0, 0, 0, 0}
1725 };
1726 c = getopt_long(argc, argv, "f:h",
1727 long_options, &option_index);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001728 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001729 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001730 }
bellardea2384d2004-08-01 21:59:26 +00001731 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001732 case '?':
bellardea2384d2004-08-01 21:59:26 +00001733 case 'h':
1734 help();
1735 break;
1736 case 'f':
1737 fmt = optarg;
1738 break;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001739 case OPTION_OUTPUT:
1740 output = optarg;
1741 break;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001742 case OPTION_BACKING_CHAIN:
1743 chain = true;
1744 break;
bellardea2384d2004-08-01 21:59:26 +00001745 }
1746 }
Kevin Wolffc11eb22013-08-05 10:53:04 +02001747 if (optind != argc - 1) {
bellardea2384d2004-08-01 21:59:26 +00001748 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001749 }
bellardea2384d2004-08-01 21:59:26 +00001750 filename = argv[optind++];
1751
Benoît Canetc054b3f2012-09-05 13:09:02 +02001752 if (output && !strcmp(output, "json")) {
1753 output_format = OFORMAT_JSON;
1754 } else if (output && !strcmp(output, "human")) {
1755 output_format = OFORMAT_HUMAN;
1756 } else if (output) {
1757 error_report("--output must be used with human or json as argument.");
1758 return 1;
1759 }
1760
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001761 list = collect_image_info_list(filename, fmt, chain);
1762 if (!list) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001763 return 1;
1764 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001765
Benoît Canetc054b3f2012-09-05 13:09:02 +02001766 switch (output_format) {
1767 case OFORMAT_HUMAN:
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001768 dump_human_image_info_list(list);
Benoît Canetc054b3f2012-09-05 13:09:02 +02001769 break;
1770 case OFORMAT_JSON:
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001771 if (chain) {
1772 dump_json_image_info_list(list);
1773 } else {
1774 dump_json_image_info(list->value);
1775 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001776 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001777 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001778
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001779 qapi_free_ImageInfoList(list);
bellardea2384d2004-08-01 21:59:26 +00001780 return 0;
1781}
1782
aliguorif7b4a942009-01-07 17:40:15 +00001783#define SNAPSHOT_LIST 1
1784#define SNAPSHOT_CREATE 2
1785#define SNAPSHOT_APPLY 3
1786#define SNAPSHOT_DELETE 4
1787
Stuart Brady153859b2009-06-07 00:42:17 +01001788static int img_snapshot(int argc, char **argv)
aliguorif7b4a942009-01-07 17:40:15 +00001789{
1790 BlockDriverState *bs;
1791 QEMUSnapshotInfo sn;
1792 char *filename, *snapshot_name = NULL;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001793 int c, ret = 0, bdrv_oflags;
aliguorif7b4a942009-01-07 17:40:15 +00001794 int action = 0;
1795 qemu_timeval tv;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001796 bool quiet = false;
aliguorif7b4a942009-01-07 17:40:15 +00001797
Kevin Wolf710da702011-01-10 12:33:02 +01001798 bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
aliguorif7b4a942009-01-07 17:40:15 +00001799 /* Parse commandline parameters */
1800 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001801 c = getopt(argc, argv, "la:c:d:hq");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001802 if (c == -1) {
aliguorif7b4a942009-01-07 17:40:15 +00001803 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001804 }
aliguorif7b4a942009-01-07 17:40:15 +00001805 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001806 case '?':
aliguorif7b4a942009-01-07 17:40:15 +00001807 case 'h':
1808 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001809 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001810 case 'l':
1811 if (action) {
1812 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001813 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001814 }
1815 action = SNAPSHOT_LIST;
Naphtali Spreif5edb012010-01-17 16:48:13 +02001816 bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
aliguorif7b4a942009-01-07 17:40:15 +00001817 break;
1818 case 'a':
1819 if (action) {
1820 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001821 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001822 }
1823 action = SNAPSHOT_APPLY;
1824 snapshot_name = optarg;
1825 break;
1826 case 'c':
1827 if (action) {
1828 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001829 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001830 }
1831 action = SNAPSHOT_CREATE;
1832 snapshot_name = optarg;
1833 break;
1834 case 'd':
1835 if (action) {
1836 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001837 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001838 }
1839 action = SNAPSHOT_DELETE;
1840 snapshot_name = optarg;
1841 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001842 case 'q':
1843 quiet = true;
1844 break;
aliguorif7b4a942009-01-07 17:40:15 +00001845 }
1846 }
1847
Kevin Wolffc11eb22013-08-05 10:53:04 +02001848 if (optind != argc - 1) {
aliguorif7b4a942009-01-07 17:40:15 +00001849 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001850 }
aliguorif7b4a942009-01-07 17:40:15 +00001851 filename = argv[optind++];
1852
1853 /* Open the image */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001854 bs = bdrv_new_open(filename, NULL, bdrv_oflags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001855 if (!bs) {
1856 return 1;
1857 }
aliguorif7b4a942009-01-07 17:40:15 +00001858
1859 /* Perform the requested action */
1860 switch(action) {
1861 case SNAPSHOT_LIST:
1862 dump_snapshots(bs);
1863 break;
1864
1865 case SNAPSHOT_CREATE:
1866 memset(&sn, 0, sizeof(sn));
1867 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1868
1869 qemu_gettimeofday(&tv);
1870 sn.date_sec = tv.tv_sec;
1871 sn.date_nsec = tv.tv_usec * 1000;
1872
1873 ret = bdrv_snapshot_create(bs, &sn);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001874 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001875 error_report("Could not create snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001876 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001877 }
aliguorif7b4a942009-01-07 17:40:15 +00001878 break;
1879
1880 case SNAPSHOT_APPLY:
1881 ret = bdrv_snapshot_goto(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001882 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001883 error_report("Could not apply snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001884 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001885 }
aliguorif7b4a942009-01-07 17:40:15 +00001886 break;
1887
1888 case SNAPSHOT_DELETE:
1889 ret = bdrv_snapshot_delete(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001890 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001891 error_report("Could not delete snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001892 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001893 }
aliguorif7b4a942009-01-07 17:40:15 +00001894 break;
1895 }
1896
1897 /* Cleanup */
1898 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001899 if (ret) {
1900 return 1;
1901 }
Stuart Brady153859b2009-06-07 00:42:17 +01001902 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001903}
1904
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001905static int img_rebase(int argc, char **argv)
1906{
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001907 BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001908 BlockDriver *old_backing_drv, *new_backing_drv;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001909 char *filename;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001910 const char *fmt, *cache, *out_basefmt, *out_baseimg;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001911 int c, flags, ret;
1912 int unsafe = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001913 int progress = 0;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001914 bool quiet = false;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001915
1916 /* Parse commandline parameters */
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001917 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001918 cache = BDRV_DEFAULT_CACHE;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001919 out_baseimg = NULL;
1920 out_basefmt = NULL;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001921 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001922 c = getopt(argc, argv, "uhf:F:b:pt:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001923 if (c == -1) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001924 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001925 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001926 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001927 case '?':
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001928 case 'h':
1929 help();
1930 return 0;
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001931 case 'f':
1932 fmt = optarg;
1933 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001934 case 'F':
1935 out_basefmt = optarg;
1936 break;
1937 case 'b':
1938 out_baseimg = optarg;
1939 break;
1940 case 'u':
1941 unsafe = 1;
1942 break;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001943 case 'p':
1944 progress = 1;
1945 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001946 case 't':
1947 cache = optarg;
1948 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001949 case 'q':
1950 quiet = true;
1951 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001952 }
1953 }
1954
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001955 if (quiet) {
1956 progress = 0;
1957 }
1958
Kevin Wolffc11eb22013-08-05 10:53:04 +02001959 if ((optind != argc - 1) || (!unsafe && !out_baseimg)) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001960 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001961 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001962 filename = argv[optind++];
1963
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001964 qemu_progress_init(progress, 2.0);
1965 qemu_progress_print(0, 100);
1966
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001967 flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +01001968 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001969 if (ret < 0) {
1970 error_report("Invalid cache option: %s", cache);
1971 return -1;
1972 }
1973
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001974 /*
1975 * Open the images.
1976 *
1977 * Ignore the old backing file for unsafe rebase in case we want to correct
1978 * the reference to a renamed or moved backing file.
1979 */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001980 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001981 if (!bs) {
1982 return 1;
1983 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001984
1985 /* Find the right drivers for the backing files */
1986 old_backing_drv = NULL;
1987 new_backing_drv = NULL;
1988
1989 if (!unsafe && bs->backing_format[0] != '\0') {
1990 old_backing_drv = bdrv_find_format(bs->backing_format);
1991 if (old_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001992 error_report("Invalid format name: '%s'", bs->backing_format);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001993 ret = -1;
1994 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001995 }
1996 }
1997
1998 if (out_basefmt != NULL) {
1999 new_backing_drv = bdrv_find_format(out_basefmt);
2000 if (new_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002001 error_report("Invalid format name: '%s'", out_basefmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002002 ret = -1;
2003 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002004 }
2005 }
2006
2007 /* For safe rebasing we need to compare old and new backing file */
2008 if (unsafe) {
2009 /* Make the compiler happy */
2010 bs_old_backing = NULL;
2011 bs_new_backing = NULL;
2012 } else {
2013 char backing_name[1024];
2014
2015 bs_old_backing = bdrv_new("old_backing");
2016 bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
Kevin Wolfde9c0ce2013-03-15 10:35:02 +01002017 ret = bdrv_open(bs_old_backing, backing_name, NULL, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002018 old_backing_drv);
2019 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002020 error_report("Could not open old backing file '%s'", backing_name);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002021 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002022 }
Alex Bligha6166732012-10-16 13:46:18 +01002023 if (out_baseimg[0]) {
2024 bs_new_backing = bdrv_new("new_backing");
Kevin Wolfde9c0ce2013-03-15 10:35:02 +01002025 ret = bdrv_open(bs_new_backing, out_baseimg, NULL, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002026 new_backing_drv);
Alex Bligha6166732012-10-16 13:46:18 +01002027 if (ret) {
2028 error_report("Could not open new backing file '%s'",
2029 out_baseimg);
2030 goto out;
2031 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002032 }
2033 }
2034
2035 /*
2036 * Check each unallocated cluster in the COW file. If it is unallocated,
2037 * accesses go to the backing file. We must therefore compare this cluster
2038 * in the old and new backing file, and if they differ we need to copy it
2039 * from the old backing file into the COW file.
2040 *
2041 * If qemu-img crashes during this step, no harm is done. The content of
2042 * the image is the same as the original one at any time.
2043 */
2044 if (!unsafe) {
2045 uint64_t num_sectors;
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002046 uint64_t old_backing_num_sectors;
Alex Bligha6166732012-10-16 13:46:18 +01002047 uint64_t new_backing_num_sectors = 0;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002048 uint64_t sector;
Kevin Wolfcc60e322010-04-29 14:47:48 +02002049 int n;
TeLeMand6771bf2010-02-08 16:20:00 +08002050 uint8_t * buf_old;
2051 uint8_t * buf_new;
Kevin Wolf1f710492012-10-12 14:29:18 +02002052 float local_progress = 0;
TeLeMand6771bf2010-02-08 16:20:00 +08002053
Kevin Wolfbb1c0592011-08-08 14:09:12 +02002054 buf_old = qemu_blockalign(bs, IO_BUF_SIZE);
2055 buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002056
2057 bdrv_get_geometry(bs, &num_sectors);
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002058 bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
Alex Bligha6166732012-10-16 13:46:18 +01002059 if (bs_new_backing) {
2060 bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
2061 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002062
Kevin Wolf1f710492012-10-12 14:29:18 +02002063 if (num_sectors != 0) {
2064 local_progress = (float)100 /
2065 (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
2066 }
2067
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002068 for (sector = 0; sector < num_sectors; sector += n) {
2069
2070 /* How many sectors can we handle with the next read? */
2071 if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
2072 n = (IO_BUF_SIZE / 512);
2073 } else {
2074 n = num_sectors - sector;
2075 }
2076
2077 /* If the cluster is allocated, we don't need to take action */
Kevin Wolfcc60e322010-04-29 14:47:48 +02002078 ret = bdrv_is_allocated(bs, sector, n, &n);
2079 if (ret) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002080 continue;
2081 }
2082
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002083 /*
2084 * Read old and new backing file and take into consideration that
2085 * backing files may be smaller than the COW image.
2086 */
2087 if (sector >= old_backing_num_sectors) {
2088 memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
2089 } else {
2090 if (sector + n > old_backing_num_sectors) {
2091 n = old_backing_num_sectors - sector;
2092 }
2093
2094 ret = bdrv_read(bs_old_backing, sector, buf_old, n);
2095 if (ret < 0) {
2096 error_report("error while reading from old backing file");
2097 goto out;
2098 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002099 }
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002100
Alex Bligha6166732012-10-16 13:46:18 +01002101 if (sector >= new_backing_num_sectors || !bs_new_backing) {
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002102 memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
2103 } else {
2104 if (sector + n > new_backing_num_sectors) {
2105 n = new_backing_num_sectors - sector;
2106 }
2107
2108 ret = bdrv_read(bs_new_backing, sector, buf_new, n);
2109 if (ret < 0) {
2110 error_report("error while reading from new backing file");
2111 goto out;
2112 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002113 }
2114
2115 /* If they differ, we need to write to the COW file */
2116 uint64_t written = 0;
2117
2118 while (written < n) {
2119 int pnum;
2120
2121 if (compare_sectors(buf_old + written * 512,
Kevin Wolf60b1bd42010-02-17 12:32:59 +01002122 buf_new + written * 512, n - written, &pnum))
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002123 {
2124 ret = bdrv_write(bs, sector + written,
2125 buf_old + written * 512, pnum);
2126 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002127 error_report("Error while writing to COW image: %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002128 strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002129 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002130 }
2131 }
2132
2133 written += pnum;
2134 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002135 qemu_progress_print(local_progress, 100);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002136 }
TeLeMand6771bf2010-02-08 16:20:00 +08002137
Kevin Wolfbb1c0592011-08-08 14:09:12 +02002138 qemu_vfree(buf_old);
2139 qemu_vfree(buf_new);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002140 }
2141
2142 /*
2143 * Change the backing file. All clusters that are different from the old
2144 * backing file are overwritten in the COW file now, so the visible content
2145 * doesn't change when we switch the backing file.
2146 */
Alex Bligha6166732012-10-16 13:46:18 +01002147 if (out_baseimg && *out_baseimg) {
2148 ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
2149 } else {
2150 ret = bdrv_change_backing_file(bs, NULL, NULL);
2151 }
2152
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002153 if (ret == -ENOSPC) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002154 error_report("Could not change the backing file to '%s': No "
2155 "space left in the file header", out_baseimg);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002156 } else if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002157 error_report("Could not change the backing file to '%s': %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002158 out_baseimg, strerror(-ret));
2159 }
2160
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002161 qemu_progress_print(100, 0);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002162 /*
2163 * TODO At this point it is possible to check if any clusters that are
2164 * allocated in the COW file are the same in the backing file. If so, they
2165 * could be dropped from the COW file. Don't do this before switching the
2166 * backing file, in case of a crash this would lead to corruption.
2167 */
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002168out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002169 qemu_progress_end();
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002170 /* Cleanup */
2171 if (!unsafe) {
Kevin Wolfeb863ad2011-03-31 12:39:51 +02002172 if (bs_old_backing != NULL) {
2173 bdrv_delete(bs_old_backing);
2174 }
2175 if (bs_new_backing != NULL) {
2176 bdrv_delete(bs_new_backing);
2177 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002178 }
2179
2180 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002181 if (ret) {
2182 return 1;
2183 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002184 return 0;
2185}
2186
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002187static int img_resize(int argc, char **argv)
2188{
2189 int c, ret, relative;
2190 const char *filename, *fmt, *size;
2191 int64_t n, total_size;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002192 bool quiet = false;
Jes Sorensen2a819982010-12-06 17:08:31 +01002193 BlockDriverState *bs = NULL;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002194 QemuOpts *param;
2195 static QemuOptsList resize_options = {
2196 .name = "resize_options",
2197 .head = QTAILQ_HEAD_INITIALIZER(resize_options.head),
2198 .desc = {
2199 {
2200 .name = BLOCK_OPT_SIZE,
2201 .type = QEMU_OPT_SIZE,
2202 .help = "Virtual disk size"
2203 }, {
2204 /* end of list */
2205 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002206 },
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002207 };
2208
Kevin Wolfe80fec72011-04-29 10:58:12 +02002209 /* Remove size from argv manually so that negative numbers are not treated
2210 * as options by getopt. */
2211 if (argc < 3) {
2212 help();
2213 return 1;
2214 }
2215
2216 size = argv[--argc];
2217
2218 /* Parse getopt arguments */
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002219 fmt = NULL;
2220 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002221 c = getopt(argc, argv, "f:hq");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002222 if (c == -1) {
2223 break;
2224 }
2225 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01002226 case '?':
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002227 case 'h':
2228 help();
2229 break;
2230 case 'f':
2231 fmt = optarg;
2232 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002233 case 'q':
2234 quiet = true;
2235 break;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002236 }
2237 }
Kevin Wolffc11eb22013-08-05 10:53:04 +02002238 if (optind != argc - 1) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002239 help();
2240 }
2241 filename = argv[optind++];
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002242
2243 /* Choose grow, shrink, or absolute resize mode */
2244 switch (size[0]) {
2245 case '+':
2246 relative = 1;
2247 size++;
2248 break;
2249 case '-':
2250 relative = -1;
2251 size++;
2252 break;
2253 default:
2254 relative = 0;
2255 break;
2256 }
2257
2258 /* Parse size */
Dong Xu Wange478b442012-12-06 14:47:22 +08002259 param = qemu_opts_create_nofail(&resize_options);
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002260 if (qemu_opt_set(param, BLOCK_OPT_SIZE, size)) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002261 /* Error message already printed when size parsing fails */
Jes Sorensen2a819982010-12-06 17:08:31 +01002262 ret = -1;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002263 qemu_opts_del(param);
Jes Sorensen2a819982010-12-06 17:08:31 +01002264 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002265 }
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002266 n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
2267 qemu_opts_del(param);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002268
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002269 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002270 if (!bs) {
Jes Sorensen2a819982010-12-06 17:08:31 +01002271 ret = -1;
2272 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002273 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002274
2275 if (relative) {
2276 total_size = bdrv_getlength(bs) + n * relative;
2277 } else {
2278 total_size = n;
2279 }
2280 if (total_size <= 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002281 error_report("New image size must be positive");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002282 ret = -1;
2283 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002284 }
2285
2286 ret = bdrv_truncate(bs, total_size);
2287 switch (ret) {
2288 case 0:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002289 qprintf(quiet, "Image resized.\n");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002290 break;
2291 case -ENOTSUP:
Kevin Wolf259b2172012-03-06 12:44:45 +01002292 error_report("This image does not support resize");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002293 break;
2294 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +01002295 error_report("Image is read-only");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002296 break;
2297 default:
Jes Sorensen15654a62010-12-16 14:31:53 +01002298 error_report("Error resizing image (%d)", -ret);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002299 break;
2300 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002301out:
Jes Sorensen2a819982010-12-06 17:08:31 +01002302 if (bs) {
2303 bdrv_delete(bs);
2304 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002305 if (ret) {
2306 return 1;
2307 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002308 return 0;
2309}
2310
Anthony Liguoric227f092009-10-01 16:12:16 -05002311static const img_cmd_t img_cmds[] = {
Stuart Brady153859b2009-06-07 00:42:17 +01002312#define DEF(option, callback, arg_string) \
2313 { option, callback },
2314#include "qemu-img-cmds.h"
2315#undef DEF
2316#undef GEN_DOCS
2317 { NULL, NULL, },
2318};
2319
bellardea2384d2004-08-01 21:59:26 +00002320int main(int argc, char **argv)
2321{
Anthony Liguoric227f092009-10-01 16:12:16 -05002322 const img_cmd_t *cmd;
Stuart Brady153859b2009-06-07 00:42:17 +01002323 const char *cmdname;
bellardea2384d2004-08-01 21:59:26 +00002324
Kevin Wolf53f76e52010-12-16 15:10:32 +01002325 error_set_progname(argv[0]);
2326
Paolo Bonzini2592c592012-11-03 18:10:17 +01002327 qemu_init_main_loop();
bellardea2384d2004-08-01 21:59:26 +00002328 bdrv_init();
2329 if (argc < 2)
2330 help();
Stuart Brady153859b2009-06-07 00:42:17 +01002331 cmdname = argv[1];
aurel328f9b1572009-02-09 18:14:31 +00002332 argc--; argv++;
Stuart Brady153859b2009-06-07 00:42:17 +01002333
2334 /* find the command */
2335 for(cmd = img_cmds; cmd->name != NULL; cmd++) {
2336 if (!strcmp(cmdname, cmd->name)) {
2337 return cmd->handler(argc, argv);
2338 }
bellardea2384d2004-08-01 21:59:26 +00002339 }
Stuart Brady153859b2009-06-07 00:42:17 +01002340
2341 /* not found */
2342 help();
bellardea2384d2004-08-01 21:59:26 +00002343 return 0;
2344}