blob: 31627b0da82ff122313efc069f432e0a04efc9be [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"
Benoît Canetc054b3f2012-09-05 13:09:02 +020033#include <getopt.h>
aliguori9230eaf2009-03-28 17:55:19 +000034#include <stdio.h>
Miroslav Rezaninaf382d432013-02-13 09:09:40 +010035#include <stdarg.h>
bellardea2384d2004-08-01 21:59:26 +000036
bellarde8445332006-06-14 15:32:10 +000037#ifdef _WIN32
38#include <windows.h>
39#endif
40
Anthony Liguoric227f092009-10-01 16:12:16 -050041typedef struct img_cmd_t {
Stuart Brady153859b2009-06-07 00:42:17 +010042 const char *name;
43 int (*handler)(int argc, char **argv);
Anthony Liguoric227f092009-10-01 16:12:16 -050044} img_cmd_t;
Stuart Brady153859b2009-06-07 00:42:17 +010045
Federico Simoncelli8599ea42013-01-28 06:59:47 -050046enum {
47 OPTION_OUTPUT = 256,
48 OPTION_BACKING_CHAIN = 257,
49};
50
51typedef enum OutputFormat {
52 OFORMAT_JSON,
53 OFORMAT_HUMAN,
54} OutputFormat;
55
aurel32137519c2008-11-30 19:12:49 +000056/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
Stefan Hajnocziadfe0782010-04-13 10:29:35 +010057#define BDRV_O_FLAGS BDRV_O_CACHE_WB
Federico Simoncelli661a0f72011-06-20 12:48:19 -040058#define BDRV_DEFAULT_CACHE "writeback"
aurel32137519c2008-11-30 19:12:49 +000059
bellardea2384d2004-08-01 21:59:26 +000060static void format_print(void *opaque, const char *name)
61{
62 printf(" %s", name);
63}
64
blueswir1d2c639d2009-01-24 18:19:25 +000065/* Please keep in synch with qemu-img.texi */
pbrook3f379ab2007-11-11 03:33:13 +000066static void help(void)
bellardea2384d2004-08-01 21:59:26 +000067{
Paolo Bonzinie00291c2010-02-04 16:49:56 +010068 const char *help_msg =
69 "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
malc3f020d72010-02-08 12:04:56 +030070 "usage: qemu-img command [command options]\n"
71 "QEMU disk image utility\n"
72 "\n"
73 "Command syntax:\n"
Stuart Brady153859b2009-06-07 00:42:17 +010074#define DEF(option, callback, arg_string) \
75 " " arg_string "\n"
76#include "qemu-img-cmds.h"
77#undef DEF
78#undef GEN_DOCS
malc3f020d72010-02-08 12:04:56 +030079 "\n"
80 "Command parameters:\n"
81 " 'filename' is a disk image filename\n"
82 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
Federico Simoncelli661a0f72011-06-20 12:48:19 -040083 " 'cache' is the cache mode used to write the output disk image, the valid\n"
Liu Yuan80ccf932012-04-20 17:10:56 +080084 " options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
85 " 'directsync' and 'unsafe' (default for convert)\n"
malc3f020d72010-02-08 12:04:56 +030086 " 'size' is the disk image size in bytes. Optional suffixes\n"
87 " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
88 " and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
89 " 'output_filename' is the destination disk image filename\n"
90 " 'output_fmt' is the destination format\n"
91 " 'options' is a comma separated list of format specific options in a\n"
92 " name=value format. Use -o ? for an overview of the options supported by the\n"
93 " used format\n"
94 " '-c' indicates that target image must be compressed (qcow format only)\n"
95 " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
96 " match exactly. The image doesn't need a working backing file before\n"
97 " rebasing in this case (useful for renaming the backing file)\n"
98 " '-h' with or without a command shows this help and lists the supported formats\n"
Jes Sorensen6b837bc2011-03-30 14:16:25 +020099 " '-p' show progress of command (only certain commands)\n"
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100100 " '-q' use Quiet mode - do not print any output (except errors)\n"
Kevin Wolfa22f1232011-08-26 15:27:13 +0200101 " '-S' indicates the consecutive number of bytes that must contain only zeros\n"
102 " for qemu-img to create a sparse image during conversion\n"
Benoît Canetc054b3f2012-09-05 13:09:02 +0200103 " '--output' takes the format in which the output must be done (human or json)\n"
malc3f020d72010-02-08 12:04:56 +0300104 "\n"
Kevin Wolf4534ff52012-05-11 16:07:02 +0200105 "Parameters to check subcommand:\n"
106 " '-r' tries to repair any inconsistencies that are found during the check.\n"
107 " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
108 " kinds of errors, with a higher risk of choosing the wrong fix or\n"
Stefan Weil0546b8c2012-08-10 22:03:25 +0200109 " hiding corruption that has already occurred.\n"
Kevin Wolf4534ff52012-05-11 16:07:02 +0200110 "\n"
malc3f020d72010-02-08 12:04:56 +0300111 "Parameters to snapshot subcommand:\n"
112 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
113 " '-a' applies a snapshot (revert disk to saved state)\n"
114 " '-c' creates a snapshot\n"
115 " '-d' deletes a snapshot\n"
Miroslav Rezaninad14ed182013-02-13 09:09:41 +0100116 " '-l' lists all snapshots in the given image\n"
117 "\n"
118 "Parameters to compare subcommand:\n"
119 " '-f' first image format\n"
120 " '-F' second image format\n"
121 " '-s' run in Strict mode - fail on different image size or sector allocation\n";
Paolo Bonzinie00291c2010-02-04 16:49:56 +0100122
123 printf("%s\nSupported formats:", help_msg);
bellardea2384d2004-08-01 21:59:26 +0000124 bdrv_iterate_format(format_print, NULL);
125 printf("\n");
126 exit(1);
127}
128
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100129static int qprintf(bool quiet, const char *fmt, ...)
130{
131 int ret = 0;
132 if (!quiet) {
133 va_list args;
134 va_start(args, fmt);
135 ret = vprintf(fmt, args);
136 va_end(args);
137 }
138 return ret;
139}
140
bellardea2384d2004-08-01 21:59:26 +0000141#if defined(WIN32)
142/* XXX: put correct support for win32 */
143static int read_password(char *buf, int buf_size)
144{
145 int c, i;
146 printf("Password: ");
147 fflush(stdout);
148 i = 0;
149 for(;;) {
150 c = getchar();
151 if (c == '\n')
152 break;
153 if (i < (buf_size - 1))
154 buf[i++] = c;
155 }
156 buf[i] = '\0';
157 return 0;
158}
159
160#else
161
162#include <termios.h>
163
164static struct termios oldtty;
165
166static void term_exit(void)
167{
168 tcsetattr (0, TCSANOW, &oldtty);
169}
170
171static void term_init(void)
172{
173 struct termios tty;
174
175 tcgetattr (0, &tty);
176 oldtty = tty;
177
178 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
179 |INLCR|IGNCR|ICRNL|IXON);
180 tty.c_oflag |= OPOST;
181 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
182 tty.c_cflag &= ~(CSIZE|PARENB);
183 tty.c_cflag |= CS8;
184 tty.c_cc[VMIN] = 1;
185 tty.c_cc[VTIME] = 0;
ths3b46e622007-09-17 08:09:54 +0000186
bellardea2384d2004-08-01 21:59:26 +0000187 tcsetattr (0, TCSANOW, &tty);
188
189 atexit(term_exit);
190}
191
pbrook3f379ab2007-11-11 03:33:13 +0000192static int read_password(char *buf, int buf_size)
bellardea2384d2004-08-01 21:59:26 +0000193{
194 uint8_t ch;
195 int i, ret;
196
197 printf("password: ");
198 fflush(stdout);
199 term_init();
200 i = 0;
201 for(;;) {
202 ret = read(0, &ch, 1);
203 if (ret == -1) {
204 if (errno == EAGAIN || errno == EINTR) {
205 continue;
206 } else {
207 ret = -1;
208 break;
209 }
210 } else if (ret == 0) {
211 ret = -1;
212 break;
213 } else {
214 if (ch == '\r') {
215 ret = 0;
216 break;
217 }
218 if (i < (buf_size - 1))
219 buf[i++] = ch;
220 }
221 }
222 term_exit();
223 buf[i] = '\0';
224 printf("\n");
225 return ret;
226}
227#endif
228
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100229static int print_block_option_help(const char *filename, const char *fmt)
230{
231 BlockDriver *drv, *proto_drv;
232 QEMUOptionParameter *create_options = NULL;
233
234 /* Find driver and parse its options */
235 drv = bdrv_find_format(fmt);
236 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100237 error_report("Unknown file format '%s'", fmt);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100238 return 1;
239 }
240
241 proto_drv = bdrv_find_protocol(filename);
242 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100243 error_report("Unknown protocol '%s'", filename);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100244 return 1;
245 }
246
247 create_options = append_option_parameters(create_options,
248 drv->create_options);
249 create_options = append_option_parameters(create_options,
250 proto_drv->create_options);
251 print_option_help(create_options);
252 free_option_parameters(create_options);
253 return 0;
254}
255
bellard75c23802004-08-27 21:28:58 +0000256static BlockDriverState *bdrv_new_open(const char *filename,
Sheng Yang9bc378c2010-01-29 10:15:06 +0800257 const char *fmt,
Daniel P. Berrangef0536bb2012-09-10 12:11:31 +0100258 int flags,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100259 bool require_io,
260 bool quiet)
bellard75c23802004-08-27 21:28:58 +0000261{
262 BlockDriverState *bs;
263 BlockDriver *drv;
264 char password[256];
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100265 int ret;
bellard75c23802004-08-27 21:28:58 +0000266
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100267 bs = bdrv_new("image");
Kevin Wolfad717132010-12-16 15:37:41 +0100268
bellard75c23802004-08-27 21:28:58 +0000269 if (fmt) {
270 drv = bdrv_find_format(fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900271 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100272 error_report("Unknown file format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900273 goto fail;
274 }
bellard75c23802004-08-27 21:28:58 +0000275 } else {
276 drv = NULL;
277 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100278
Kevin Wolfde9c0ce2013-03-15 10:35:02 +0100279 ret = bdrv_open(bs, filename, NULL, flags, drv);
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100280 if (ret < 0) {
281 error_report("Could not open '%s': %s", filename, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900282 goto fail;
bellard75c23802004-08-27 21:28:58 +0000283 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100284
Daniel P. Berrangef0536bb2012-09-10 12:11:31 +0100285 if (bdrv_is_encrypted(bs) && require_io) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100286 qprintf(quiet, "Disk image '%s' is encrypted.\n", filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900287 if (read_password(password, sizeof(password)) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100288 error_report("No password given");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900289 goto fail;
290 }
291 if (bdrv_set_key(bs, password) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100292 error_report("invalid password");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900293 goto fail;
294 }
bellard75c23802004-08-27 21:28:58 +0000295 }
296 return bs;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900297fail:
298 if (bs) {
299 bdrv_delete(bs);
300 }
301 return NULL;
bellard75c23802004-08-27 21:28:58 +0000302}
303
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900304static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
Jes Sorenseneec77d92010-12-07 17:44:34 +0100305 const char *base_filename,
306 const char *base_fmt)
Kevin Wolfefa84d42009-05-18 16:42:12 +0200307{
Kevin Wolfefa84d42009-05-18 16:42:12 +0200308 if (base_filename) {
309 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100310 error_report("Backing file not supported for file format '%s'",
311 fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900312 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200313 }
314 }
315 if (base_fmt) {
316 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100317 error_report("Backing file format not supported for file "
318 "format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900319 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200320 }
321 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900322 return 0;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200323}
324
bellardea2384d2004-08-01 21:59:26 +0000325static int img_create(int argc, char **argv)
326{
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200327 int c;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100328 uint64_t img_size = -1;
bellardea2384d2004-08-01 21:59:26 +0000329 const char *fmt = "raw";
aliguori9230eaf2009-03-28 17:55:19 +0000330 const char *base_fmt = NULL;
bellardea2384d2004-08-01 21:59:26 +0000331 const char *filename;
332 const char *base_filename = NULL;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200333 char *options = NULL;
Luiz Capitulino9b375252012-11-30 10:52:05 -0200334 Error *local_err = NULL;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100335 bool quiet = false;
ths3b46e622007-09-17 08:09:54 +0000336
bellardea2384d2004-08-01 21:59:26 +0000337 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100338 c = getopt(argc, argv, "F:b:f:he6o:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100339 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000340 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100341 }
bellardea2384d2004-08-01 21:59:26 +0000342 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100343 case '?':
bellardea2384d2004-08-01 21:59:26 +0000344 case 'h':
345 help();
346 break;
aliguori9230eaf2009-03-28 17:55:19 +0000347 case 'F':
348 base_fmt = optarg;
349 break;
bellardea2384d2004-08-01 21:59:26 +0000350 case 'b':
351 base_filename = optarg;
352 break;
353 case 'f':
354 fmt = optarg;
355 break;
356 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200357 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100358 "encryption\' instead!");
359 return 1;
thsd8871c52007-10-24 16:11:42 +0000360 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200361 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100362 "compat6\' instead!");
363 return 1;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200364 case 'o':
365 options = optarg;
366 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100367 case 'q':
368 quiet = true;
369 break;
bellardea2384d2004-08-01 21:59:26 +0000370 }
371 }
aliguori9230eaf2009-03-28 17:55:19 +0000372
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900373 /* Get the filename */
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100374 if (optind >= argc) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900375 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100376 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900377 filename = argv[optind++];
378
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100379 /* Get image size, if specified */
380 if (optind < argc) {
Jes Sorensen70b4f4b2011-01-05 11:41:02 +0100381 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +0100382 char *end;
383 sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
384 if (sval < 0 || *end) {
liguang79443392012-12-17 09:49:23 +0800385 if (sval == -ERANGE) {
386 error_report("Image size must be less than 8 EiB!");
387 } else {
388 error_report("Invalid image size specified! You may use k, M, "
389 "G or T suffixes for ");
390 error_report("kilobytes, megabytes, gigabytes and terabytes.");
391 }
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200392 return 1;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100393 }
394 img_size = (uint64_t)sval;
395 }
396
Peter Maydellc8057f92012-08-02 13:45:54 +0100397 if (options && is_help_option(options)) {
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200398 return print_block_option_help(filename, fmt);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100399 }
400
Luiz Capitulino9b375252012-11-30 10:52:05 -0200401 bdrv_img_create(filename, fmt, base_filename, base_fmt,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100402 options, img_size, BDRV_O_FLAGS, &local_err, quiet);
Luiz Capitulino9b375252012-11-30 10:52:05 -0200403 if (error_is_set(&local_err)) {
404 error_report("%s", error_get_pretty(local_err));
405 error_free(local_err);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900406 return 1;
407 }
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200408
bellardea2384d2004-08-01 21:59:26 +0000409 return 0;
410}
411
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100412static void dump_json_image_check(ImageCheck *check, bool quiet)
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500413{
414 Error *errp = NULL;
415 QString *str;
416 QmpOutputVisitor *ov = qmp_output_visitor_new();
417 QObject *obj;
418 visit_type_ImageCheck(qmp_output_get_visitor(ov),
419 &check, NULL, &errp);
420 obj = qmp_output_get_qobject(ov);
421 str = qobject_to_json_pretty(obj);
422 assert(str != NULL);
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100423 qprintf(quiet, "%s\n", qstring_get_str(str));
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500424 qobject_decref(obj);
425 qmp_output_visitor_cleanup(ov);
426 QDECREF(str);
427}
428
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100429static void dump_human_image_check(ImageCheck *check, bool quiet)
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500430{
431 if (!(check->corruptions || check->leaks || check->check_errors)) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100432 qprintf(quiet, "No errors were found on the image.\n");
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500433 } else {
434 if (check->corruptions) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100435 qprintf(quiet, "\n%" PRId64 " errors were found on the image.\n"
436 "Data may be corrupted, or further writes to the image "
437 "may corrupt it.\n",
438 check->corruptions);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500439 }
440
441 if (check->leaks) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100442 qprintf(quiet,
443 "\n%" PRId64 " leaked clusters were found on the image.\n"
444 "This means waste of disk space, but no harm to data.\n",
445 check->leaks);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500446 }
447
448 if (check->check_errors) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100449 qprintf(quiet,
450 "\n%" PRId64
451 " internal errors have occurred during the check.\n",
452 check->check_errors);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500453 }
454 }
455
456 if (check->total_clusters != 0 && check->allocated_clusters != 0) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100457 qprintf(quiet, "%" PRId64 "/%" PRId64 " = %0.2f%% allocated, "
458 "%0.2f%% fragmented, %0.2f%% compressed clusters\n",
459 check->allocated_clusters, check->total_clusters,
460 check->allocated_clusters * 100.0 / check->total_clusters,
461 check->fragmented_clusters * 100.0 / check->allocated_clusters,
462 check->compressed_clusters * 100.0 /
463 check->allocated_clusters);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500464 }
465
466 if (check->image_end_offset) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100467 qprintf(quiet,
468 "Image end offset: %" PRId64 "\n", check->image_end_offset);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500469 }
470}
471
472static int collect_image_check(BlockDriverState *bs,
473 ImageCheck *check,
474 const char *filename,
475 const char *fmt,
476 int fix)
477{
478 int ret;
479 BdrvCheckResult result;
480
481 ret = bdrv_check(bs, &result, fix);
482 if (ret < 0) {
483 return ret;
484 }
485
486 check->filename = g_strdup(filename);
487 check->format = g_strdup(bdrv_get_format_name(bs));
488 check->check_errors = result.check_errors;
489 check->corruptions = result.corruptions;
490 check->has_corruptions = result.corruptions != 0;
491 check->leaks = result.leaks;
492 check->has_leaks = result.leaks != 0;
493 check->corruptions_fixed = result.corruptions_fixed;
494 check->has_corruptions_fixed = result.corruptions != 0;
495 check->leaks_fixed = result.leaks_fixed;
496 check->has_leaks_fixed = result.leaks != 0;
497 check->image_end_offset = result.image_end_offset;
498 check->has_image_end_offset = result.image_end_offset != 0;
499 check->total_clusters = result.bfi.total_clusters;
500 check->has_total_clusters = result.bfi.total_clusters != 0;
501 check->allocated_clusters = result.bfi.allocated_clusters;
502 check->has_allocated_clusters = result.bfi.allocated_clusters != 0;
503 check->fragmented_clusters = result.bfi.fragmented_clusters;
504 check->has_fragmented_clusters = result.bfi.fragmented_clusters != 0;
Stefan Hajnoczie6439d72013-02-07 17:15:04 +0100505 check->compressed_clusters = result.bfi.compressed_clusters;
506 check->has_compressed_clusters = result.bfi.compressed_clusters != 0;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500507
508 return 0;
509}
510
Kevin Wolfe076f332010-06-29 11:43:13 +0200511/*
512 * Checks an image for consistency. Exit codes:
513 *
514 * 0 - Check completed, image is good
515 * 1 - Check not completed because of internal errors
516 * 2 - Check completed, image is corrupted
517 * 3 - Check completed, image has leaked clusters, but is good otherwise
518 */
aliguori15859692009-04-21 23:11:53 +0000519static int img_check(int argc, char **argv)
520{
521 int c, ret;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500522 OutputFormat output_format = OFORMAT_HUMAN;
523 const char *filename, *fmt, *output;
aliguori15859692009-04-21 23:11:53 +0000524 BlockDriverState *bs;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200525 int fix = 0;
Stefan Hajnoczi058f8f12012-08-09 13:05:56 +0100526 int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500527 ImageCheck *check;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100528 bool quiet = false;
aliguori15859692009-04-21 23:11:53 +0000529
530 fmt = NULL;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500531 output = NULL;
aliguori15859692009-04-21 23:11:53 +0000532 for(;;) {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500533 int option_index = 0;
534 static const struct option long_options[] = {
535 {"help", no_argument, 0, 'h'},
536 {"format", required_argument, 0, 'f'},
537 {"repair", no_argument, 0, 'r'},
538 {"output", required_argument, 0, OPTION_OUTPUT},
539 {0, 0, 0, 0}
540 };
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100541 c = getopt_long(argc, argv, "f:hr:q",
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500542 long_options, &option_index);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100543 if (c == -1) {
aliguori15859692009-04-21 23:11:53 +0000544 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100545 }
aliguori15859692009-04-21 23:11:53 +0000546 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100547 case '?':
aliguori15859692009-04-21 23:11:53 +0000548 case 'h':
549 help();
550 break;
551 case 'f':
552 fmt = optarg;
553 break;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200554 case 'r':
555 flags |= BDRV_O_RDWR;
556
557 if (!strcmp(optarg, "leaks")) {
558 fix = BDRV_FIX_LEAKS;
559 } else if (!strcmp(optarg, "all")) {
560 fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
561 } else {
562 help();
563 }
564 break;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500565 case OPTION_OUTPUT:
566 output = optarg;
567 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100568 case 'q':
569 quiet = true;
570 break;
aliguori15859692009-04-21 23:11:53 +0000571 }
572 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100573 if (optind >= argc) {
aliguori15859692009-04-21 23:11:53 +0000574 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100575 }
aliguori15859692009-04-21 23:11:53 +0000576 filename = argv[optind++];
577
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500578 if (output && !strcmp(output, "json")) {
579 output_format = OFORMAT_JSON;
580 } else if (output && !strcmp(output, "human")) {
581 output_format = OFORMAT_HUMAN;
582 } else if (output) {
583 error_report("--output must be used with human or json as argument.");
584 return 1;
585 }
586
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100587 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900588 if (!bs) {
589 return 1;
590 }
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500591
592 check = g_new0(ImageCheck, 1);
593 ret = collect_image_check(bs, check, filename, fmt, fix);
Kevin Wolfe076f332010-06-29 11:43:13 +0200594
595 if (ret == -ENOTSUP) {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500596 if (output_format == OFORMAT_HUMAN) {
597 error_report("This image format does not support checks");
598 }
599 ret = 1;
600 goto fail;
Kevin Wolfe076f332010-06-29 11:43:13 +0200601 }
602
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500603 if (check->corruptions_fixed || check->leaks_fixed) {
604 int corruptions_fixed, leaks_fixed;
605
606 leaks_fixed = check->leaks_fixed;
607 corruptions_fixed = check->corruptions_fixed;
608
609 if (output_format == OFORMAT_HUMAN) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100610 qprintf(quiet,
611 "The following inconsistencies were found and repaired:\n\n"
612 " %" PRId64 " leaked clusters\n"
613 " %" PRId64 " corruptions\n\n"
614 "Double checking the fixed image now...\n",
615 check->leaks_fixed,
616 check->corruptions_fixed);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500617 }
618
619 ret = collect_image_check(bs, check, filename, fmt, 0);
620
621 check->leaks_fixed = leaks_fixed;
622 check->corruptions_fixed = corruptions_fixed;
Kevin Wolfccf34712012-05-11 18:16:54 +0200623 }
624
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500625 switch (output_format) {
626 case OFORMAT_HUMAN:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100627 dump_human_image_check(check, quiet);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500628 break;
629 case OFORMAT_JSON:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100630 dump_json_image_check(check, quiet);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500631 break;
632 }
633
634 if (ret || check->check_errors) {
635 ret = 1;
636 goto fail;
637 }
638
639 if (check->corruptions) {
640 ret = 2;
641 } else if (check->leaks) {
642 ret = 3;
Kevin Wolfe076f332010-06-29 11:43:13 +0200643 } else {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500644 ret = 0;
aliguori15859692009-04-21 23:11:53 +0000645 }
646
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500647fail:
648 qapi_free_ImageCheck(check);
aliguori15859692009-04-21 23:11:53 +0000649 bdrv_delete(bs);
Kevin Wolfe076f332010-06-29 11:43:13 +0200650
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500651 return ret;
aliguori15859692009-04-21 23:11:53 +0000652}
653
bellardea2384d2004-08-01 21:59:26 +0000654static int img_commit(int argc, char **argv)
655{
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400656 int c, ret, flags;
657 const char *filename, *fmt, *cache;
bellardea2384d2004-08-01 21:59:26 +0000658 BlockDriverState *bs;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100659 bool quiet = false;
bellardea2384d2004-08-01 21:59:26 +0000660
661 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400662 cache = BDRV_DEFAULT_CACHE;
bellardea2384d2004-08-01 21:59:26 +0000663 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100664 c = getopt(argc, argv, "f:ht:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100665 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000666 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100667 }
bellardea2384d2004-08-01 21:59:26 +0000668 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100669 case '?':
bellardea2384d2004-08-01 21:59:26 +0000670 case 'h':
671 help();
672 break;
673 case 'f':
674 fmt = optarg;
675 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400676 case 't':
677 cache = optarg;
678 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100679 case 'q':
680 quiet = true;
681 break;
bellardea2384d2004-08-01 21:59:26 +0000682 }
683 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100684 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +0000685 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100686 }
bellardea2384d2004-08-01 21:59:26 +0000687 filename = argv[optind++];
688
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400689 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +0100690 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400691 if (ret < 0) {
692 error_report("Invalid cache option: %s", cache);
693 return -1;
694 }
695
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100696 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900697 if (!bs) {
698 return 1;
699 }
bellardea2384d2004-08-01 21:59:26 +0000700 ret = bdrv_commit(bs);
701 switch(ret) {
702 case 0:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100703 qprintf(quiet, "Image committed.\n");
bellardea2384d2004-08-01 21:59:26 +0000704 break;
705 case -ENOENT:
Jes Sorensen15654a62010-12-16 14:31:53 +0100706 error_report("No disk inserted");
bellardea2384d2004-08-01 21:59:26 +0000707 break;
708 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +0100709 error_report("Image is read-only");
bellardea2384d2004-08-01 21:59:26 +0000710 break;
711 case -ENOTSUP:
Jes Sorensen15654a62010-12-16 14:31:53 +0100712 error_report("Image is already committed");
bellardea2384d2004-08-01 21:59:26 +0000713 break;
714 default:
Jes Sorensen15654a62010-12-16 14:31:53 +0100715 error_report("Error while committing image");
bellardea2384d2004-08-01 21:59:26 +0000716 break;
717 }
718
719 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900720 if (ret) {
721 return 1;
722 }
bellardea2384d2004-08-01 21:59:26 +0000723 return 0;
724}
725
Dmitry Konishchevf6a00aa2011-05-18 15:03:59 +0400726/*
thsf58c7b32008-06-05 21:53:49 +0000727 * Returns true iff the first sector pointed to by 'buf' contains at least
728 * a non-NUL byte.
729 *
730 * 'pnum' is set to the number of sectors (including and immediately following
731 * the first one) that are known to be in the same allocated/unallocated state.
732 */
bellardea2384d2004-08-01 21:59:26 +0000733static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
734{
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000735 bool is_zero;
736 int i;
bellardea2384d2004-08-01 21:59:26 +0000737
738 if (n <= 0) {
739 *pnum = 0;
740 return 0;
741 }
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000742 is_zero = buffer_is_zero(buf, 512);
bellardea2384d2004-08-01 21:59:26 +0000743 for(i = 1; i < n; i++) {
744 buf += 512;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000745 if (is_zero != buffer_is_zero(buf, 512)) {
bellardea2384d2004-08-01 21:59:26 +0000746 break;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000747 }
bellardea2384d2004-08-01 21:59:26 +0000748 }
749 *pnum = i;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000750 return !is_zero;
bellardea2384d2004-08-01 21:59:26 +0000751}
752
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100753/*
Kevin Wolfa22f1232011-08-26 15:27:13 +0200754 * Like is_allocated_sectors, but if the buffer starts with a used sector,
755 * up to 'min' consecutive sectors containing zeros are ignored. This avoids
756 * breaking up write requests for only small sparse areas.
757 */
758static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
759 int min)
760{
761 int ret;
762 int num_checked, num_used;
763
764 if (n < min) {
765 min = n;
766 }
767
768 ret = is_allocated_sectors(buf, n, pnum);
769 if (!ret) {
770 return ret;
771 }
772
773 num_used = *pnum;
774 buf += BDRV_SECTOR_SIZE * *pnum;
775 n -= *pnum;
776 num_checked = num_used;
777
778 while (n > 0) {
779 ret = is_allocated_sectors(buf, n, pnum);
780
781 buf += BDRV_SECTOR_SIZE * *pnum;
782 n -= *pnum;
783 num_checked += *pnum;
784 if (ret) {
785 num_used = num_checked;
786 } else if (*pnum >= min) {
787 break;
788 }
789 }
790
791 *pnum = num_used;
792 return 1;
793}
794
795/*
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100796 * Compares two buffers sector by sector. Returns 0 if the first sector of both
797 * buffers matches, non-zero otherwise.
798 *
799 * pnum is set to the number of sectors (including and immediately following
800 * the first one) that are known to have the same comparison result
801 */
802static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
803 int *pnum)
804{
805 int res, i;
806
807 if (n <= 0) {
808 *pnum = 0;
809 return 0;
810 }
811
812 res = !!memcmp(buf1, buf2, 512);
813 for(i = 1; i < n; i++) {
814 buf1 += 512;
815 buf2 += 512;
816
817 if (!!memcmp(buf1, buf2, 512) != res) {
818 break;
819 }
820 }
821
822 *pnum = i;
823 return res;
824}
825
Kevin Wolf80ee15a2009-09-15 12:30:43 +0200826#define IO_BUF_SIZE (2 * 1024 * 1024)
bellardea2384d2004-08-01 21:59:26 +0000827
Miroslav Rezaninad14ed182013-02-13 09:09:41 +0100828static int64_t sectors_to_bytes(int64_t sectors)
829{
830 return sectors << BDRV_SECTOR_BITS;
831}
832
833static int64_t sectors_to_process(int64_t total, int64_t from)
834{
835 return MIN(total - from, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
836}
837
838/*
839 * Check if passed sectors are empty (not allocated or contain only 0 bytes)
840 *
841 * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero
842 * data and negative value on error.
843 *
844 * @param bs: Driver used for accessing file
845 * @param sect_num: Number of first sector to check
846 * @param sect_count: Number of sectors to check
847 * @param filename: Name of disk file we are checking (logging purpose)
848 * @param buffer: Allocated buffer for storing read data
849 * @param quiet: Flag for quiet mode
850 */
851static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
852 int sect_count, const char *filename,
853 uint8_t *buffer, bool quiet)
854{
855 int pnum, ret = 0;
856 ret = bdrv_read(bs, sect_num, buffer, sect_count);
857 if (ret < 0) {
858 error_report("Error while reading offset %" PRId64 " of %s: %s",
859 sectors_to_bytes(sect_num), filename, strerror(-ret));
860 return ret;
861 }
862 ret = is_allocated_sectors(buffer, sect_count, &pnum);
863 if (ret || pnum != sect_count) {
864 qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
865 sectors_to_bytes(ret ? sect_num : sect_num + pnum));
866 return 1;
867 }
868
869 return 0;
870}
871
872/*
873 * Compares two images. Exit codes:
874 *
875 * 0 - Images are identical
876 * 1 - Images differ
877 * >1 - Error occurred
878 */
879static int img_compare(int argc, char **argv)
880{
881 const char *fmt1 = NULL, *fmt2 = NULL, *filename1, *filename2;
882 BlockDriverState *bs1, *bs2;
883 int64_t total_sectors1, total_sectors2;
884 uint8_t *buf1 = NULL, *buf2 = NULL;
885 int pnum1, pnum2;
886 int allocated1, allocated2;
887 int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
888 bool progress = false, quiet = false, strict = false;
889 int64_t total_sectors;
890 int64_t sector_num = 0;
891 int64_t nb_sectors;
892 int c, pnum;
893 uint64_t bs_sectors;
894 uint64_t progress_base;
895
896 for (;;) {
897 c = getopt(argc, argv, "hpf:F:sq");
898 if (c == -1) {
899 break;
900 }
901 switch (c) {
902 case '?':
903 case 'h':
904 help();
905 break;
906 case 'f':
907 fmt1 = optarg;
908 break;
909 case 'F':
910 fmt2 = optarg;
911 break;
912 case 'p':
913 progress = true;
914 break;
915 case 'q':
916 quiet = true;
917 break;
918 case 's':
919 strict = true;
920 break;
921 }
922 }
923
924 /* Progress is not shown in Quiet mode */
925 if (quiet) {
926 progress = false;
927 }
928
929
930 if (optind > argc - 2) {
931 help();
932 }
933 filename1 = argv[optind++];
934 filename2 = argv[optind++];
935
936 /* Initialize before goto out */
937 qemu_progress_init(progress, 2.0);
938
939 bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
940 if (!bs1) {
941 error_report("Can't open file %s", filename1);
942 ret = 2;
943 goto out3;
944 }
945
946 bs2 = bdrv_new_open(filename2, fmt2, BDRV_O_FLAGS, true, quiet);
947 if (!bs2) {
948 error_report("Can't open file %s", filename2);
949 ret = 2;
950 goto out2;
951 }
952
953 buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
954 buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
955 bdrv_get_geometry(bs1, &bs_sectors);
956 total_sectors1 = bs_sectors;
957 bdrv_get_geometry(bs2, &bs_sectors);
958 total_sectors2 = bs_sectors;
959 total_sectors = MIN(total_sectors1, total_sectors2);
960 progress_base = MAX(total_sectors1, total_sectors2);
961
962 qemu_progress_print(0, 100);
963
964 if (strict && total_sectors1 != total_sectors2) {
965 ret = 1;
966 qprintf(quiet, "Strict mode: Image size mismatch!\n");
967 goto out;
968 }
969
970 for (;;) {
971 nb_sectors = sectors_to_process(total_sectors, sector_num);
972 if (nb_sectors <= 0) {
973 break;
974 }
975 allocated1 = bdrv_is_allocated_above(bs1, NULL, sector_num, nb_sectors,
976 &pnum1);
977 if (allocated1 < 0) {
978 ret = 3;
979 error_report("Sector allocation test failed for %s", filename1);
980 goto out;
981 }
982
983 allocated2 = bdrv_is_allocated_above(bs2, NULL, sector_num, nb_sectors,
984 &pnum2);
985 if (allocated2 < 0) {
986 ret = 3;
987 error_report("Sector allocation test failed for %s", filename2);
988 goto out;
989 }
990 nb_sectors = MIN(pnum1, pnum2);
991
992 if (allocated1 == allocated2) {
993 if (allocated1) {
994 ret = bdrv_read(bs1, sector_num, buf1, nb_sectors);
995 if (ret < 0) {
996 error_report("Error while reading offset %" PRId64 " of %s:"
997 " %s", sectors_to_bytes(sector_num), filename1,
998 strerror(-ret));
999 ret = 4;
1000 goto out;
1001 }
1002 ret = bdrv_read(bs2, sector_num, buf2, nb_sectors);
1003 if (ret < 0) {
1004 error_report("Error while reading offset %" PRId64
1005 " of %s: %s", sectors_to_bytes(sector_num),
1006 filename2, strerror(-ret));
1007 ret = 4;
1008 goto out;
1009 }
1010 ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
1011 if (ret || pnum != nb_sectors) {
1012 ret = 1;
1013 qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
1014 sectors_to_bytes(
1015 ret ? sector_num : sector_num + pnum));
1016 goto out;
1017 }
1018 }
1019 } else {
1020 if (strict) {
1021 ret = 1;
1022 qprintf(quiet, "Strict mode: Offset %" PRId64
1023 " allocation mismatch!\n",
1024 sectors_to_bytes(sector_num));
1025 goto out;
1026 }
1027
1028 if (allocated1) {
1029 ret = check_empty_sectors(bs1, sector_num, nb_sectors,
1030 filename1, buf1, quiet);
1031 } else {
1032 ret = check_empty_sectors(bs2, sector_num, nb_sectors,
1033 filename2, buf1, quiet);
1034 }
1035 if (ret) {
1036 if (ret < 0) {
1037 ret = 4;
1038 error_report("Error while reading offset %" PRId64 ": %s",
1039 sectors_to_bytes(sector_num), strerror(-ret));
1040 }
1041 goto out;
1042 }
1043 }
1044 sector_num += nb_sectors;
1045 qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
1046 }
1047
1048 if (total_sectors1 != total_sectors2) {
1049 BlockDriverState *bs_over;
1050 int64_t total_sectors_over;
1051 const char *filename_over;
1052
1053 qprintf(quiet, "Warning: Image size mismatch!\n");
1054 if (total_sectors1 > total_sectors2) {
1055 total_sectors_over = total_sectors1;
1056 bs_over = bs1;
1057 filename_over = filename1;
1058 } else {
1059 total_sectors_over = total_sectors2;
1060 bs_over = bs2;
1061 filename_over = filename2;
1062 }
1063
1064 for (;;) {
1065 nb_sectors = sectors_to_process(total_sectors_over, sector_num);
1066 if (nb_sectors <= 0) {
1067 break;
1068 }
1069 ret = bdrv_is_allocated_above(bs_over, NULL, sector_num,
1070 nb_sectors, &pnum);
1071 if (ret < 0) {
1072 ret = 3;
1073 error_report("Sector allocation test failed for %s",
1074 filename_over);
1075 goto out;
1076
1077 }
1078 nb_sectors = pnum;
1079 if (ret) {
1080 ret = check_empty_sectors(bs_over, sector_num, nb_sectors,
1081 filename_over, buf1, quiet);
1082 if (ret) {
1083 if (ret < 0) {
1084 ret = 4;
1085 error_report("Error while reading offset %" PRId64
1086 " of %s: %s", sectors_to_bytes(sector_num),
1087 filename_over, strerror(-ret));
1088 }
1089 goto out;
1090 }
1091 }
1092 sector_num += nb_sectors;
1093 qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
1094 }
1095 }
1096
1097 qprintf(quiet, "Images are identical.\n");
1098 ret = 0;
1099
1100out:
1101 bdrv_delete(bs2);
1102 qemu_vfree(buf1);
1103 qemu_vfree(buf2);
1104out2:
1105 bdrv_delete(bs1);
1106out3:
1107 qemu_progress_end();
1108 return ret;
1109}
1110
bellardea2384d2004-08-01 21:59:26 +00001111static int img_convert(int argc, char **argv)
1112{
Jes Sorenseneec77d92010-12-07 17:44:34 +01001113 int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001114 int progress = 0, flags;
1115 const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001116 BlockDriver *drv, *proto_drv;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001117 BlockDriverState **bs = NULL, *out_bs = NULL;
ths96b8f132007-12-17 01:35:20 +00001118 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
1119 uint64_t bs_sectors;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001120 uint8_t * buf = NULL;
bellardea2384d2004-08-01 21:59:26 +00001121 const uint8_t *buf1;
bellardfaea38e2006-08-05 21:31:00 +00001122 BlockDriverInfo bdi;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001123 QEMUOptionParameter *param = NULL, *create_options = NULL;
Kevin Wolfa18953f2010-10-14 15:46:04 +02001124 QEMUOptionParameter *out_baseimg_param;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001125 char *options = NULL;
edison51ef6722010-09-21 19:58:41 -07001126 const char *snapshot_name = NULL;
Kevin Wolf1f710492012-10-12 14:29:18 +02001127 float local_progress = 0;
Kevin Wolfa22f1232011-08-26 15:27:13 +02001128 int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001129 bool quiet = false;
bellardea2384d2004-08-01 21:59:26 +00001130
1131 fmt = NULL;
1132 out_fmt = "raw";
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001133 cache = "unsafe";
thsf58c7b32008-06-05 21:53:49 +00001134 out_baseimg = NULL;
Jes Sorenseneec77d92010-12-07 17:44:34 +01001135 compress = 0;
bellardea2384d2004-08-01 21:59:26 +00001136 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001137 c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001138 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001139 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001140 }
bellardea2384d2004-08-01 21:59:26 +00001141 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001142 case '?':
bellardea2384d2004-08-01 21:59:26 +00001143 case 'h':
1144 help();
1145 break;
1146 case 'f':
1147 fmt = optarg;
1148 break;
1149 case 'O':
1150 out_fmt = optarg;
1151 break;
thsf58c7b32008-06-05 21:53:49 +00001152 case 'B':
1153 out_baseimg = optarg;
1154 break;
bellardea2384d2004-08-01 21:59:26 +00001155 case 'c':
Jes Sorenseneec77d92010-12-07 17:44:34 +01001156 compress = 1;
bellardea2384d2004-08-01 21:59:26 +00001157 break;
1158 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +02001159 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +01001160 "encryption\' instead!");
1161 return 1;
thsec36ba12007-09-16 21:59:02 +00001162 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +02001163 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +01001164 "compat6\' instead!");
1165 return 1;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001166 case 'o':
1167 options = optarg;
1168 break;
edison51ef6722010-09-21 19:58:41 -07001169 case 's':
1170 snapshot_name = optarg;
1171 break;
Kevin Wolfa22f1232011-08-26 15:27:13 +02001172 case 'S':
1173 {
1174 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +01001175 char *end;
1176 sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
1177 if (sval < 0 || *end) {
Kevin Wolfa22f1232011-08-26 15:27:13 +02001178 error_report("Invalid minimum zero buffer size for sparse output specified");
1179 return 1;
1180 }
1181
1182 min_sparse = sval / BDRV_SECTOR_SIZE;
1183 break;
1184 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001185 case 'p':
1186 progress = 1;
1187 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001188 case 't':
1189 cache = optarg;
1190 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001191 case 'q':
1192 quiet = true;
1193 break;
bellardea2384d2004-08-01 21:59:26 +00001194 }
1195 }
ths3b46e622007-09-17 08:09:54 +00001196
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001197 if (quiet) {
1198 progress = 0;
1199 }
1200
balrog926c2d22007-10-31 01:11:44 +00001201 bs_n = argc - optind - 1;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001202 if (bs_n < 1) {
1203 help();
1204 }
balrog926c2d22007-10-31 01:11:44 +00001205
1206 out_filename = argv[argc - 1];
thsf58c7b32008-06-05 21:53:49 +00001207
Charles Arnoldfa170c12012-05-11 10:57:54 -06001208 /* Initialize before goto out */
1209 qemu_progress_init(progress, 2.0);
1210
Peter Maydellc8057f92012-08-02 13:45:54 +01001211 if (options && is_help_option(options)) {
Jes Sorensen4ac8aac2010-12-06 15:25:38 +01001212 ret = print_block_option_help(out_filename, out_fmt);
1213 goto out;
1214 }
1215
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001216 if (bs_n > 1 && out_baseimg) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001217 error_report("-B makes no sense when concatenating multiple input "
1218 "images");
Jes Sorensen31ca34b2010-12-06 15:25:36 +01001219 ret = -1;
1220 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001221 }
Dong Xu Wangf8111c22012-03-15 20:13:31 +08001222
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001223 qemu_progress_print(0, 100);
1224
Anthony Liguori7267c092011-08-20 22:09:37 -05001225 bs = g_malloc0(bs_n * sizeof(BlockDriverState *));
balrog926c2d22007-10-31 01:11:44 +00001226
1227 total_sectors = 0;
1228 for (bs_i = 0; bs_i < bs_n; bs_i++) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001229 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true,
1230 quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001231 if (!bs[bs_i]) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001232 error_report("Could not open '%s'", argv[optind + bs_i]);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001233 ret = -1;
1234 goto out;
1235 }
balrog926c2d22007-10-31 01:11:44 +00001236 bdrv_get_geometry(bs[bs_i], &bs_sectors);
1237 total_sectors += bs_sectors;
1238 }
bellardea2384d2004-08-01 21:59:26 +00001239
edison51ef6722010-09-21 19:58:41 -07001240 if (snapshot_name != NULL) {
1241 if (bs_n > 1) {
Markus Armbruster6daf1942011-06-22 14:03:54 +02001242 error_report("No support for concatenating multiple snapshot");
edison51ef6722010-09-21 19:58:41 -07001243 ret = -1;
1244 goto out;
1245 }
1246 if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +02001247 error_report("Failed to load snapshot");
edison51ef6722010-09-21 19:58:41 -07001248 ret = -1;
1249 goto out;
1250 }
1251 }
1252
Kevin Wolfefa84d42009-05-18 16:42:12 +02001253 /* Find driver and parse its options */
bellardea2384d2004-08-01 21:59:26 +00001254 drv = bdrv_find_format(out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001255 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001256 error_report("Unknown file format '%s'", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001257 ret = -1;
1258 goto out;
1259 }
balrog926c2d22007-10-31 01:11:44 +00001260
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001261 proto_drv = bdrv_find_protocol(out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001262 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001263 error_report("Unknown protocol '%s'", out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001264 ret = -1;
1265 goto out;
1266 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001267
1268 create_options = append_option_parameters(create_options,
1269 drv->create_options);
1270 create_options = append_option_parameters(create_options,
1271 proto_drv->create_options);
Kevin Wolfdb08adf2009-06-04 15:39:38 +02001272
Kevin Wolfefa84d42009-05-18 16:42:12 +02001273 if (options) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001274 param = parse_option_parameters(options, create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001275 if (param == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001276 error_report("Invalid options for file format '%s'.", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001277 ret = -1;
1278 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001279 }
1280 } else {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001281 param = parse_option_parameters("", create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001282 }
1283
1284 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
Jes Sorenseneec77d92010-12-07 17:44:34 +01001285 ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001286 if (ret < 0) {
1287 goto out;
1288 }
Kevin Wolfefa84d42009-05-18 16:42:12 +02001289
Kevin Wolfa18953f2010-10-14 15:46:04 +02001290 /* Get backing file name if -o backing_file was used */
1291 out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
1292 if (out_baseimg_param) {
1293 out_baseimg = out_baseimg_param->value.s;
1294 }
1295
Kevin Wolfefa84d42009-05-18 16:42:12 +02001296 /* Check if compression is supported */
Jes Sorenseneec77d92010-12-07 17:44:34 +01001297 if (compress) {
Kevin Wolfefa84d42009-05-18 16:42:12 +02001298 QEMUOptionParameter *encryption =
1299 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
Kevin Wolf41521fa2011-10-18 16:19:42 +02001300 QEMUOptionParameter *preallocation =
1301 get_option_parameter(param, BLOCK_OPT_PREALLOC);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001302
1303 if (!drv->bdrv_write_compressed) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001304 error_report("Compression not supported for this file format");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001305 ret = -1;
1306 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001307 }
1308
1309 if (encryption && encryption->value.n) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001310 error_report("Compression and encryption not supported at "
1311 "the same time");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001312 ret = -1;
1313 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001314 }
Kevin Wolf41521fa2011-10-18 16:19:42 +02001315
1316 if (preallocation && preallocation->value.s
1317 && strcmp(preallocation->value.s, "off"))
1318 {
1319 error_report("Compression and preallocation not supported at "
1320 "the same time");
1321 ret = -1;
1322 goto out;
1323 }
Kevin Wolfefa84d42009-05-18 16:42:12 +02001324 }
1325
1326 /* Create the new image */
1327 ret = bdrv_create(drv, out_filename, param);
bellardea2384d2004-08-01 21:59:26 +00001328 if (ret < 0) {
1329 if (ret == -ENOTSUP) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001330 error_report("Formatting not supported for file format '%s'",
1331 out_fmt);
aurel326e9ea0c2009-04-15 14:42:46 +00001332 } else if (ret == -EFBIG) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001333 error_report("The image size is too large for file format '%s'",
1334 out_fmt);
bellardea2384d2004-08-01 21:59:26 +00001335 } else {
Jes Sorensen15654a62010-12-16 14:31:53 +01001336 error_report("%s: error while converting %s: %s",
1337 out_filename, out_fmt, strerror(-ret));
bellardea2384d2004-08-01 21:59:26 +00001338 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001339 goto out;
bellardea2384d2004-08-01 21:59:26 +00001340 }
ths3b46e622007-09-17 08:09:54 +00001341
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001342 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +01001343 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001344 if (ret < 0) {
1345 error_report("Invalid cache option: %s", cache);
1346 return -1;
1347 }
1348
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001349 out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001350 if (!out_bs) {
1351 ret = -1;
1352 goto out;
1353 }
bellardea2384d2004-08-01 21:59:26 +00001354
balrog926c2d22007-10-31 01:11:44 +00001355 bs_i = 0;
1356 bs_offset = 0;
1357 bdrv_get_geometry(bs[0], &bs_sectors);
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001358 buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
balrog926c2d22007-10-31 01:11:44 +00001359
Jes Sorenseneec77d92010-12-07 17:44:34 +01001360 if (compress) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001361 ret = bdrv_get_info(out_bs, &bdi);
1362 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001363 error_report("could not get block driver info");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001364 goto out;
1365 }
bellardfaea38e2006-08-05 21:31:00 +00001366 cluster_size = bdi.cluster_size;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001367 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001368 error_report("invalid cluster size");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001369 ret = -1;
1370 goto out;
1371 }
bellardea2384d2004-08-01 21:59:26 +00001372 cluster_sectors = cluster_size >> 9;
1373 sector_num = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001374
1375 nb_sectors = total_sectors;
Kevin Wolf1f710492012-10-12 14:29:18 +02001376 if (nb_sectors != 0) {
1377 local_progress = (float)100 /
1378 (nb_sectors / MIN(nb_sectors, cluster_sectors));
1379 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001380
bellardea2384d2004-08-01 21:59:26 +00001381 for(;;) {
balrog926c2d22007-10-31 01:11:44 +00001382 int64_t bs_num;
1383 int remainder;
1384 uint8_t *buf2;
1385
bellardea2384d2004-08-01 21:59:26 +00001386 nb_sectors = total_sectors - sector_num;
1387 if (nb_sectors <= 0)
1388 break;
1389 if (nb_sectors >= cluster_sectors)
1390 n = cluster_sectors;
1391 else
1392 n = nb_sectors;
balrog926c2d22007-10-31 01:11:44 +00001393
1394 bs_num = sector_num - bs_offset;
1395 assert (bs_num >= 0);
1396 remainder = n;
1397 buf2 = buf;
1398 while (remainder > 0) {
1399 int nlow;
1400 while (bs_num == bs_sectors) {
1401 bs_i++;
1402 assert (bs_i < bs_n);
1403 bs_offset += bs_sectors;
1404 bdrv_get_geometry(bs[bs_i], &bs_sectors);
1405 bs_num = 0;
Blue Swirl0bfcd592010-05-22 08:02:12 +00001406 /* printf("changing part: sector_num=%" PRId64 ", "
1407 "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
1408 "\n", sector_num, bs_i, bs_offset, bs_sectors); */
balrog926c2d22007-10-31 01:11:44 +00001409 }
1410 assert (bs_num < bs_sectors);
1411
1412 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
1413
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001414 ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
1415 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001416 error_report("error while reading sector %" PRId64 ": %s",
1417 bs_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001418 goto out;
1419 }
balrog926c2d22007-10-31 01:11:44 +00001420
1421 buf2 += nlow * 512;
1422 bs_num += nlow;
1423
1424 remainder -= nlow;
1425 }
1426 assert (remainder == 0);
1427
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001428 if (n < cluster_sectors) {
bellardea2384d2004-08-01 21:59:26 +00001429 memset(buf + n * 512, 0, cluster_size - n * 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001430 }
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +00001431 if (!buffer_is_zero(buf, cluster_size)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001432 ret = bdrv_write_compressed(out_bs, sector_num, buf,
1433 cluster_sectors);
1434 if (ret != 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001435 error_report("error while compressing sector %" PRId64
1436 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001437 goto out;
1438 }
bellardea2384d2004-08-01 21:59:26 +00001439 }
1440 sector_num += n;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001441 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +00001442 }
bellardfaea38e2006-08-05 21:31:00 +00001443 /* signal EOF to align */
1444 bdrv_write_compressed(out_bs, 0, NULL, 0);
bellardea2384d2004-08-01 21:59:26 +00001445 } else {
Kevin Wolff2feebb2010-04-14 17:30:35 +02001446 int has_zero_init = bdrv_has_zero_init(out_bs);
1447
thsf58c7b32008-06-05 21:53:49 +00001448 sector_num = 0; // total number of sectors converted so far
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001449 nb_sectors = total_sectors - sector_num;
Kevin Wolf1f710492012-10-12 14:29:18 +02001450 if (nb_sectors != 0) {
1451 local_progress = (float)100 /
1452 (nb_sectors / MIN(nb_sectors, IO_BUF_SIZE / 512));
1453 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001454
bellardea2384d2004-08-01 21:59:26 +00001455 for(;;) {
1456 nb_sectors = total_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001457 if (nb_sectors <= 0) {
bellardea2384d2004-08-01 21:59:26 +00001458 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001459 }
1460 if (nb_sectors >= (IO_BUF_SIZE / 512)) {
bellardea2384d2004-08-01 21:59:26 +00001461 n = (IO_BUF_SIZE / 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001462 } else {
bellardea2384d2004-08-01 21:59:26 +00001463 n = nb_sectors;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001464 }
balrog926c2d22007-10-31 01:11:44 +00001465
1466 while (sector_num - bs_offset >= bs_sectors) {
1467 bs_i ++;
1468 assert (bs_i < bs_n);
1469 bs_offset += bs_sectors;
1470 bdrv_get_geometry(bs[bs_i], &bs_sectors);
Blue Swirl0bfcd592010-05-22 08:02:12 +00001471 /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
1472 "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
balrog926c2d22007-10-31 01:11:44 +00001473 sector_num, bs_i, bs_offset, bs_sectors); */
1474 }
1475
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001476 if (n > bs_offset + bs_sectors - sector_num) {
balrog926c2d22007-10-31 01:11:44 +00001477 n = bs_offset + bs_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001478 }
balrog926c2d22007-10-31 01:11:44 +00001479
Kevin Wolff2feebb2010-04-14 17:30:35 +02001480 if (has_zero_init) {
Akkarit Sangpetchd0320442009-07-17 10:02:15 +02001481 /* If the output image is being created as a copy on write image,
1482 assume that sectors which are unallocated in the input image
1483 are present in both the output's and input's base images (no
1484 need to copy them). */
1485 if (out_baseimg) {
1486 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
1487 n, &n1)) {
1488 sector_num += n1;
1489 continue;
1490 }
1491 /* The next 'n1' sectors are allocated in the input image. Copy
1492 only those as they may be followed by unallocated sectors. */
1493 n = n1;
aliguori93c65b42009-04-05 17:40:43 +00001494 }
aliguori93c65b42009-04-05 17:40:43 +00001495 } else {
1496 n1 = n;
thsf58c7b32008-06-05 21:53:49 +00001497 }
1498
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001499 ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
1500 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001501 error_report("error while reading sector %" PRId64 ": %s",
1502 sector_num - bs_offset, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001503 goto out;
1504 }
bellardea2384d2004-08-01 21:59:26 +00001505 /* NOTE: at the same time we convert, we do not write zero
1506 sectors to have a chance to compress the image. Ideally, we
1507 should add a specific call to have the info to go faster */
1508 buf1 = buf;
1509 while (n > 0) {
thsf58c7b32008-06-05 21:53:49 +00001510 /* If the output image is being created as a copy on write image,
1511 copy all sectors even the ones containing only NUL bytes,
aliguori93c65b42009-04-05 17:40:43 +00001512 because they may differ from the sectors in the base image.
1513
1514 If the output is to a host device, we also write out
1515 sectors that are entirely 0, since whatever data was
1516 already there is garbage, not 0s. */
Kevin Wolff2feebb2010-04-14 17:30:35 +02001517 if (!has_zero_init || out_baseimg ||
Kevin Wolfa22f1232011-08-26 15:27:13 +02001518 is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001519 ret = bdrv_write(out_bs, sector_num, buf1, n1);
1520 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001521 error_report("error while writing sector %" PRId64
1522 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001523 goto out;
1524 }
bellardea2384d2004-08-01 21:59:26 +00001525 }
1526 sector_num += n1;
1527 n -= n1;
1528 buf1 += n1 * 512;
1529 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001530 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +00001531 }
1532 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001533out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001534 qemu_progress_end();
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001535 free_option_parameters(create_options);
1536 free_option_parameters(param);
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001537 qemu_vfree(buf);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001538 if (out_bs) {
1539 bdrv_delete(out_bs);
1540 }
Jes Sorensen31ca34b2010-12-06 15:25:36 +01001541 if (bs) {
1542 for (bs_i = 0; bs_i < bs_n; bs_i++) {
1543 if (bs[bs_i]) {
1544 bdrv_delete(bs[bs_i]);
1545 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001546 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001547 g_free(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001548 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001549 if (ret) {
1550 return 1;
1551 }
bellardea2384d2004-08-01 21:59:26 +00001552 return 0;
1553}
1554
bellard57d1a2b2004-08-03 21:15:11 +00001555
bellardfaea38e2006-08-05 21:31:00 +00001556static void dump_snapshots(BlockDriverState *bs)
1557{
1558 QEMUSnapshotInfo *sn_tab, *sn;
1559 int nb_sns, i;
1560 char buf[256];
1561
1562 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1563 if (nb_sns <= 0)
1564 return;
1565 printf("Snapshot list:\n");
1566 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
1567 for(i = 0; i < nb_sns; i++) {
1568 sn = &sn_tab[i];
1569 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
1570 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001571 g_free(sn_tab);
bellardfaea38e2006-08-05 21:31:00 +00001572}
1573
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001574static void dump_json_image_info_list(ImageInfoList *list)
1575{
1576 Error *errp = NULL;
1577 QString *str;
1578 QmpOutputVisitor *ov = qmp_output_visitor_new();
1579 QObject *obj;
1580 visit_type_ImageInfoList(qmp_output_get_visitor(ov),
1581 &list, NULL, &errp);
1582 obj = qmp_output_get_qobject(ov);
1583 str = qobject_to_json_pretty(obj);
1584 assert(str != NULL);
1585 printf("%s\n", qstring_get_str(str));
1586 qobject_decref(obj);
1587 qmp_output_visitor_cleanup(ov);
1588 QDECREF(str);
1589}
1590
Benoît Canetc054b3f2012-09-05 13:09:02 +02001591static void collect_snapshots(BlockDriverState *bs , ImageInfo *info)
bellardea2384d2004-08-01 21:59:26 +00001592{
Benoît Canetc054b3f2012-09-05 13:09:02 +02001593 int i, sn_count;
1594 QEMUSnapshotInfo *sn_tab = NULL;
1595 SnapshotInfoList *info_list, *cur_item = NULL;
1596 sn_count = bdrv_snapshot_list(bs, &sn_tab);
1597
1598 for (i = 0; i < sn_count; i++) {
1599 info->has_snapshots = true;
1600 info_list = g_new0(SnapshotInfoList, 1);
1601
1602 info_list->value = g_new0(SnapshotInfo, 1);
1603 info_list->value->id = g_strdup(sn_tab[i].id_str);
1604 info_list->value->name = g_strdup(sn_tab[i].name);
1605 info_list->value->vm_state_size = sn_tab[i].vm_state_size;
1606 info_list->value->date_sec = sn_tab[i].date_sec;
1607 info_list->value->date_nsec = sn_tab[i].date_nsec;
1608 info_list->value->vm_clock_sec = sn_tab[i].vm_clock_nsec / 1000000000;
1609 info_list->value->vm_clock_nsec = sn_tab[i].vm_clock_nsec % 1000000000;
1610
1611 /* XXX: waiting for the qapi to support qemu-queue.h types */
1612 if (!cur_item) {
1613 info->snapshots = cur_item = info_list;
1614 } else {
1615 cur_item->next = info_list;
1616 cur_item = info_list;
1617 }
1618
1619 }
1620
1621 g_free(sn_tab);
1622}
1623
1624static void dump_json_image_info(ImageInfo *info)
1625{
1626 Error *errp = NULL;
1627 QString *str;
1628 QmpOutputVisitor *ov = qmp_output_visitor_new();
1629 QObject *obj;
1630 visit_type_ImageInfo(qmp_output_get_visitor(ov),
1631 &info, NULL, &errp);
1632 obj = qmp_output_get_qobject(ov);
1633 str = qobject_to_json_pretty(obj);
1634 assert(str != NULL);
1635 printf("%s\n", qstring_get_str(str));
1636 qobject_decref(obj);
1637 qmp_output_visitor_cleanup(ov);
1638 QDECREF(str);
1639}
1640
1641static void collect_image_info(BlockDriverState *bs,
1642 ImageInfo *info,
1643 const char *filename,
1644 const char *fmt)
1645{
ths96b8f132007-12-17 01:35:20 +00001646 uint64_t total_sectors;
bellard93b6b2a2006-08-01 15:51:11 +00001647 char backing_filename[1024];
1648 char backing_filename2[1024];
bellardfaea38e2006-08-05 21:31:00 +00001649 BlockDriverInfo bdi;
bellardea2384d2004-08-01 21:59:26 +00001650
Benoît Canetc054b3f2012-09-05 13:09:02 +02001651 bdrv_get_geometry(bs, &total_sectors);
1652
1653 info->filename = g_strdup(filename);
1654 info->format = g_strdup(bdrv_get_format_name(bs));
1655 info->virtual_size = total_sectors * 512;
1656 info->actual_size = bdrv_get_allocated_file_size(bs);
1657 info->has_actual_size = info->actual_size >= 0;
1658 if (bdrv_is_encrypted(bs)) {
1659 info->encrypted = true;
1660 info->has_encrypted = true;
1661 }
1662 if (bdrv_get_info(bs, &bdi) >= 0) {
1663 if (bdi.cluster_size != 0) {
1664 info->cluster_size = bdi.cluster_size;
1665 info->has_cluster_size = true;
1666 }
1667 info->dirty_flag = bdi.is_dirty;
1668 info->has_dirty_flag = true;
1669 }
1670 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
1671 if (backing_filename[0] != '\0') {
1672 info->backing_filename = g_strdup(backing_filename);
1673 info->has_backing_filename = true;
1674 bdrv_get_full_backing_filename(bs, backing_filename2,
1675 sizeof(backing_filename2));
1676
1677 if (strcmp(backing_filename, backing_filename2) != 0) {
1678 info->full_backing_filename =
1679 g_strdup(backing_filename2);
1680 info->has_full_backing_filename = true;
1681 }
1682
1683 if (bs->backing_format[0]) {
1684 info->backing_filename_format = g_strdup(bs->backing_format);
1685 info->has_backing_filename_format = true;
1686 }
1687 }
1688}
1689
1690static void dump_human_image_info(ImageInfo *info)
1691{
1692 char size_buf[128], dsize_buf[128];
1693 if (!info->has_actual_size) {
1694 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
1695 } else {
1696 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
1697 info->actual_size);
1698 }
1699 get_human_readable_size(size_buf, sizeof(size_buf), info->virtual_size);
1700 printf("image: %s\n"
1701 "file format: %s\n"
1702 "virtual size: %s (%" PRId64 " bytes)\n"
1703 "disk size: %s\n",
1704 info->filename, info->format, size_buf,
1705 info->virtual_size,
1706 dsize_buf);
1707
1708 if (info->has_encrypted && info->encrypted) {
1709 printf("encrypted: yes\n");
1710 }
1711
1712 if (info->has_cluster_size) {
1713 printf("cluster_size: %" PRId64 "\n", info->cluster_size);
1714 }
1715
1716 if (info->has_dirty_flag && info->dirty_flag) {
1717 printf("cleanly shut down: no\n");
1718 }
1719
1720 if (info->has_backing_filename) {
1721 printf("backing file: %s", info->backing_filename);
1722 if (info->has_full_backing_filename) {
1723 printf(" (actual path: %s)", info->full_backing_filename);
1724 }
1725 putchar('\n');
1726 if (info->has_backing_filename_format) {
1727 printf("backing file format: %s\n", info->backing_filename_format);
1728 }
1729 }
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001730
1731 if (info->has_snapshots) {
1732 SnapshotInfoList *elem;
1733 char buf[256];
1734
1735 printf("Snapshot list:\n");
1736 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
1737
1738 /* Ideally bdrv_snapshot_dump() would operate on SnapshotInfoList but
1739 * we convert to the block layer's native QEMUSnapshotInfo for now.
1740 */
1741 for (elem = info->snapshots; elem; elem = elem->next) {
1742 QEMUSnapshotInfo sn = {
1743 .vm_state_size = elem->value->vm_state_size,
1744 .date_sec = elem->value->date_sec,
1745 .date_nsec = elem->value->date_nsec,
1746 .vm_clock_nsec = elem->value->vm_clock_sec * 1000000000ULL +
1747 elem->value->vm_clock_nsec,
1748 };
1749
1750 pstrcpy(sn.id_str, sizeof(sn.id_str), elem->value->id);
1751 pstrcpy(sn.name, sizeof(sn.name), elem->value->name);
1752 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), &sn));
1753 }
1754 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001755}
1756
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001757static void dump_human_image_info_list(ImageInfoList *list)
1758{
1759 ImageInfoList *elem;
1760 bool delim = false;
1761
1762 for (elem = list; elem; elem = elem->next) {
1763 if (delim) {
1764 printf("\n");
1765 }
1766 delim = true;
1767
1768 dump_human_image_info(elem->value);
1769 }
1770}
1771
1772static gboolean str_equal_func(gconstpointer a, gconstpointer b)
1773{
1774 return strcmp(a, b) == 0;
1775}
1776
1777/**
1778 * Open an image file chain and return an ImageInfoList
1779 *
1780 * @filename: topmost image filename
1781 * @fmt: topmost image format (may be NULL to autodetect)
1782 * @chain: true - enumerate entire backing file chain
1783 * false - only topmost image file
1784 *
1785 * Returns a list of ImageInfo objects or NULL if there was an error opening an
1786 * image file. If there was an error a message will have been printed to
1787 * stderr.
1788 */
1789static ImageInfoList *collect_image_info_list(const char *filename,
1790 const char *fmt,
1791 bool chain)
1792{
1793 ImageInfoList *head = NULL;
1794 ImageInfoList **last = &head;
1795 GHashTable *filenames;
1796
1797 filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
1798
1799 while (filename) {
1800 BlockDriverState *bs;
1801 ImageInfo *info;
1802 ImageInfoList *elem;
1803
1804 if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
1805 error_report("Backing file '%s' creates an infinite loop.",
1806 filename);
1807 goto err;
1808 }
1809 g_hash_table_insert(filenames, (gpointer)filename, NULL);
1810
1811 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001812 false, false);
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001813 if (!bs) {
1814 goto err;
1815 }
1816
1817 info = g_new0(ImageInfo, 1);
1818 collect_image_info(bs, info, filename, fmt);
1819 collect_snapshots(bs, info);
1820
1821 elem = g_new0(ImageInfoList, 1);
1822 elem->value = info;
1823 *last = elem;
1824 last = &elem->next;
1825
1826 bdrv_delete(bs);
1827
1828 filename = fmt = NULL;
1829 if (chain) {
1830 if (info->has_full_backing_filename) {
1831 filename = info->full_backing_filename;
1832 } else if (info->has_backing_filename) {
1833 filename = info->backing_filename;
1834 }
1835 if (info->has_backing_filename_format) {
1836 fmt = info->backing_filename_format;
1837 }
1838 }
1839 }
1840 g_hash_table_destroy(filenames);
1841 return head;
1842
1843err:
1844 qapi_free_ImageInfoList(head);
1845 g_hash_table_destroy(filenames);
1846 return NULL;
1847}
1848
Benoît Canetc054b3f2012-09-05 13:09:02 +02001849static int img_info(int argc, char **argv)
1850{
1851 int c;
1852 OutputFormat output_format = OFORMAT_HUMAN;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001853 bool chain = false;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001854 const char *filename, *fmt, *output;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001855 ImageInfoList *list;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001856
bellardea2384d2004-08-01 21:59:26 +00001857 fmt = NULL;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001858 output = NULL;
bellardea2384d2004-08-01 21:59:26 +00001859 for(;;) {
Benoît Canetc054b3f2012-09-05 13:09:02 +02001860 int option_index = 0;
1861 static const struct option long_options[] = {
1862 {"help", no_argument, 0, 'h'},
1863 {"format", required_argument, 0, 'f'},
1864 {"output", required_argument, 0, OPTION_OUTPUT},
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001865 {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
Benoît Canetc054b3f2012-09-05 13:09:02 +02001866 {0, 0, 0, 0}
1867 };
1868 c = getopt_long(argc, argv, "f:h",
1869 long_options, &option_index);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001870 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001871 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001872 }
bellardea2384d2004-08-01 21:59:26 +00001873 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001874 case '?':
bellardea2384d2004-08-01 21:59:26 +00001875 case 'h':
1876 help();
1877 break;
1878 case 'f':
1879 fmt = optarg;
1880 break;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001881 case OPTION_OUTPUT:
1882 output = optarg;
1883 break;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001884 case OPTION_BACKING_CHAIN:
1885 chain = true;
1886 break;
bellardea2384d2004-08-01 21:59:26 +00001887 }
1888 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001889 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +00001890 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001891 }
bellardea2384d2004-08-01 21:59:26 +00001892 filename = argv[optind++];
1893
Benoît Canetc054b3f2012-09-05 13:09:02 +02001894 if (output && !strcmp(output, "json")) {
1895 output_format = OFORMAT_JSON;
1896 } else if (output && !strcmp(output, "human")) {
1897 output_format = OFORMAT_HUMAN;
1898 } else if (output) {
1899 error_report("--output must be used with human or json as argument.");
1900 return 1;
1901 }
1902
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001903 list = collect_image_info_list(filename, fmt, chain);
1904 if (!list) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001905 return 1;
1906 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001907
Benoît Canetc054b3f2012-09-05 13:09:02 +02001908 switch (output_format) {
1909 case OFORMAT_HUMAN:
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001910 dump_human_image_info_list(list);
Benoît Canetc054b3f2012-09-05 13:09:02 +02001911 break;
1912 case OFORMAT_JSON:
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001913 if (chain) {
1914 dump_json_image_info_list(list);
1915 } else {
1916 dump_json_image_info(list->value);
1917 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001918 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001919 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001920
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001921 qapi_free_ImageInfoList(list);
bellardea2384d2004-08-01 21:59:26 +00001922 return 0;
1923}
1924
aliguorif7b4a942009-01-07 17:40:15 +00001925#define SNAPSHOT_LIST 1
1926#define SNAPSHOT_CREATE 2
1927#define SNAPSHOT_APPLY 3
1928#define SNAPSHOT_DELETE 4
1929
Stuart Brady153859b2009-06-07 00:42:17 +01001930static int img_snapshot(int argc, char **argv)
aliguorif7b4a942009-01-07 17:40:15 +00001931{
1932 BlockDriverState *bs;
1933 QEMUSnapshotInfo sn;
1934 char *filename, *snapshot_name = NULL;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001935 int c, ret = 0, bdrv_oflags;
aliguorif7b4a942009-01-07 17:40:15 +00001936 int action = 0;
1937 qemu_timeval tv;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001938 bool quiet = false;
aliguorif7b4a942009-01-07 17:40:15 +00001939
Kevin Wolf710da702011-01-10 12:33:02 +01001940 bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
aliguorif7b4a942009-01-07 17:40:15 +00001941 /* Parse commandline parameters */
1942 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001943 c = getopt(argc, argv, "la:c:d:hq");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001944 if (c == -1) {
aliguorif7b4a942009-01-07 17:40:15 +00001945 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001946 }
aliguorif7b4a942009-01-07 17:40:15 +00001947 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001948 case '?':
aliguorif7b4a942009-01-07 17:40:15 +00001949 case 'h':
1950 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001951 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001952 case 'l':
1953 if (action) {
1954 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001955 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001956 }
1957 action = SNAPSHOT_LIST;
Naphtali Spreif5edb012010-01-17 16:48:13 +02001958 bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
aliguorif7b4a942009-01-07 17:40:15 +00001959 break;
1960 case 'a':
1961 if (action) {
1962 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001963 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001964 }
1965 action = SNAPSHOT_APPLY;
1966 snapshot_name = optarg;
1967 break;
1968 case 'c':
1969 if (action) {
1970 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001971 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001972 }
1973 action = SNAPSHOT_CREATE;
1974 snapshot_name = optarg;
1975 break;
1976 case 'd':
1977 if (action) {
1978 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001979 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001980 }
1981 action = SNAPSHOT_DELETE;
1982 snapshot_name = optarg;
1983 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001984 case 'q':
1985 quiet = true;
1986 break;
aliguorif7b4a942009-01-07 17:40:15 +00001987 }
1988 }
1989
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001990 if (optind >= argc) {
aliguorif7b4a942009-01-07 17:40:15 +00001991 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001992 }
aliguorif7b4a942009-01-07 17:40:15 +00001993 filename = argv[optind++];
1994
1995 /* Open the image */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001996 bs = bdrv_new_open(filename, NULL, bdrv_oflags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001997 if (!bs) {
1998 return 1;
1999 }
aliguorif7b4a942009-01-07 17:40:15 +00002000
2001 /* Perform the requested action */
2002 switch(action) {
2003 case SNAPSHOT_LIST:
2004 dump_snapshots(bs);
2005 break;
2006
2007 case SNAPSHOT_CREATE:
2008 memset(&sn, 0, sizeof(sn));
2009 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
2010
2011 qemu_gettimeofday(&tv);
2012 sn.date_sec = tv.tv_sec;
2013 sn.date_nsec = tv.tv_usec * 1000;
2014
2015 ret = bdrv_snapshot_create(bs, &sn);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002016 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002017 error_report("Could not create snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00002018 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002019 }
aliguorif7b4a942009-01-07 17:40:15 +00002020 break;
2021
2022 case SNAPSHOT_APPLY:
2023 ret = bdrv_snapshot_goto(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002024 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002025 error_report("Could not apply snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00002026 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002027 }
aliguorif7b4a942009-01-07 17:40:15 +00002028 break;
2029
2030 case SNAPSHOT_DELETE:
2031 ret = bdrv_snapshot_delete(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002032 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002033 error_report("Could not delete snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00002034 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002035 }
aliguorif7b4a942009-01-07 17:40:15 +00002036 break;
2037 }
2038
2039 /* Cleanup */
2040 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002041 if (ret) {
2042 return 1;
2043 }
Stuart Brady153859b2009-06-07 00:42:17 +01002044 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00002045}
2046
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002047static int img_rebase(int argc, char **argv)
2048{
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002049 BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
Stefan Hajnoczif163d072010-04-13 10:29:34 +01002050 BlockDriver *old_backing_drv, *new_backing_drv;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002051 char *filename;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04002052 const char *fmt, *cache, *out_basefmt, *out_baseimg;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002053 int c, flags, ret;
2054 int unsafe = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002055 int progress = 0;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002056 bool quiet = false;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002057
2058 /* Parse commandline parameters */
Kevin Wolfe53dbee2010-03-02 12:14:31 +01002059 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04002060 cache = BDRV_DEFAULT_CACHE;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002061 out_baseimg = NULL;
2062 out_basefmt = NULL;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002063 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002064 c = getopt(argc, argv, "uhf:F:b:pt:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002065 if (c == -1) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002066 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002067 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002068 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01002069 case '?':
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002070 case 'h':
2071 help();
2072 return 0;
Kevin Wolfe53dbee2010-03-02 12:14:31 +01002073 case 'f':
2074 fmt = optarg;
2075 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002076 case 'F':
2077 out_basefmt = optarg;
2078 break;
2079 case 'b':
2080 out_baseimg = optarg;
2081 break;
2082 case 'u':
2083 unsafe = 1;
2084 break;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002085 case 'p':
2086 progress = 1;
2087 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04002088 case 't':
2089 cache = optarg;
2090 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002091 case 'q':
2092 quiet = true;
2093 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002094 }
2095 }
2096
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002097 if (quiet) {
2098 progress = 0;
2099 }
2100
Anthony Liguori9a9d9db2011-04-13 15:51:47 +01002101 if ((optind >= argc) || (!unsafe && !out_baseimg)) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002102 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01002103 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002104 filename = argv[optind++];
2105
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002106 qemu_progress_init(progress, 2.0);
2107 qemu_progress_print(0, 100);
2108
Federico Simoncelli661a0f72011-06-20 12:48:19 -04002109 flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +01002110 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -04002111 if (ret < 0) {
2112 error_report("Invalid cache option: %s", cache);
2113 return -1;
2114 }
2115
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002116 /*
2117 * Open the images.
2118 *
2119 * Ignore the old backing file for unsafe rebase in case we want to correct
2120 * the reference to a renamed or moved backing file.
2121 */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002122 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002123 if (!bs) {
2124 return 1;
2125 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002126
2127 /* Find the right drivers for the backing files */
2128 old_backing_drv = NULL;
2129 new_backing_drv = NULL;
2130
2131 if (!unsafe && bs->backing_format[0] != '\0') {
2132 old_backing_drv = bdrv_find_format(bs->backing_format);
2133 if (old_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002134 error_report("Invalid format name: '%s'", bs->backing_format);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002135 ret = -1;
2136 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002137 }
2138 }
2139
2140 if (out_basefmt != NULL) {
2141 new_backing_drv = bdrv_find_format(out_basefmt);
2142 if (new_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002143 error_report("Invalid format name: '%s'", out_basefmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002144 ret = -1;
2145 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002146 }
2147 }
2148
2149 /* For safe rebasing we need to compare old and new backing file */
2150 if (unsafe) {
2151 /* Make the compiler happy */
2152 bs_old_backing = NULL;
2153 bs_new_backing = NULL;
2154 } else {
2155 char backing_name[1024];
2156
2157 bs_old_backing = bdrv_new("old_backing");
2158 bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
Kevin Wolfde9c0ce2013-03-15 10:35:02 +01002159 ret = bdrv_open(bs_old_backing, backing_name, NULL, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002160 old_backing_drv);
2161 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002162 error_report("Could not open old backing file '%s'", backing_name);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002163 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002164 }
Alex Bligha6166732012-10-16 13:46:18 +01002165 if (out_baseimg[0]) {
2166 bs_new_backing = bdrv_new("new_backing");
Kevin Wolfde9c0ce2013-03-15 10:35:02 +01002167 ret = bdrv_open(bs_new_backing, out_baseimg, NULL, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002168 new_backing_drv);
Alex Bligha6166732012-10-16 13:46:18 +01002169 if (ret) {
2170 error_report("Could not open new backing file '%s'",
2171 out_baseimg);
2172 goto out;
2173 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002174 }
2175 }
2176
2177 /*
2178 * Check each unallocated cluster in the COW file. If it is unallocated,
2179 * accesses go to the backing file. We must therefore compare this cluster
2180 * in the old and new backing file, and if they differ we need to copy it
2181 * from the old backing file into the COW file.
2182 *
2183 * If qemu-img crashes during this step, no harm is done. The content of
2184 * the image is the same as the original one at any time.
2185 */
2186 if (!unsafe) {
2187 uint64_t num_sectors;
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002188 uint64_t old_backing_num_sectors;
Alex Bligha6166732012-10-16 13:46:18 +01002189 uint64_t new_backing_num_sectors = 0;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002190 uint64_t sector;
Kevin Wolfcc60e322010-04-29 14:47:48 +02002191 int n;
TeLeMand6771bf2010-02-08 16:20:00 +08002192 uint8_t * buf_old;
2193 uint8_t * buf_new;
Kevin Wolf1f710492012-10-12 14:29:18 +02002194 float local_progress = 0;
TeLeMand6771bf2010-02-08 16:20:00 +08002195
Kevin Wolfbb1c0592011-08-08 14:09:12 +02002196 buf_old = qemu_blockalign(bs, IO_BUF_SIZE);
2197 buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002198
2199 bdrv_get_geometry(bs, &num_sectors);
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002200 bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
Alex Bligha6166732012-10-16 13:46:18 +01002201 if (bs_new_backing) {
2202 bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
2203 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002204
Kevin Wolf1f710492012-10-12 14:29:18 +02002205 if (num_sectors != 0) {
2206 local_progress = (float)100 /
2207 (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
2208 }
2209
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002210 for (sector = 0; sector < num_sectors; sector += n) {
2211
2212 /* How many sectors can we handle with the next read? */
2213 if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
2214 n = (IO_BUF_SIZE / 512);
2215 } else {
2216 n = num_sectors - sector;
2217 }
2218
2219 /* If the cluster is allocated, we don't need to take action */
Kevin Wolfcc60e322010-04-29 14:47:48 +02002220 ret = bdrv_is_allocated(bs, sector, n, &n);
2221 if (ret) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002222 continue;
2223 }
2224
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002225 /*
2226 * Read old and new backing file and take into consideration that
2227 * backing files may be smaller than the COW image.
2228 */
2229 if (sector >= old_backing_num_sectors) {
2230 memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
2231 } else {
2232 if (sector + n > old_backing_num_sectors) {
2233 n = old_backing_num_sectors - sector;
2234 }
2235
2236 ret = bdrv_read(bs_old_backing, sector, buf_old, n);
2237 if (ret < 0) {
2238 error_report("error while reading from old backing file");
2239 goto out;
2240 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002241 }
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002242
Alex Bligha6166732012-10-16 13:46:18 +01002243 if (sector >= new_backing_num_sectors || !bs_new_backing) {
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002244 memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
2245 } else {
2246 if (sector + n > new_backing_num_sectors) {
2247 n = new_backing_num_sectors - sector;
2248 }
2249
2250 ret = bdrv_read(bs_new_backing, sector, buf_new, n);
2251 if (ret < 0) {
2252 error_report("error while reading from new backing file");
2253 goto out;
2254 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002255 }
2256
2257 /* If they differ, we need to write to the COW file */
2258 uint64_t written = 0;
2259
2260 while (written < n) {
2261 int pnum;
2262
2263 if (compare_sectors(buf_old + written * 512,
Kevin Wolf60b1bd42010-02-17 12:32:59 +01002264 buf_new + written * 512, n - written, &pnum))
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002265 {
2266 ret = bdrv_write(bs, sector + written,
2267 buf_old + written * 512, pnum);
2268 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002269 error_report("Error while writing to COW image: %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002270 strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002271 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002272 }
2273 }
2274
2275 written += pnum;
2276 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002277 qemu_progress_print(local_progress, 100);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002278 }
TeLeMand6771bf2010-02-08 16:20:00 +08002279
Kevin Wolfbb1c0592011-08-08 14:09:12 +02002280 qemu_vfree(buf_old);
2281 qemu_vfree(buf_new);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002282 }
2283
2284 /*
2285 * Change the backing file. All clusters that are different from the old
2286 * backing file are overwritten in the COW file now, so the visible content
2287 * doesn't change when we switch the backing file.
2288 */
Alex Bligha6166732012-10-16 13:46:18 +01002289 if (out_baseimg && *out_baseimg) {
2290 ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
2291 } else {
2292 ret = bdrv_change_backing_file(bs, NULL, NULL);
2293 }
2294
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002295 if (ret == -ENOSPC) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002296 error_report("Could not change the backing file to '%s': No "
2297 "space left in the file header", out_baseimg);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002298 } else if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002299 error_report("Could not change the backing file to '%s': %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002300 out_baseimg, strerror(-ret));
2301 }
2302
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002303 qemu_progress_print(100, 0);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002304 /*
2305 * TODO At this point it is possible to check if any clusters that are
2306 * allocated in the COW file are the same in the backing file. If so, they
2307 * could be dropped from the COW file. Don't do this before switching the
2308 * backing file, in case of a crash this would lead to corruption.
2309 */
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002310out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002311 qemu_progress_end();
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002312 /* Cleanup */
2313 if (!unsafe) {
Kevin Wolfeb863ad2011-03-31 12:39:51 +02002314 if (bs_old_backing != NULL) {
2315 bdrv_delete(bs_old_backing);
2316 }
2317 if (bs_new_backing != NULL) {
2318 bdrv_delete(bs_new_backing);
2319 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002320 }
2321
2322 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002323 if (ret) {
2324 return 1;
2325 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002326 return 0;
2327}
2328
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002329static int img_resize(int argc, char **argv)
2330{
2331 int c, ret, relative;
2332 const char *filename, *fmt, *size;
2333 int64_t n, total_size;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002334 bool quiet = false;
Jes Sorensen2a819982010-12-06 17:08:31 +01002335 BlockDriverState *bs = NULL;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002336 QemuOpts *param;
2337 static QemuOptsList resize_options = {
2338 .name = "resize_options",
2339 .head = QTAILQ_HEAD_INITIALIZER(resize_options.head),
2340 .desc = {
2341 {
2342 .name = BLOCK_OPT_SIZE,
2343 .type = QEMU_OPT_SIZE,
2344 .help = "Virtual disk size"
2345 }, {
2346 /* end of list */
2347 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002348 },
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002349 };
2350
Kevin Wolfe80fec72011-04-29 10:58:12 +02002351 /* Remove size from argv manually so that negative numbers are not treated
2352 * as options by getopt. */
2353 if (argc < 3) {
2354 help();
2355 return 1;
2356 }
2357
2358 size = argv[--argc];
2359
2360 /* Parse getopt arguments */
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002361 fmt = NULL;
2362 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002363 c = getopt(argc, argv, "f:hq");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002364 if (c == -1) {
2365 break;
2366 }
2367 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01002368 case '?':
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002369 case 'h':
2370 help();
2371 break;
2372 case 'f':
2373 fmt = optarg;
2374 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002375 case 'q':
2376 quiet = true;
2377 break;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002378 }
2379 }
Kevin Wolfe80fec72011-04-29 10:58:12 +02002380 if (optind >= argc) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002381 help();
2382 }
2383 filename = argv[optind++];
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002384
2385 /* Choose grow, shrink, or absolute resize mode */
2386 switch (size[0]) {
2387 case '+':
2388 relative = 1;
2389 size++;
2390 break;
2391 case '-':
2392 relative = -1;
2393 size++;
2394 break;
2395 default:
2396 relative = 0;
2397 break;
2398 }
2399
2400 /* Parse size */
Dong Xu Wange478b442012-12-06 14:47:22 +08002401 param = qemu_opts_create_nofail(&resize_options);
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002402 if (qemu_opt_set(param, BLOCK_OPT_SIZE, size)) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002403 /* Error message already printed when size parsing fails */
Jes Sorensen2a819982010-12-06 17:08:31 +01002404 ret = -1;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002405 qemu_opts_del(param);
Jes Sorensen2a819982010-12-06 17:08:31 +01002406 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002407 }
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002408 n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
2409 qemu_opts_del(param);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002410
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002411 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002412 if (!bs) {
Jes Sorensen2a819982010-12-06 17:08:31 +01002413 ret = -1;
2414 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002415 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002416
2417 if (relative) {
2418 total_size = bdrv_getlength(bs) + n * relative;
2419 } else {
2420 total_size = n;
2421 }
2422 if (total_size <= 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002423 error_report("New image size must be positive");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002424 ret = -1;
2425 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002426 }
2427
2428 ret = bdrv_truncate(bs, total_size);
2429 switch (ret) {
2430 case 0:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002431 qprintf(quiet, "Image resized.\n");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002432 break;
2433 case -ENOTSUP:
Kevin Wolf259b2172012-03-06 12:44:45 +01002434 error_report("This image does not support resize");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002435 break;
2436 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +01002437 error_report("Image is read-only");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002438 break;
2439 default:
Jes Sorensen15654a62010-12-16 14:31:53 +01002440 error_report("Error resizing image (%d)", -ret);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002441 break;
2442 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002443out:
Jes Sorensen2a819982010-12-06 17:08:31 +01002444 if (bs) {
2445 bdrv_delete(bs);
2446 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002447 if (ret) {
2448 return 1;
2449 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002450 return 0;
2451}
2452
Anthony Liguoric227f092009-10-01 16:12:16 -05002453static const img_cmd_t img_cmds[] = {
Stuart Brady153859b2009-06-07 00:42:17 +01002454#define DEF(option, callback, arg_string) \
2455 { option, callback },
2456#include "qemu-img-cmds.h"
2457#undef DEF
2458#undef GEN_DOCS
2459 { NULL, NULL, },
2460};
2461
bellardea2384d2004-08-01 21:59:26 +00002462int main(int argc, char **argv)
2463{
Anthony Liguoric227f092009-10-01 16:12:16 -05002464 const img_cmd_t *cmd;
Stuart Brady153859b2009-06-07 00:42:17 +01002465 const char *cmdname;
bellardea2384d2004-08-01 21:59:26 +00002466
Kevin Wolf53f76e52010-12-16 15:10:32 +01002467 error_set_progname(argv[0]);
2468
Paolo Bonzini2592c592012-11-03 18:10:17 +01002469 qemu_init_main_loop();
bellardea2384d2004-08-01 21:59:26 +00002470 bdrv_init();
2471 if (argc < 2)
2472 help();
Stuart Brady153859b2009-06-07 00:42:17 +01002473 cmdname = argv[1];
aurel328f9b1572009-02-09 18:14:31 +00002474 argc--; argv++;
Stuart Brady153859b2009-06-07 00:42:17 +01002475
2476 /* find the command */
2477 for(cmd = img_cmds; cmd->name != NULL; cmd++) {
2478 if (!strcmp(cmdname, cmd->name)) {
2479 return cmd->handler(argc, argv);
2480 }
bellardea2384d2004-08-01 21:59:26 +00002481 }
Stuart Brady153859b2009-06-07 00:42:17 +01002482
2483 /* not found */
2484 help();
bellardea2384d2004-08-01 21:59:26 +00002485 return 0;
2486}