blob: 82c7977353799eed497e1199f85dc7302493848e [file] [log] [blame]
bellardea2384d2004-08-01 21:59:26 +00001/*
bellardfb43f4d2006-08-07 21:34:46 +00002 * QEMU disk image utility
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard68d0f702008-01-06 17:21:48 +00004 * Copyright (c) 2003-2008 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
bellardea2384d2004-08-01 21:59:26 +00006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
Benoît Canetc054b3f2012-09-05 13:09:02 +020024#include "qapi-visit.h"
25#include "qapi/qmp-output-visitor.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010026#include "qapi/qmp/qjson.h"
pbrookfaf07962007-11-11 02:51:17 +000027#include "qemu-common.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010028#include "qemu/option.h"
29#include "qemu/error-report.h"
30#include "qemu/osdep.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010031#include "sysemu/sysemu.h"
Paolo Bonzini737e1502012-12-17 18:19:44 +010032#include "block/block_int.h"
Wenchao Xiaf364ec62013-05-25 11:09:44 +080033#include "block/qapi.h"
Benoît Canetc054b3f2012-09-05 13:09:02 +020034#include <getopt.h>
aliguori9230eaf2009-03-28 17:55:19 +000035#include <stdio.h>
Miroslav Rezaninaf382d432013-02-13 09:09:40 +010036#include <stdarg.h>
bellardea2384d2004-08-01 21:59:26 +000037
bellarde8445332006-06-14 15:32:10 +000038#ifdef _WIN32
39#include <windows.h>
40#endif
41
Anthony Liguoric227f092009-10-01 16:12:16 -050042typedef struct img_cmd_t {
Stuart Brady153859b2009-06-07 00:42:17 +010043 const char *name;
44 int (*handler)(int argc, char **argv);
Anthony Liguoric227f092009-10-01 16:12:16 -050045} img_cmd_t;
Stuart Brady153859b2009-06-07 00:42:17 +010046
Federico Simoncelli8599ea42013-01-28 06:59:47 -050047enum {
48 OPTION_OUTPUT = 256,
49 OPTION_BACKING_CHAIN = 257,
50};
51
52typedef enum OutputFormat {
53 OFORMAT_JSON,
54 OFORMAT_HUMAN,
55} OutputFormat;
56
aurel32137519c2008-11-30 19:12:49 +000057/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
Stefan Hajnocziadfe0782010-04-13 10:29:35 +010058#define BDRV_O_FLAGS BDRV_O_CACHE_WB
Federico Simoncelli661a0f72011-06-20 12:48:19 -040059#define BDRV_DEFAULT_CACHE "writeback"
aurel32137519c2008-11-30 19:12:49 +000060
bellardea2384d2004-08-01 21:59:26 +000061static void format_print(void *opaque, const char *name)
62{
63 printf(" %s", name);
64}
65
blueswir1d2c639d2009-01-24 18:19:25 +000066/* Please keep in synch with qemu-img.texi */
pbrook3f379ab2007-11-11 03:33:13 +000067static void help(void)
bellardea2384d2004-08-01 21:59:26 +000068{
Paolo Bonzinie00291c2010-02-04 16:49:56 +010069 const char *help_msg =
70 "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
malc3f020d72010-02-08 12:04:56 +030071 "usage: qemu-img command [command options]\n"
72 "QEMU disk image utility\n"
73 "\n"
74 "Command syntax:\n"
Stuart Brady153859b2009-06-07 00:42:17 +010075#define DEF(option, callback, arg_string) \
76 " " arg_string "\n"
77#include "qemu-img-cmds.h"
78#undef DEF
79#undef GEN_DOCS
malc3f020d72010-02-08 12:04:56 +030080 "\n"
81 "Command parameters:\n"
82 " 'filename' is a disk image filename\n"
83 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
Federico Simoncelli661a0f72011-06-20 12:48:19 -040084 " 'cache' is the cache mode used to write the output disk image, the valid\n"
Liu Yuan80ccf932012-04-20 17:10:56 +080085 " options are: 'none', 'writeback' (default, except for convert), 'writethrough',\n"
86 " 'directsync' and 'unsafe' (default for convert)\n"
malc3f020d72010-02-08 12:04:56 +030087 " 'size' is the disk image size in bytes. Optional suffixes\n"
88 " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
89 " and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
90 " 'output_filename' is the destination disk image filename\n"
91 " 'output_fmt' is the destination format\n"
92 " 'options' is a comma separated list of format specific options in a\n"
93 " name=value format. Use -o ? for an overview of the options supported by the\n"
94 " used format\n"
95 " '-c' indicates that target image must be compressed (qcow format only)\n"
96 " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
97 " match exactly. The image doesn't need a working backing file before\n"
98 " rebasing in this case (useful for renaming the backing file)\n"
99 " '-h' with or without a command shows this help and lists the supported formats\n"
Jes Sorensen6b837bc2011-03-30 14:16:25 +0200100 " '-p' show progress of command (only certain commands)\n"
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100101 " '-q' use Quiet mode - do not print any output (except errors)\n"
Kevin Wolfa22f1232011-08-26 15:27:13 +0200102 " '-S' indicates the consecutive number of bytes that must contain only zeros\n"
103 " for qemu-img to create a sparse image during conversion\n"
Benoît Canetc054b3f2012-09-05 13:09:02 +0200104 " '--output' takes the format in which the output must be done (human or json)\n"
malc3f020d72010-02-08 12:04:56 +0300105 "\n"
Kevin Wolf4534ff52012-05-11 16:07:02 +0200106 "Parameters to check subcommand:\n"
107 " '-r' tries to repair any inconsistencies that are found during the check.\n"
108 " '-r leaks' repairs only cluster leaks, whereas '-r all' fixes all\n"
109 " kinds of errors, with a higher risk of choosing the wrong fix or\n"
Stefan Weil0546b8c2012-08-10 22:03:25 +0200110 " hiding corruption that has already occurred.\n"
Kevin Wolf4534ff52012-05-11 16:07:02 +0200111 "\n"
malc3f020d72010-02-08 12:04:56 +0300112 "Parameters to snapshot subcommand:\n"
113 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
114 " '-a' applies a snapshot (revert disk to saved state)\n"
115 " '-c' creates a snapshot\n"
116 " '-d' deletes a snapshot\n"
Miroslav Rezaninad14ed182013-02-13 09:09:41 +0100117 " '-l' lists all snapshots in the given image\n"
118 "\n"
119 "Parameters to compare subcommand:\n"
120 " '-f' first image format\n"
121 " '-F' second image format\n"
122 " '-s' run in Strict mode - fail on different image size or sector allocation\n";
Paolo Bonzinie00291c2010-02-04 16:49:56 +0100123
124 printf("%s\nSupported formats:", help_msg);
bellardea2384d2004-08-01 21:59:26 +0000125 bdrv_iterate_format(format_print, NULL);
126 printf("\n");
127 exit(1);
128}
129
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100130static int qprintf(bool quiet, const char *fmt, ...)
131{
132 int ret = 0;
133 if (!quiet) {
134 va_list args;
135 va_start(args, fmt);
136 ret = vprintf(fmt, args);
137 va_end(args);
138 }
139 return ret;
140}
141
bellardea2384d2004-08-01 21:59:26 +0000142#if defined(WIN32)
143/* XXX: put correct support for win32 */
144static int read_password(char *buf, int buf_size)
145{
146 int c, i;
147 printf("Password: ");
148 fflush(stdout);
149 i = 0;
150 for(;;) {
151 c = getchar();
152 if (c == '\n')
153 break;
154 if (i < (buf_size - 1))
155 buf[i++] = c;
156 }
157 buf[i] = '\0';
158 return 0;
159}
160
161#else
162
163#include <termios.h>
164
165static struct termios oldtty;
166
167static void term_exit(void)
168{
169 tcsetattr (0, TCSANOW, &oldtty);
170}
171
172static void term_init(void)
173{
174 struct termios tty;
175
176 tcgetattr (0, &tty);
177 oldtty = tty;
178
179 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
180 |INLCR|IGNCR|ICRNL|IXON);
181 tty.c_oflag |= OPOST;
182 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
183 tty.c_cflag &= ~(CSIZE|PARENB);
184 tty.c_cflag |= CS8;
185 tty.c_cc[VMIN] = 1;
186 tty.c_cc[VTIME] = 0;
ths3b46e622007-09-17 08:09:54 +0000187
bellardea2384d2004-08-01 21:59:26 +0000188 tcsetattr (0, TCSANOW, &tty);
189
190 atexit(term_exit);
191}
192
pbrook3f379ab2007-11-11 03:33:13 +0000193static int read_password(char *buf, int buf_size)
bellardea2384d2004-08-01 21:59:26 +0000194{
195 uint8_t ch;
196 int i, ret;
197
198 printf("password: ");
199 fflush(stdout);
200 term_init();
201 i = 0;
202 for(;;) {
203 ret = read(0, &ch, 1);
204 if (ret == -1) {
205 if (errno == EAGAIN || errno == EINTR) {
206 continue;
207 } else {
208 ret = -1;
209 break;
210 }
211 } else if (ret == 0) {
212 ret = -1;
213 break;
214 } else {
215 if (ch == '\r') {
216 ret = 0;
217 break;
218 }
219 if (i < (buf_size - 1))
220 buf[i++] = ch;
221 }
222 }
223 term_exit();
224 buf[i] = '\0';
225 printf("\n");
226 return ret;
227}
228#endif
229
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100230static int print_block_option_help(const char *filename, const char *fmt)
231{
232 BlockDriver *drv, *proto_drv;
233 QEMUOptionParameter *create_options = NULL;
234
235 /* Find driver and parse its options */
236 drv = bdrv_find_format(fmt);
237 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100238 error_report("Unknown file format '%s'", fmt);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100239 return 1;
240 }
241
242 proto_drv = bdrv_find_protocol(filename);
243 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100244 error_report("Unknown protocol '%s'", filename);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100245 return 1;
246 }
247
248 create_options = append_option_parameters(create_options,
249 drv->create_options);
250 create_options = append_option_parameters(create_options,
251 proto_drv->create_options);
252 print_option_help(create_options);
253 free_option_parameters(create_options);
254 return 0;
255}
256
bellard75c23802004-08-27 21:28:58 +0000257static BlockDriverState *bdrv_new_open(const char *filename,
Sheng Yang9bc378c2010-01-29 10:15:06 +0800258 const char *fmt,
Daniel P. Berrangef0536bb2012-09-10 12:11:31 +0100259 int flags,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100260 bool require_io,
261 bool quiet)
bellard75c23802004-08-27 21:28:58 +0000262{
263 BlockDriverState *bs;
264 BlockDriver *drv;
265 char password[256];
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100266 int ret;
bellard75c23802004-08-27 21:28:58 +0000267
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100268 bs = bdrv_new("image");
Kevin Wolfad717132010-12-16 15:37:41 +0100269
bellard75c23802004-08-27 21:28:58 +0000270 if (fmt) {
271 drv = bdrv_find_format(fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900272 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100273 error_report("Unknown file format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900274 goto fail;
275 }
bellard75c23802004-08-27 21:28:58 +0000276 } else {
277 drv = NULL;
278 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100279
Kevin Wolfde9c0ce2013-03-15 10:35:02 +0100280 ret = bdrv_open(bs, filename, NULL, flags, drv);
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100281 if (ret < 0) {
282 error_report("Could not open '%s': %s", filename, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900283 goto fail;
bellard75c23802004-08-27 21:28:58 +0000284 }
Kevin Wolfb9eaf9e2011-02-09 11:25:53 +0100285
Daniel P. Berrangef0536bb2012-09-10 12:11:31 +0100286 if (bdrv_is_encrypted(bs) && require_io) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100287 qprintf(quiet, "Disk image '%s' is encrypted.\n", filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900288 if (read_password(password, sizeof(password)) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100289 error_report("No password given");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900290 goto fail;
291 }
292 if (bdrv_set_key(bs, password) < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100293 error_report("invalid password");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900294 goto fail;
295 }
bellard75c23802004-08-27 21:28:58 +0000296 }
297 return bs;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900298fail:
299 if (bs) {
300 bdrv_delete(bs);
301 }
302 return NULL;
bellard75c23802004-08-27 21:28:58 +0000303}
304
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900305static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
Jes Sorenseneec77d92010-12-07 17:44:34 +0100306 const char *base_filename,
307 const char *base_fmt)
Kevin Wolfefa84d42009-05-18 16:42:12 +0200308{
Kevin Wolfefa84d42009-05-18 16:42:12 +0200309 if (base_filename) {
310 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100311 error_report("Backing file not supported for file format '%s'",
312 fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900313 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200314 }
315 }
316 if (base_fmt) {
317 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
Jes Sorensen15654a62010-12-16 14:31:53 +0100318 error_report("Backing file format not supported for file "
319 "format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900320 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200321 }
322 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900323 return 0;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200324}
325
bellardea2384d2004-08-01 21:59:26 +0000326static int img_create(int argc, char **argv)
327{
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200328 int c;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100329 uint64_t img_size = -1;
bellardea2384d2004-08-01 21:59:26 +0000330 const char *fmt = "raw";
aliguori9230eaf2009-03-28 17:55:19 +0000331 const char *base_fmt = NULL;
bellardea2384d2004-08-01 21:59:26 +0000332 const char *filename;
333 const char *base_filename = NULL;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200334 char *options = NULL;
Luiz Capitulino9b375252012-11-30 10:52:05 -0200335 Error *local_err = NULL;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100336 bool quiet = false;
ths3b46e622007-09-17 08:09:54 +0000337
bellardea2384d2004-08-01 21:59:26 +0000338 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100339 c = getopt(argc, argv, "F:b:f:he6o:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100340 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000341 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100342 }
bellardea2384d2004-08-01 21:59:26 +0000343 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100344 case '?':
bellardea2384d2004-08-01 21:59:26 +0000345 case 'h':
346 help();
347 break;
aliguori9230eaf2009-03-28 17:55:19 +0000348 case 'F':
349 base_fmt = optarg;
350 break;
bellardea2384d2004-08-01 21:59:26 +0000351 case 'b':
352 base_filename = optarg;
353 break;
354 case 'f':
355 fmt = optarg;
356 break;
357 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200358 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100359 "encryption\' instead!");
360 return 1;
thsd8871c52007-10-24 16:11:42 +0000361 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +0200362 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +0100363 "compat6\' instead!");
364 return 1;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200365 case 'o':
366 options = optarg;
367 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100368 case 'q':
369 quiet = true;
370 break;
bellardea2384d2004-08-01 21:59:26 +0000371 }
372 }
aliguori9230eaf2009-03-28 17:55:19 +0000373
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900374 /* Get the filename */
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100375 if (optind >= argc) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900376 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100377 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900378 filename = argv[optind++];
379
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100380 /* Get image size, if specified */
381 if (optind < argc) {
Jes Sorensen70b4f4b2011-01-05 11:41:02 +0100382 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +0100383 char *end;
384 sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
385 if (sval < 0 || *end) {
liguang79443392012-12-17 09:49:23 +0800386 if (sval == -ERANGE) {
387 error_report("Image size must be less than 8 EiB!");
388 } else {
389 error_report("Invalid image size specified! You may use k, M, "
390 "G or T suffixes for ");
391 error_report("kilobytes, megabytes, gigabytes and terabytes.");
392 }
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200393 return 1;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100394 }
395 img_size = (uint64_t)sval;
396 }
397
Peter Maydellc8057f92012-08-02 13:45:54 +0100398 if (options && is_help_option(options)) {
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200399 return print_block_option_help(filename, fmt);
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100400 }
401
Luiz Capitulino9b375252012-11-30 10:52:05 -0200402 bdrv_img_create(filename, fmt, base_filename, base_fmt,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100403 options, img_size, BDRV_O_FLAGS, &local_err, quiet);
Luiz Capitulino9b375252012-11-30 10:52:05 -0200404 if (error_is_set(&local_err)) {
405 error_report("%s", error_get_pretty(local_err));
406 error_free(local_err);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900407 return 1;
408 }
Luiz Capitulinoa9300912012-11-30 10:52:06 -0200409
bellardea2384d2004-08-01 21:59:26 +0000410 return 0;
411}
412
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100413static void dump_json_image_check(ImageCheck *check, bool quiet)
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500414{
415 Error *errp = NULL;
416 QString *str;
417 QmpOutputVisitor *ov = qmp_output_visitor_new();
418 QObject *obj;
419 visit_type_ImageCheck(qmp_output_get_visitor(ov),
420 &check, NULL, &errp);
421 obj = qmp_output_get_qobject(ov);
422 str = qobject_to_json_pretty(obj);
423 assert(str != NULL);
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100424 qprintf(quiet, "%s\n", qstring_get_str(str));
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500425 qobject_decref(obj);
426 qmp_output_visitor_cleanup(ov);
427 QDECREF(str);
428}
429
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100430static void dump_human_image_check(ImageCheck *check, bool quiet)
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500431{
432 if (!(check->corruptions || check->leaks || check->check_errors)) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100433 qprintf(quiet, "No errors were found on the image.\n");
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500434 } else {
435 if (check->corruptions) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100436 qprintf(quiet, "\n%" PRId64 " errors were found on the image.\n"
437 "Data may be corrupted, or further writes to the image "
438 "may corrupt it.\n",
439 check->corruptions);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500440 }
441
442 if (check->leaks) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100443 qprintf(quiet,
444 "\n%" PRId64 " leaked clusters were found on the image.\n"
445 "This means waste of disk space, but no harm to data.\n",
446 check->leaks);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500447 }
448
449 if (check->check_errors) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100450 qprintf(quiet,
451 "\n%" PRId64
452 " internal errors have occurred during the check.\n",
453 check->check_errors);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500454 }
455 }
456
457 if (check->total_clusters != 0 && check->allocated_clusters != 0) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100458 qprintf(quiet, "%" PRId64 "/%" PRId64 " = %0.2f%% allocated, "
459 "%0.2f%% fragmented, %0.2f%% compressed clusters\n",
460 check->allocated_clusters, check->total_clusters,
461 check->allocated_clusters * 100.0 / check->total_clusters,
462 check->fragmented_clusters * 100.0 / check->allocated_clusters,
463 check->compressed_clusters * 100.0 /
464 check->allocated_clusters);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500465 }
466
467 if (check->image_end_offset) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100468 qprintf(quiet,
469 "Image end offset: %" PRId64 "\n", check->image_end_offset);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500470 }
471}
472
473static int collect_image_check(BlockDriverState *bs,
474 ImageCheck *check,
475 const char *filename,
476 const char *fmt,
477 int fix)
478{
479 int ret;
480 BdrvCheckResult result;
481
482 ret = bdrv_check(bs, &result, fix);
483 if (ret < 0) {
484 return ret;
485 }
486
487 check->filename = g_strdup(filename);
488 check->format = g_strdup(bdrv_get_format_name(bs));
489 check->check_errors = result.check_errors;
490 check->corruptions = result.corruptions;
491 check->has_corruptions = result.corruptions != 0;
492 check->leaks = result.leaks;
493 check->has_leaks = result.leaks != 0;
494 check->corruptions_fixed = result.corruptions_fixed;
495 check->has_corruptions_fixed = result.corruptions != 0;
496 check->leaks_fixed = result.leaks_fixed;
497 check->has_leaks_fixed = result.leaks != 0;
498 check->image_end_offset = result.image_end_offset;
499 check->has_image_end_offset = result.image_end_offset != 0;
500 check->total_clusters = result.bfi.total_clusters;
501 check->has_total_clusters = result.bfi.total_clusters != 0;
502 check->allocated_clusters = result.bfi.allocated_clusters;
503 check->has_allocated_clusters = result.bfi.allocated_clusters != 0;
504 check->fragmented_clusters = result.bfi.fragmented_clusters;
505 check->has_fragmented_clusters = result.bfi.fragmented_clusters != 0;
Stefan Hajnoczie6439d72013-02-07 17:15:04 +0100506 check->compressed_clusters = result.bfi.compressed_clusters;
507 check->has_compressed_clusters = result.bfi.compressed_clusters != 0;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500508
509 return 0;
510}
511
Kevin Wolfe076f332010-06-29 11:43:13 +0200512/*
513 * Checks an image for consistency. Exit codes:
514 *
515 * 0 - Check completed, image is good
516 * 1 - Check not completed because of internal errors
517 * 2 - Check completed, image is corrupted
518 * 3 - Check completed, image has leaked clusters, but is good otherwise
519 */
aliguori15859692009-04-21 23:11:53 +0000520static int img_check(int argc, char **argv)
521{
522 int c, ret;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500523 OutputFormat output_format = OFORMAT_HUMAN;
524 const char *filename, *fmt, *output;
aliguori15859692009-04-21 23:11:53 +0000525 BlockDriverState *bs;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200526 int fix = 0;
Stefan Hajnoczi058f8f12012-08-09 13:05:56 +0100527 int flags = BDRV_O_FLAGS | BDRV_O_CHECK;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500528 ImageCheck *check;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100529 bool quiet = false;
aliguori15859692009-04-21 23:11:53 +0000530
531 fmt = NULL;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500532 output = NULL;
aliguori15859692009-04-21 23:11:53 +0000533 for(;;) {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500534 int option_index = 0;
535 static const struct option long_options[] = {
536 {"help", no_argument, 0, 'h'},
537 {"format", required_argument, 0, 'f'},
538 {"repair", no_argument, 0, 'r'},
539 {"output", required_argument, 0, OPTION_OUTPUT},
540 {0, 0, 0, 0}
541 };
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100542 c = getopt_long(argc, argv, "f:hr:q",
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500543 long_options, &option_index);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100544 if (c == -1) {
aliguori15859692009-04-21 23:11:53 +0000545 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100546 }
aliguori15859692009-04-21 23:11:53 +0000547 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100548 case '?':
aliguori15859692009-04-21 23:11:53 +0000549 case 'h':
550 help();
551 break;
552 case 'f':
553 fmt = optarg;
554 break;
Kevin Wolf4534ff52012-05-11 16:07:02 +0200555 case 'r':
556 flags |= BDRV_O_RDWR;
557
558 if (!strcmp(optarg, "leaks")) {
559 fix = BDRV_FIX_LEAKS;
560 } else if (!strcmp(optarg, "all")) {
561 fix = BDRV_FIX_LEAKS | BDRV_FIX_ERRORS;
562 } else {
563 help();
564 }
565 break;
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500566 case OPTION_OUTPUT:
567 output = optarg;
568 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100569 case 'q':
570 quiet = true;
571 break;
aliguori15859692009-04-21 23:11:53 +0000572 }
573 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100574 if (optind >= argc) {
aliguori15859692009-04-21 23:11:53 +0000575 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100576 }
aliguori15859692009-04-21 23:11:53 +0000577 filename = argv[optind++];
578
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500579 if (output && !strcmp(output, "json")) {
580 output_format = OFORMAT_JSON;
581 } else if (output && !strcmp(output, "human")) {
582 output_format = OFORMAT_HUMAN;
583 } else if (output) {
584 error_report("--output must be used with human or json as argument.");
585 return 1;
586 }
587
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100588 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900589 if (!bs) {
590 return 1;
591 }
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500592
593 check = g_new0(ImageCheck, 1);
594 ret = collect_image_check(bs, check, filename, fmt, fix);
Kevin Wolfe076f332010-06-29 11:43:13 +0200595
596 if (ret == -ENOTSUP) {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500597 if (output_format == OFORMAT_HUMAN) {
598 error_report("This image format does not support checks");
599 }
600 ret = 1;
601 goto fail;
Kevin Wolfe076f332010-06-29 11:43:13 +0200602 }
603
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500604 if (check->corruptions_fixed || check->leaks_fixed) {
605 int corruptions_fixed, leaks_fixed;
606
607 leaks_fixed = check->leaks_fixed;
608 corruptions_fixed = check->corruptions_fixed;
609
610 if (output_format == OFORMAT_HUMAN) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100611 qprintf(quiet,
612 "The following inconsistencies were found and repaired:\n\n"
613 " %" PRId64 " leaked clusters\n"
614 " %" PRId64 " corruptions\n\n"
615 "Double checking the fixed image now...\n",
616 check->leaks_fixed,
617 check->corruptions_fixed);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500618 }
619
620 ret = collect_image_check(bs, check, filename, fmt, 0);
621
622 check->leaks_fixed = leaks_fixed;
623 check->corruptions_fixed = corruptions_fixed;
Kevin Wolfccf34712012-05-11 18:16:54 +0200624 }
625
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500626 switch (output_format) {
627 case OFORMAT_HUMAN:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100628 dump_human_image_check(check, quiet);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500629 break;
630 case OFORMAT_JSON:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100631 dump_json_image_check(check, quiet);
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500632 break;
633 }
634
635 if (ret || check->check_errors) {
636 ret = 1;
637 goto fail;
638 }
639
640 if (check->corruptions) {
641 ret = 2;
642 } else if (check->leaks) {
643 ret = 3;
Kevin Wolfe076f332010-06-29 11:43:13 +0200644 } else {
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500645 ret = 0;
aliguori15859692009-04-21 23:11:53 +0000646 }
647
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500648fail:
649 qapi_free_ImageCheck(check);
aliguori15859692009-04-21 23:11:53 +0000650 bdrv_delete(bs);
Kevin Wolfe076f332010-06-29 11:43:13 +0200651
Federico Simoncelli8599ea42013-01-28 06:59:47 -0500652 return ret;
aliguori15859692009-04-21 23:11:53 +0000653}
654
bellardea2384d2004-08-01 21:59:26 +0000655static int img_commit(int argc, char **argv)
656{
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400657 int c, ret, flags;
658 const char *filename, *fmt, *cache;
bellardea2384d2004-08-01 21:59:26 +0000659 BlockDriverState *bs;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100660 bool quiet = false;
bellardea2384d2004-08-01 21:59:26 +0000661
662 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400663 cache = BDRV_DEFAULT_CACHE;
bellardea2384d2004-08-01 21:59:26 +0000664 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100665 c = getopt(argc, argv, "f:ht:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100666 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000667 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100668 }
bellardea2384d2004-08-01 21:59:26 +0000669 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100670 case '?':
bellardea2384d2004-08-01 21:59:26 +0000671 case 'h':
672 help();
673 break;
674 case 'f':
675 fmt = optarg;
676 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400677 case 't':
678 cache = optarg;
679 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100680 case 'q':
681 quiet = true;
682 break;
bellardea2384d2004-08-01 21:59:26 +0000683 }
684 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100685 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +0000686 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100687 }
bellardea2384d2004-08-01 21:59:26 +0000688 filename = argv[optind++];
689
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400690 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +0100691 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -0400692 if (ret < 0) {
693 error_report("Invalid cache option: %s", cache);
694 return -1;
695 }
696
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100697 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900698 if (!bs) {
699 return 1;
700 }
bellardea2384d2004-08-01 21:59:26 +0000701 ret = bdrv_commit(bs);
702 switch(ret) {
703 case 0:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +0100704 qprintf(quiet, "Image committed.\n");
bellardea2384d2004-08-01 21:59:26 +0000705 break;
706 case -ENOENT:
Jes Sorensen15654a62010-12-16 14:31:53 +0100707 error_report("No disk inserted");
bellardea2384d2004-08-01 21:59:26 +0000708 break;
709 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +0100710 error_report("Image is read-only");
bellardea2384d2004-08-01 21:59:26 +0000711 break;
712 case -ENOTSUP:
Jes Sorensen15654a62010-12-16 14:31:53 +0100713 error_report("Image is already committed");
bellardea2384d2004-08-01 21:59:26 +0000714 break;
715 default:
Jes Sorensen15654a62010-12-16 14:31:53 +0100716 error_report("Error while committing image");
bellardea2384d2004-08-01 21:59:26 +0000717 break;
718 }
719
720 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900721 if (ret) {
722 return 1;
723 }
bellardea2384d2004-08-01 21:59:26 +0000724 return 0;
725}
726
Dmitry Konishchevf6a00aa2011-05-18 15:03:59 +0400727/*
thsf58c7b32008-06-05 21:53:49 +0000728 * Returns true iff the first sector pointed to by 'buf' contains at least
729 * a non-NUL byte.
730 *
731 * 'pnum' is set to the number of sectors (including and immediately following
732 * the first one) that are known to be in the same allocated/unallocated state.
733 */
bellardea2384d2004-08-01 21:59:26 +0000734static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
735{
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000736 bool is_zero;
737 int i;
bellardea2384d2004-08-01 21:59:26 +0000738
739 if (n <= 0) {
740 *pnum = 0;
741 return 0;
742 }
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000743 is_zero = buffer_is_zero(buf, 512);
bellardea2384d2004-08-01 21:59:26 +0000744 for(i = 1; i < n; i++) {
745 buf += 512;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000746 if (is_zero != buffer_is_zero(buf, 512)) {
bellardea2384d2004-08-01 21:59:26 +0000747 break;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000748 }
bellardea2384d2004-08-01 21:59:26 +0000749 }
750 *pnum = i;
Stefan Hajnoczi1a6d39f2012-02-07 13:27:24 +0000751 return !is_zero;
bellardea2384d2004-08-01 21:59:26 +0000752}
753
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100754/*
Kevin Wolfa22f1232011-08-26 15:27:13 +0200755 * Like is_allocated_sectors, but if the buffer starts with a used sector,
756 * up to 'min' consecutive sectors containing zeros are ignored. This avoids
757 * breaking up write requests for only small sparse areas.
758 */
759static int is_allocated_sectors_min(const uint8_t *buf, int n, int *pnum,
760 int min)
761{
762 int ret;
763 int num_checked, num_used;
764
765 if (n < min) {
766 min = n;
767 }
768
769 ret = is_allocated_sectors(buf, n, pnum);
770 if (!ret) {
771 return ret;
772 }
773
774 num_used = *pnum;
775 buf += BDRV_SECTOR_SIZE * *pnum;
776 n -= *pnum;
777 num_checked = num_used;
778
779 while (n > 0) {
780 ret = is_allocated_sectors(buf, n, pnum);
781
782 buf += BDRV_SECTOR_SIZE * *pnum;
783 n -= *pnum;
784 num_checked += *pnum;
785 if (ret) {
786 num_used = num_checked;
787 } else if (*pnum >= min) {
788 break;
789 }
790 }
791
792 *pnum = num_used;
793 return 1;
794}
795
796/*
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100797 * Compares two buffers sector by sector. Returns 0 if the first sector of both
798 * buffers matches, non-zero otherwise.
799 *
800 * pnum is set to the number of sectors (including and immediately following
801 * the first one) that are known to have the same comparison result
802 */
803static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
804 int *pnum)
805{
806 int res, i;
807
808 if (n <= 0) {
809 *pnum = 0;
810 return 0;
811 }
812
813 res = !!memcmp(buf1, buf2, 512);
814 for(i = 1; i < n; i++) {
815 buf1 += 512;
816 buf2 += 512;
817
818 if (!!memcmp(buf1, buf2, 512) != res) {
819 break;
820 }
821 }
822
823 *pnum = i;
824 return res;
825}
826
Kevin Wolf80ee15a2009-09-15 12:30:43 +0200827#define IO_BUF_SIZE (2 * 1024 * 1024)
bellardea2384d2004-08-01 21:59:26 +0000828
Miroslav Rezaninad14ed182013-02-13 09:09:41 +0100829static int64_t sectors_to_bytes(int64_t sectors)
830{
831 return sectors << BDRV_SECTOR_BITS;
832}
833
834static int64_t sectors_to_process(int64_t total, int64_t from)
835{
836 return MIN(total - from, IO_BUF_SIZE >> BDRV_SECTOR_BITS);
837}
838
839/*
840 * Check if passed sectors are empty (not allocated or contain only 0 bytes)
841 *
842 * Returns 0 in case sectors are filled with 0, 1 if sectors contain non-zero
843 * data and negative value on error.
844 *
845 * @param bs: Driver used for accessing file
846 * @param sect_num: Number of first sector to check
847 * @param sect_count: Number of sectors to check
848 * @param filename: Name of disk file we are checking (logging purpose)
849 * @param buffer: Allocated buffer for storing read data
850 * @param quiet: Flag for quiet mode
851 */
852static int check_empty_sectors(BlockDriverState *bs, int64_t sect_num,
853 int sect_count, const char *filename,
854 uint8_t *buffer, bool quiet)
855{
856 int pnum, ret = 0;
857 ret = bdrv_read(bs, sect_num, buffer, sect_count);
858 if (ret < 0) {
859 error_report("Error while reading offset %" PRId64 " of %s: %s",
860 sectors_to_bytes(sect_num), filename, strerror(-ret));
861 return ret;
862 }
863 ret = is_allocated_sectors(buffer, sect_count, &pnum);
864 if (ret || pnum != sect_count) {
865 qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
866 sectors_to_bytes(ret ? sect_num : sect_num + pnum));
867 return 1;
868 }
869
870 return 0;
871}
872
873/*
874 * Compares two images. Exit codes:
875 *
876 * 0 - Images are identical
877 * 1 - Images differ
878 * >1 - Error occurred
879 */
880static int img_compare(int argc, char **argv)
881{
882 const char *fmt1 = NULL, *fmt2 = NULL, *filename1, *filename2;
883 BlockDriverState *bs1, *bs2;
884 int64_t total_sectors1, total_sectors2;
885 uint8_t *buf1 = NULL, *buf2 = NULL;
886 int pnum1, pnum2;
887 int allocated1, allocated2;
888 int ret = 0; /* return value - 0 Ident, 1 Different, >1 Error */
889 bool progress = false, quiet = false, strict = false;
890 int64_t total_sectors;
891 int64_t sector_num = 0;
892 int64_t nb_sectors;
893 int c, pnum;
894 uint64_t bs_sectors;
895 uint64_t progress_base;
896
897 for (;;) {
898 c = getopt(argc, argv, "hpf:F:sq");
899 if (c == -1) {
900 break;
901 }
902 switch (c) {
903 case '?':
904 case 'h':
905 help();
906 break;
907 case 'f':
908 fmt1 = optarg;
909 break;
910 case 'F':
911 fmt2 = optarg;
912 break;
913 case 'p':
914 progress = true;
915 break;
916 case 'q':
917 quiet = true;
918 break;
919 case 's':
920 strict = true;
921 break;
922 }
923 }
924
925 /* Progress is not shown in Quiet mode */
926 if (quiet) {
927 progress = false;
928 }
929
930
931 if (optind > argc - 2) {
932 help();
933 }
934 filename1 = argv[optind++];
935 filename2 = argv[optind++];
936
937 /* Initialize before goto out */
938 qemu_progress_init(progress, 2.0);
939
940 bs1 = bdrv_new_open(filename1, fmt1, BDRV_O_FLAGS, true, quiet);
941 if (!bs1) {
942 error_report("Can't open file %s", filename1);
943 ret = 2;
944 goto out3;
945 }
946
947 bs2 = bdrv_new_open(filename2, fmt2, BDRV_O_FLAGS, true, quiet);
948 if (!bs2) {
949 error_report("Can't open file %s", filename2);
950 ret = 2;
951 goto out2;
952 }
953
954 buf1 = qemu_blockalign(bs1, IO_BUF_SIZE);
955 buf2 = qemu_blockalign(bs2, IO_BUF_SIZE);
956 bdrv_get_geometry(bs1, &bs_sectors);
957 total_sectors1 = bs_sectors;
958 bdrv_get_geometry(bs2, &bs_sectors);
959 total_sectors2 = bs_sectors;
960 total_sectors = MIN(total_sectors1, total_sectors2);
961 progress_base = MAX(total_sectors1, total_sectors2);
962
963 qemu_progress_print(0, 100);
964
965 if (strict && total_sectors1 != total_sectors2) {
966 ret = 1;
967 qprintf(quiet, "Strict mode: Image size mismatch!\n");
968 goto out;
969 }
970
971 for (;;) {
972 nb_sectors = sectors_to_process(total_sectors, sector_num);
973 if (nb_sectors <= 0) {
974 break;
975 }
976 allocated1 = bdrv_is_allocated_above(bs1, NULL, sector_num, nb_sectors,
977 &pnum1);
978 if (allocated1 < 0) {
979 ret = 3;
980 error_report("Sector allocation test failed for %s", filename1);
981 goto out;
982 }
983
984 allocated2 = bdrv_is_allocated_above(bs2, NULL, sector_num, nb_sectors,
985 &pnum2);
986 if (allocated2 < 0) {
987 ret = 3;
988 error_report("Sector allocation test failed for %s", filename2);
989 goto out;
990 }
991 nb_sectors = MIN(pnum1, pnum2);
992
993 if (allocated1 == allocated2) {
994 if (allocated1) {
995 ret = bdrv_read(bs1, sector_num, buf1, nb_sectors);
996 if (ret < 0) {
997 error_report("Error while reading offset %" PRId64 " of %s:"
998 " %s", sectors_to_bytes(sector_num), filename1,
999 strerror(-ret));
1000 ret = 4;
1001 goto out;
1002 }
1003 ret = bdrv_read(bs2, sector_num, buf2, nb_sectors);
1004 if (ret < 0) {
1005 error_report("Error while reading offset %" PRId64
1006 " of %s: %s", sectors_to_bytes(sector_num),
1007 filename2, strerror(-ret));
1008 ret = 4;
1009 goto out;
1010 }
1011 ret = compare_sectors(buf1, buf2, nb_sectors, &pnum);
1012 if (ret || pnum != nb_sectors) {
1013 ret = 1;
1014 qprintf(quiet, "Content mismatch at offset %" PRId64 "!\n",
1015 sectors_to_bytes(
1016 ret ? sector_num : sector_num + pnum));
1017 goto out;
1018 }
1019 }
1020 } else {
1021 if (strict) {
1022 ret = 1;
1023 qprintf(quiet, "Strict mode: Offset %" PRId64
1024 " allocation mismatch!\n",
1025 sectors_to_bytes(sector_num));
1026 goto out;
1027 }
1028
1029 if (allocated1) {
1030 ret = check_empty_sectors(bs1, sector_num, nb_sectors,
1031 filename1, buf1, quiet);
1032 } else {
1033 ret = check_empty_sectors(bs2, sector_num, nb_sectors,
1034 filename2, buf1, quiet);
1035 }
1036 if (ret) {
1037 if (ret < 0) {
1038 ret = 4;
1039 error_report("Error while reading offset %" PRId64 ": %s",
1040 sectors_to_bytes(sector_num), strerror(-ret));
1041 }
1042 goto out;
1043 }
1044 }
1045 sector_num += nb_sectors;
1046 qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
1047 }
1048
1049 if (total_sectors1 != total_sectors2) {
1050 BlockDriverState *bs_over;
1051 int64_t total_sectors_over;
1052 const char *filename_over;
1053
1054 qprintf(quiet, "Warning: Image size mismatch!\n");
1055 if (total_sectors1 > total_sectors2) {
1056 total_sectors_over = total_sectors1;
1057 bs_over = bs1;
1058 filename_over = filename1;
1059 } else {
1060 total_sectors_over = total_sectors2;
1061 bs_over = bs2;
1062 filename_over = filename2;
1063 }
1064
1065 for (;;) {
1066 nb_sectors = sectors_to_process(total_sectors_over, sector_num);
1067 if (nb_sectors <= 0) {
1068 break;
1069 }
1070 ret = bdrv_is_allocated_above(bs_over, NULL, sector_num,
1071 nb_sectors, &pnum);
1072 if (ret < 0) {
1073 ret = 3;
1074 error_report("Sector allocation test failed for %s",
1075 filename_over);
1076 goto out;
1077
1078 }
1079 nb_sectors = pnum;
1080 if (ret) {
1081 ret = check_empty_sectors(bs_over, sector_num, nb_sectors,
1082 filename_over, buf1, quiet);
1083 if (ret) {
1084 if (ret < 0) {
1085 ret = 4;
1086 error_report("Error while reading offset %" PRId64
1087 " of %s: %s", sectors_to_bytes(sector_num),
1088 filename_over, strerror(-ret));
1089 }
1090 goto out;
1091 }
1092 }
1093 sector_num += nb_sectors;
1094 qemu_progress_print(((float) nb_sectors / progress_base)*100, 100);
1095 }
1096 }
1097
1098 qprintf(quiet, "Images are identical.\n");
1099 ret = 0;
1100
1101out:
1102 bdrv_delete(bs2);
1103 qemu_vfree(buf1);
1104 qemu_vfree(buf2);
1105out2:
1106 bdrv_delete(bs1);
1107out3:
1108 qemu_progress_end();
1109 return ret;
1110}
1111
bellardea2384d2004-08-01 21:59:26 +00001112static int img_convert(int argc, char **argv)
1113{
Jes Sorenseneec77d92010-12-07 17:44:34 +01001114 int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001115 int progress = 0, flags;
1116 const char *fmt, *out_fmt, *cache, *out_baseimg, *out_filename;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001117 BlockDriver *drv, *proto_drv;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001118 BlockDriverState **bs = NULL, *out_bs = NULL;
ths96b8f132007-12-17 01:35:20 +00001119 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
1120 uint64_t bs_sectors;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001121 uint8_t * buf = NULL;
bellardea2384d2004-08-01 21:59:26 +00001122 const uint8_t *buf1;
bellardfaea38e2006-08-05 21:31:00 +00001123 BlockDriverInfo bdi;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001124 QEMUOptionParameter *param = NULL, *create_options = NULL;
Kevin Wolfa18953f2010-10-14 15:46:04 +02001125 QEMUOptionParameter *out_baseimg_param;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001126 char *options = NULL;
edison51ef6722010-09-21 19:58:41 -07001127 const char *snapshot_name = NULL;
Kevin Wolf1f710492012-10-12 14:29:18 +02001128 float local_progress = 0;
Kevin Wolfa22f1232011-08-26 15:27:13 +02001129 int min_sparse = 8; /* Need at least 4k of zeros for sparse detection */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001130 bool quiet = false;
bellardea2384d2004-08-01 21:59:26 +00001131
1132 fmt = NULL;
1133 out_fmt = "raw";
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001134 cache = "unsafe";
thsf58c7b32008-06-05 21:53:49 +00001135 out_baseimg = NULL;
Jes Sorenseneec77d92010-12-07 17:44:34 +01001136 compress = 0;
bellardea2384d2004-08-01 21:59:26 +00001137 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001138 c = getopt(argc, argv, "f:O:B:s:hce6o:pS:t:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001139 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001140 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001141 }
bellardea2384d2004-08-01 21:59:26 +00001142 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001143 case '?':
bellardea2384d2004-08-01 21:59:26 +00001144 case 'h':
1145 help();
1146 break;
1147 case 'f':
1148 fmt = optarg;
1149 break;
1150 case 'O':
1151 out_fmt = optarg;
1152 break;
thsf58c7b32008-06-05 21:53:49 +00001153 case 'B':
1154 out_baseimg = optarg;
1155 break;
bellardea2384d2004-08-01 21:59:26 +00001156 case 'c':
Jes Sorenseneec77d92010-12-07 17:44:34 +01001157 compress = 1;
bellardea2384d2004-08-01 21:59:26 +00001158 break;
1159 case 'e':
Markus Armbruster9d42e152011-06-22 14:03:55 +02001160 error_report("option -e is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +01001161 "encryption\' instead!");
1162 return 1;
thsec36ba12007-09-16 21:59:02 +00001163 case '6':
Markus Armbruster9d42e152011-06-22 14:03:55 +02001164 error_report("option -6 is deprecated, please use \'-o "
Jes Sorenseneec77d92010-12-07 17:44:34 +01001165 "compat6\' instead!");
1166 return 1;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001167 case 'o':
1168 options = optarg;
1169 break;
edison51ef6722010-09-21 19:58:41 -07001170 case 's':
1171 snapshot_name = optarg;
1172 break;
Kevin Wolfa22f1232011-08-26 15:27:13 +02001173 case 'S':
1174 {
1175 int64_t sval;
Markus Armbrustere36b3692011-11-22 09:46:05 +01001176 char *end;
1177 sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
1178 if (sval < 0 || *end) {
Kevin Wolfa22f1232011-08-26 15:27:13 +02001179 error_report("Invalid minimum zero buffer size for sparse output specified");
1180 return 1;
1181 }
1182
1183 min_sparse = sval / BDRV_SECTOR_SIZE;
1184 break;
1185 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001186 case 'p':
1187 progress = 1;
1188 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001189 case 't':
1190 cache = optarg;
1191 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001192 case 'q':
1193 quiet = true;
1194 break;
bellardea2384d2004-08-01 21:59:26 +00001195 }
1196 }
ths3b46e622007-09-17 08:09:54 +00001197
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001198 if (quiet) {
1199 progress = 0;
1200 }
1201
balrog926c2d22007-10-31 01:11:44 +00001202 bs_n = argc - optind - 1;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001203 if (bs_n < 1) {
1204 help();
1205 }
balrog926c2d22007-10-31 01:11:44 +00001206
1207 out_filename = argv[argc - 1];
thsf58c7b32008-06-05 21:53:49 +00001208
Charles Arnoldfa170c12012-05-11 10:57:54 -06001209 /* Initialize before goto out */
1210 qemu_progress_init(progress, 2.0);
1211
Peter Maydellc8057f92012-08-02 13:45:54 +01001212 if (options && is_help_option(options)) {
Jes Sorensen4ac8aac2010-12-06 15:25:38 +01001213 ret = print_block_option_help(out_filename, out_fmt);
1214 goto out;
1215 }
1216
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001217 if (bs_n > 1 && out_baseimg) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001218 error_report("-B makes no sense when concatenating multiple input "
1219 "images");
Jes Sorensen31ca34b2010-12-06 15:25:36 +01001220 ret = -1;
1221 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001222 }
Dong Xu Wangf8111c22012-03-15 20:13:31 +08001223
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001224 qemu_progress_print(0, 100);
1225
Anthony Liguori7267c092011-08-20 22:09:37 -05001226 bs = g_malloc0(bs_n * sizeof(BlockDriverState *));
balrog926c2d22007-10-31 01:11:44 +00001227
1228 total_sectors = 0;
1229 for (bs_i = 0; bs_i < bs_n; bs_i++) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001230 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS, true,
1231 quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001232 if (!bs[bs_i]) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001233 error_report("Could not open '%s'", argv[optind + bs_i]);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001234 ret = -1;
1235 goto out;
1236 }
balrog926c2d22007-10-31 01:11:44 +00001237 bdrv_get_geometry(bs[bs_i], &bs_sectors);
1238 total_sectors += bs_sectors;
1239 }
bellardea2384d2004-08-01 21:59:26 +00001240
edison51ef6722010-09-21 19:58:41 -07001241 if (snapshot_name != NULL) {
1242 if (bs_n > 1) {
Markus Armbruster6daf1942011-06-22 14:03:54 +02001243 error_report("No support for concatenating multiple snapshot");
edison51ef6722010-09-21 19:58:41 -07001244 ret = -1;
1245 goto out;
1246 }
1247 if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +02001248 error_report("Failed to load snapshot");
edison51ef6722010-09-21 19:58:41 -07001249 ret = -1;
1250 goto out;
1251 }
1252 }
1253
Kevin Wolfefa84d42009-05-18 16:42:12 +02001254 /* Find driver and parse its options */
bellardea2384d2004-08-01 21:59:26 +00001255 drv = bdrv_find_format(out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001256 if (!drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001257 error_report("Unknown file format '%s'", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001258 ret = -1;
1259 goto out;
1260 }
balrog926c2d22007-10-31 01:11:44 +00001261
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001262 proto_drv = bdrv_find_protocol(out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001263 if (!proto_drv) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001264 error_report("Unknown protocol '%s'", out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001265 ret = -1;
1266 goto out;
1267 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001268
1269 create_options = append_option_parameters(create_options,
1270 drv->create_options);
1271 create_options = append_option_parameters(create_options,
1272 proto_drv->create_options);
Kevin Wolfdb08adf2009-06-04 15:39:38 +02001273
Kevin Wolfefa84d42009-05-18 16:42:12 +02001274 if (options) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001275 param = parse_option_parameters(options, create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001276 if (param == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001277 error_report("Invalid options for file format '%s'.", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001278 ret = -1;
1279 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001280 }
1281 } else {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +09001282 param = parse_option_parameters("", create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001283 }
1284
1285 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
Jes Sorenseneec77d92010-12-07 17:44:34 +01001286 ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001287 if (ret < 0) {
1288 goto out;
1289 }
Kevin Wolfefa84d42009-05-18 16:42:12 +02001290
Kevin Wolfa18953f2010-10-14 15:46:04 +02001291 /* Get backing file name if -o backing_file was used */
1292 out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
1293 if (out_baseimg_param) {
1294 out_baseimg = out_baseimg_param->value.s;
1295 }
1296
Kevin Wolfefa84d42009-05-18 16:42:12 +02001297 /* Check if compression is supported */
Jes Sorenseneec77d92010-12-07 17:44:34 +01001298 if (compress) {
Kevin Wolfefa84d42009-05-18 16:42:12 +02001299 QEMUOptionParameter *encryption =
1300 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
Kevin Wolf41521fa2011-10-18 16:19:42 +02001301 QEMUOptionParameter *preallocation =
1302 get_option_parameter(param, BLOCK_OPT_PREALLOC);
Kevin Wolfefa84d42009-05-18 16:42:12 +02001303
1304 if (!drv->bdrv_write_compressed) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001305 error_report("Compression not supported for this file format");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001306 ret = -1;
1307 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001308 }
1309
1310 if (encryption && encryption->value.n) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001311 error_report("Compression and encryption not supported at "
1312 "the same time");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001313 ret = -1;
1314 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +02001315 }
Kevin Wolf41521fa2011-10-18 16:19:42 +02001316
1317 if (preallocation && preallocation->value.s
1318 && strcmp(preallocation->value.s, "off"))
1319 {
1320 error_report("Compression and preallocation not supported at "
1321 "the same time");
1322 ret = -1;
1323 goto out;
1324 }
Kevin Wolfefa84d42009-05-18 16:42:12 +02001325 }
1326
1327 /* Create the new image */
1328 ret = bdrv_create(drv, out_filename, param);
bellardea2384d2004-08-01 21:59:26 +00001329 if (ret < 0) {
1330 if (ret == -ENOTSUP) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001331 error_report("Formatting not supported for file format '%s'",
1332 out_fmt);
aurel326e9ea0c2009-04-15 14:42:46 +00001333 } else if (ret == -EFBIG) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001334 error_report("The image size is too large for file format '%s'",
1335 out_fmt);
bellardea2384d2004-08-01 21:59:26 +00001336 } else {
Jes Sorensen15654a62010-12-16 14:31:53 +01001337 error_report("%s: error while converting %s: %s",
1338 out_filename, out_fmt, strerror(-ret));
bellardea2384d2004-08-01 21:59:26 +00001339 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001340 goto out;
bellardea2384d2004-08-01 21:59:26 +00001341 }
ths3b46e622007-09-17 08:09:54 +00001342
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001343 flags = BDRV_O_RDWR;
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +01001344 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001345 if (ret < 0) {
1346 error_report("Invalid cache option: %s", cache);
1347 return -1;
1348 }
1349
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001350 out_bs = bdrv_new_open(out_filename, out_fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001351 if (!out_bs) {
1352 ret = -1;
1353 goto out;
1354 }
bellardea2384d2004-08-01 21:59:26 +00001355
balrog926c2d22007-10-31 01:11:44 +00001356 bs_i = 0;
1357 bs_offset = 0;
1358 bdrv_get_geometry(bs[0], &bs_sectors);
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001359 buf = qemu_blockalign(out_bs, IO_BUF_SIZE);
balrog926c2d22007-10-31 01:11:44 +00001360
Jes Sorenseneec77d92010-12-07 17:44:34 +01001361 if (compress) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001362 ret = bdrv_get_info(out_bs, &bdi);
1363 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001364 error_report("could not get block driver info");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001365 goto out;
1366 }
bellardfaea38e2006-08-05 21:31:00 +00001367 cluster_size = bdi.cluster_size;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001368 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001369 error_report("invalid cluster size");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001370 ret = -1;
1371 goto out;
1372 }
bellardea2384d2004-08-01 21:59:26 +00001373 cluster_sectors = cluster_size >> 9;
1374 sector_num = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001375
1376 nb_sectors = total_sectors;
Kevin Wolf1f710492012-10-12 14:29:18 +02001377 if (nb_sectors != 0) {
1378 local_progress = (float)100 /
1379 (nb_sectors / MIN(nb_sectors, cluster_sectors));
1380 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001381
bellardea2384d2004-08-01 21:59:26 +00001382 for(;;) {
balrog926c2d22007-10-31 01:11:44 +00001383 int64_t bs_num;
1384 int remainder;
1385 uint8_t *buf2;
1386
bellardea2384d2004-08-01 21:59:26 +00001387 nb_sectors = total_sectors - sector_num;
1388 if (nb_sectors <= 0)
1389 break;
1390 if (nb_sectors >= cluster_sectors)
1391 n = cluster_sectors;
1392 else
1393 n = nb_sectors;
balrog926c2d22007-10-31 01:11:44 +00001394
1395 bs_num = sector_num - bs_offset;
1396 assert (bs_num >= 0);
1397 remainder = n;
1398 buf2 = buf;
1399 while (remainder > 0) {
1400 int nlow;
1401 while (bs_num == bs_sectors) {
1402 bs_i++;
1403 assert (bs_i < bs_n);
1404 bs_offset += bs_sectors;
1405 bdrv_get_geometry(bs[bs_i], &bs_sectors);
1406 bs_num = 0;
Blue Swirl0bfcd592010-05-22 08:02:12 +00001407 /* printf("changing part: sector_num=%" PRId64 ", "
1408 "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
1409 "\n", sector_num, bs_i, bs_offset, bs_sectors); */
balrog926c2d22007-10-31 01:11:44 +00001410 }
1411 assert (bs_num < bs_sectors);
1412
1413 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
1414
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001415 ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
1416 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001417 error_report("error while reading sector %" PRId64 ": %s",
1418 bs_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001419 goto out;
1420 }
balrog926c2d22007-10-31 01:11:44 +00001421
1422 buf2 += nlow * 512;
1423 bs_num += nlow;
1424
1425 remainder -= nlow;
1426 }
1427 assert (remainder == 0);
1428
Stefan Hajnoczi54f106d2013-04-15 17:17:33 +02001429 if (!buffer_is_zero(buf, n * BDRV_SECTOR_SIZE)) {
1430 ret = bdrv_write_compressed(out_bs, sector_num, buf, n);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001431 if (ret != 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001432 error_report("error while compressing sector %" PRId64
1433 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001434 goto out;
1435 }
bellardea2384d2004-08-01 21:59:26 +00001436 }
1437 sector_num += n;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001438 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +00001439 }
bellardfaea38e2006-08-05 21:31:00 +00001440 /* signal EOF to align */
1441 bdrv_write_compressed(out_bs, 0, NULL, 0);
bellardea2384d2004-08-01 21:59:26 +00001442 } else {
Kevin Wolff2feebb2010-04-14 17:30:35 +02001443 int has_zero_init = bdrv_has_zero_init(out_bs);
1444
thsf58c7b32008-06-05 21:53:49 +00001445 sector_num = 0; // total number of sectors converted so far
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001446 nb_sectors = total_sectors - sector_num;
Kevin Wolf1f710492012-10-12 14:29:18 +02001447 if (nb_sectors != 0) {
1448 local_progress = (float)100 /
1449 (nb_sectors / MIN(nb_sectors, IO_BUF_SIZE / 512));
1450 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001451
bellardea2384d2004-08-01 21:59:26 +00001452 for(;;) {
1453 nb_sectors = total_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001454 if (nb_sectors <= 0) {
bellardea2384d2004-08-01 21:59:26 +00001455 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001456 }
1457 if (nb_sectors >= (IO_BUF_SIZE / 512)) {
bellardea2384d2004-08-01 21:59:26 +00001458 n = (IO_BUF_SIZE / 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001459 } else {
bellardea2384d2004-08-01 21:59:26 +00001460 n = nb_sectors;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001461 }
balrog926c2d22007-10-31 01:11:44 +00001462
1463 while (sector_num - bs_offset >= bs_sectors) {
1464 bs_i ++;
1465 assert (bs_i < bs_n);
1466 bs_offset += bs_sectors;
1467 bdrv_get_geometry(bs[bs_i], &bs_sectors);
Blue Swirl0bfcd592010-05-22 08:02:12 +00001468 /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
1469 "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
balrog926c2d22007-10-31 01:11:44 +00001470 sector_num, bs_i, bs_offset, bs_sectors); */
1471 }
1472
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001473 if (n > bs_offset + bs_sectors - sector_num) {
balrog926c2d22007-10-31 01:11:44 +00001474 n = bs_offset + bs_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001475 }
balrog926c2d22007-10-31 01:11:44 +00001476
Kevin Wolff2feebb2010-04-14 17:30:35 +02001477 if (has_zero_init) {
Akkarit Sangpetchd0320442009-07-17 10:02:15 +02001478 /* If the output image is being created as a copy on write image,
1479 assume that sectors which are unallocated in the input image
1480 are present in both the output's and input's base images (no
1481 need to copy them). */
1482 if (out_baseimg) {
1483 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
1484 n, &n1)) {
1485 sector_num += n1;
1486 continue;
1487 }
1488 /* The next 'n1' sectors are allocated in the input image. Copy
1489 only those as they may be followed by unallocated sectors. */
1490 n = n1;
aliguori93c65b42009-04-05 17:40:43 +00001491 }
aliguori93c65b42009-04-05 17:40:43 +00001492 } else {
1493 n1 = n;
thsf58c7b32008-06-05 21:53:49 +00001494 }
1495
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001496 ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
1497 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001498 error_report("error while reading sector %" PRId64 ": %s",
1499 sector_num - bs_offset, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001500 goto out;
1501 }
bellardea2384d2004-08-01 21:59:26 +00001502 /* NOTE: at the same time we convert, we do not write zero
1503 sectors to have a chance to compress the image. Ideally, we
1504 should add a specific call to have the info to go faster */
1505 buf1 = buf;
1506 while (n > 0) {
thsf58c7b32008-06-05 21:53:49 +00001507 /* If the output image is being created as a copy on write image,
1508 copy all sectors even the ones containing only NUL bytes,
aliguori93c65b42009-04-05 17:40:43 +00001509 because they may differ from the sectors in the base image.
1510
1511 If the output is to a host device, we also write out
1512 sectors that are entirely 0, since whatever data was
1513 already there is garbage, not 0s. */
Kevin Wolff2feebb2010-04-14 17:30:35 +02001514 if (!has_zero_init || out_baseimg ||
Kevin Wolfa22f1232011-08-26 15:27:13 +02001515 is_allocated_sectors_min(buf1, n, &n1, min_sparse)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001516 ret = bdrv_write(out_bs, sector_num, buf1, n1);
1517 if (ret < 0) {
Stefan Hajnoczi3fba9d82011-08-17 17:41:09 +01001518 error_report("error while writing sector %" PRId64
1519 ": %s", sector_num, strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001520 goto out;
1521 }
bellardea2384d2004-08-01 21:59:26 +00001522 }
1523 sector_num += n1;
1524 n -= n1;
1525 buf1 += n1 * 512;
1526 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001527 qemu_progress_print(local_progress, 100);
bellardea2384d2004-08-01 21:59:26 +00001528 }
1529 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001530out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001531 qemu_progress_end();
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001532 free_option_parameters(create_options);
1533 free_option_parameters(param);
Kevin Wolfbb1c0592011-08-08 14:09:12 +02001534 qemu_vfree(buf);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001535 if (out_bs) {
1536 bdrv_delete(out_bs);
1537 }
Jes Sorensen31ca34b2010-12-06 15:25:36 +01001538 if (bs) {
1539 for (bs_i = 0; bs_i < bs_n; bs_i++) {
1540 if (bs[bs_i]) {
1541 bdrv_delete(bs[bs_i]);
1542 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001543 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001544 g_free(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001545 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001546 if (ret) {
1547 return 1;
1548 }
bellardea2384d2004-08-01 21:59:26 +00001549 return 0;
1550}
1551
bellard57d1a2b2004-08-03 21:15:11 +00001552
bellardfaea38e2006-08-05 21:31:00 +00001553static void dump_snapshots(BlockDriverState *bs)
1554{
1555 QEMUSnapshotInfo *sn_tab, *sn;
1556 int nb_sns, i;
bellardfaea38e2006-08-05 21:31:00 +00001557
1558 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1559 if (nb_sns <= 0)
1560 return;
1561 printf("Snapshot list:\n");
Wenchao Xia5b917042013-05-25 11:09:45 +08001562 bdrv_snapshot_dump(fprintf, stdout, NULL);
1563 printf("\n");
bellardfaea38e2006-08-05 21:31:00 +00001564 for(i = 0; i < nb_sns; i++) {
1565 sn = &sn_tab[i];
Wenchao Xia5b917042013-05-25 11:09:45 +08001566 bdrv_snapshot_dump(fprintf, stdout, sn);
1567 printf("\n");
bellardfaea38e2006-08-05 21:31:00 +00001568 }
Anthony Liguori7267c092011-08-20 22:09:37 -05001569 g_free(sn_tab);
bellardfaea38e2006-08-05 21:31:00 +00001570}
1571
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001572static void dump_json_image_info_list(ImageInfoList *list)
1573{
1574 Error *errp = NULL;
1575 QString *str;
1576 QmpOutputVisitor *ov = qmp_output_visitor_new();
1577 QObject *obj;
1578 visit_type_ImageInfoList(qmp_output_get_visitor(ov),
1579 &list, NULL, &errp);
1580 obj = qmp_output_get_qobject(ov);
1581 str = qobject_to_json_pretty(obj);
1582 assert(str != NULL);
1583 printf("%s\n", qstring_get_str(str));
1584 qobject_decref(obj);
1585 qmp_output_visitor_cleanup(ov);
1586 QDECREF(str);
1587}
1588
Benoît Canetc054b3f2012-09-05 13:09:02 +02001589static void dump_json_image_info(ImageInfo *info)
1590{
1591 Error *errp = NULL;
1592 QString *str;
1593 QmpOutputVisitor *ov = qmp_output_visitor_new();
1594 QObject *obj;
1595 visit_type_ImageInfo(qmp_output_get_visitor(ov),
1596 &info, NULL, &errp);
1597 obj = qmp_output_get_qobject(ov);
1598 str = qobject_to_json_pretty(obj);
1599 assert(str != NULL);
1600 printf("%s\n", qstring_get_str(str));
1601 qobject_decref(obj);
1602 qmp_output_visitor_cleanup(ov);
1603 QDECREF(str);
1604}
1605
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001606static void dump_human_image_info_list(ImageInfoList *list)
1607{
1608 ImageInfoList *elem;
1609 bool delim = false;
1610
1611 for (elem = list; elem; elem = elem->next) {
1612 if (delim) {
1613 printf("\n");
1614 }
1615 delim = true;
1616
Wenchao Xia5b917042013-05-25 11:09:45 +08001617 bdrv_image_info_dump(fprintf, stdout, elem->value);
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001618 }
1619}
1620
1621static gboolean str_equal_func(gconstpointer a, gconstpointer b)
1622{
1623 return strcmp(a, b) == 0;
1624}
1625
1626/**
1627 * Open an image file chain and return an ImageInfoList
1628 *
1629 * @filename: topmost image filename
1630 * @fmt: topmost image format (may be NULL to autodetect)
1631 * @chain: true - enumerate entire backing file chain
1632 * false - only topmost image file
1633 *
1634 * Returns a list of ImageInfo objects or NULL if there was an error opening an
1635 * image file. If there was an error a message will have been printed to
1636 * stderr.
1637 */
1638static ImageInfoList *collect_image_info_list(const char *filename,
1639 const char *fmt,
1640 bool chain)
1641{
1642 ImageInfoList *head = NULL;
1643 ImageInfoList **last = &head;
1644 GHashTable *filenames;
1645
1646 filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
1647
1648 while (filename) {
1649 BlockDriverState *bs;
1650 ImageInfo *info;
1651 ImageInfoList *elem;
1652
1653 if (g_hash_table_lookup_extended(filenames, filename, NULL, NULL)) {
1654 error_report("Backing file '%s' creates an infinite loop.",
1655 filename);
1656 goto err;
1657 }
1658 g_hash_table_insert(filenames, (gpointer)filename, NULL);
1659
1660 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING,
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001661 false, false);
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001662 if (!bs) {
1663 goto err;
1664 }
1665
1666 info = g_new0(ImageInfo, 1);
Wenchao Xiaf364ec62013-05-25 11:09:44 +08001667 bdrv_collect_image_info(bs, info, filename);
1668 bdrv_collect_snapshots(bs, info);
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001669
1670 elem = g_new0(ImageInfoList, 1);
1671 elem->value = info;
1672 *last = elem;
1673 last = &elem->next;
1674
1675 bdrv_delete(bs);
1676
1677 filename = fmt = NULL;
1678 if (chain) {
1679 if (info->has_full_backing_filename) {
1680 filename = info->full_backing_filename;
1681 } else if (info->has_backing_filename) {
1682 filename = info->backing_filename;
1683 }
1684 if (info->has_backing_filename_format) {
1685 fmt = info->backing_filename_format;
1686 }
1687 }
1688 }
1689 g_hash_table_destroy(filenames);
1690 return head;
1691
1692err:
1693 qapi_free_ImageInfoList(head);
1694 g_hash_table_destroy(filenames);
1695 return NULL;
1696}
1697
Benoît Canetc054b3f2012-09-05 13:09:02 +02001698static int img_info(int argc, char **argv)
1699{
1700 int c;
1701 OutputFormat output_format = OFORMAT_HUMAN;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001702 bool chain = false;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001703 const char *filename, *fmt, *output;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001704 ImageInfoList *list;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001705
bellardea2384d2004-08-01 21:59:26 +00001706 fmt = NULL;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001707 output = NULL;
bellardea2384d2004-08-01 21:59:26 +00001708 for(;;) {
Benoît Canetc054b3f2012-09-05 13:09:02 +02001709 int option_index = 0;
1710 static const struct option long_options[] = {
1711 {"help", no_argument, 0, 'h'},
1712 {"format", required_argument, 0, 'f'},
1713 {"output", required_argument, 0, OPTION_OUTPUT},
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001714 {"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
Benoît Canetc054b3f2012-09-05 13:09:02 +02001715 {0, 0, 0, 0}
1716 };
1717 c = getopt_long(argc, argv, "f:h",
1718 long_options, &option_index);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001719 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001720 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001721 }
bellardea2384d2004-08-01 21:59:26 +00001722 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001723 case '?':
bellardea2384d2004-08-01 21:59:26 +00001724 case 'h':
1725 help();
1726 break;
1727 case 'f':
1728 fmt = optarg;
1729 break;
Benoît Canetc054b3f2012-09-05 13:09:02 +02001730 case OPTION_OUTPUT:
1731 output = optarg;
1732 break;
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001733 case OPTION_BACKING_CHAIN:
1734 chain = true;
1735 break;
bellardea2384d2004-08-01 21:59:26 +00001736 }
1737 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001738 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +00001739 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001740 }
bellardea2384d2004-08-01 21:59:26 +00001741 filename = argv[optind++];
1742
Benoît Canetc054b3f2012-09-05 13:09:02 +02001743 if (output && !strcmp(output, "json")) {
1744 output_format = OFORMAT_JSON;
1745 } else if (output && !strcmp(output, "human")) {
1746 output_format = OFORMAT_HUMAN;
1747 } else if (output) {
1748 error_report("--output must be used with human or json as argument.");
1749 return 1;
1750 }
1751
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001752 list = collect_image_info_list(filename, fmt, chain);
1753 if (!list) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001754 return 1;
1755 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001756
Benoît Canetc054b3f2012-09-05 13:09:02 +02001757 switch (output_format) {
1758 case OFORMAT_HUMAN:
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001759 dump_human_image_info_list(list);
Benoît Canetc054b3f2012-09-05 13:09:02 +02001760 break;
1761 case OFORMAT_JSON:
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001762 if (chain) {
1763 dump_json_image_info_list(list);
1764 } else {
1765 dump_json_image_info(list->value);
1766 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001767 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001768 }
Benoît Canetc054b3f2012-09-05 13:09:02 +02001769
Stefan Hajnoczi9699bf02012-10-17 14:02:31 +02001770 qapi_free_ImageInfoList(list);
bellardea2384d2004-08-01 21:59:26 +00001771 return 0;
1772}
1773
aliguorif7b4a942009-01-07 17:40:15 +00001774#define SNAPSHOT_LIST 1
1775#define SNAPSHOT_CREATE 2
1776#define SNAPSHOT_APPLY 3
1777#define SNAPSHOT_DELETE 4
1778
Stuart Brady153859b2009-06-07 00:42:17 +01001779static int img_snapshot(int argc, char **argv)
aliguorif7b4a942009-01-07 17:40:15 +00001780{
1781 BlockDriverState *bs;
1782 QEMUSnapshotInfo sn;
1783 char *filename, *snapshot_name = NULL;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001784 int c, ret = 0, bdrv_oflags;
aliguorif7b4a942009-01-07 17:40:15 +00001785 int action = 0;
1786 qemu_timeval tv;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001787 bool quiet = false;
aliguorif7b4a942009-01-07 17:40:15 +00001788
Kevin Wolf710da702011-01-10 12:33:02 +01001789 bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
aliguorif7b4a942009-01-07 17:40:15 +00001790 /* Parse commandline parameters */
1791 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001792 c = getopt(argc, argv, "la:c:d:hq");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001793 if (c == -1) {
aliguorif7b4a942009-01-07 17:40:15 +00001794 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001795 }
aliguorif7b4a942009-01-07 17:40:15 +00001796 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001797 case '?':
aliguorif7b4a942009-01-07 17:40:15 +00001798 case 'h':
1799 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001800 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001801 case 'l':
1802 if (action) {
1803 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001804 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001805 }
1806 action = SNAPSHOT_LIST;
Naphtali Spreif5edb012010-01-17 16:48:13 +02001807 bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
aliguorif7b4a942009-01-07 17:40:15 +00001808 break;
1809 case 'a':
1810 if (action) {
1811 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001812 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001813 }
1814 action = SNAPSHOT_APPLY;
1815 snapshot_name = optarg;
1816 break;
1817 case 'c':
1818 if (action) {
1819 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001820 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001821 }
1822 action = SNAPSHOT_CREATE;
1823 snapshot_name = optarg;
1824 break;
1825 case 'd':
1826 if (action) {
1827 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001828 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001829 }
1830 action = SNAPSHOT_DELETE;
1831 snapshot_name = optarg;
1832 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001833 case 'q':
1834 quiet = true;
1835 break;
aliguorif7b4a942009-01-07 17:40:15 +00001836 }
1837 }
1838
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001839 if (optind >= argc) {
aliguorif7b4a942009-01-07 17:40:15 +00001840 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001841 }
aliguorif7b4a942009-01-07 17:40:15 +00001842 filename = argv[optind++];
1843
1844 /* Open the image */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001845 bs = bdrv_new_open(filename, NULL, bdrv_oflags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001846 if (!bs) {
1847 return 1;
1848 }
aliguorif7b4a942009-01-07 17:40:15 +00001849
1850 /* Perform the requested action */
1851 switch(action) {
1852 case SNAPSHOT_LIST:
1853 dump_snapshots(bs);
1854 break;
1855
1856 case SNAPSHOT_CREATE:
1857 memset(&sn, 0, sizeof(sn));
1858 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1859
1860 qemu_gettimeofday(&tv);
1861 sn.date_sec = tv.tv_sec;
1862 sn.date_nsec = tv.tv_usec * 1000;
1863
1864 ret = bdrv_snapshot_create(bs, &sn);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001865 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001866 error_report("Could not create snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001867 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001868 }
aliguorif7b4a942009-01-07 17:40:15 +00001869 break;
1870
1871 case SNAPSHOT_APPLY:
1872 ret = bdrv_snapshot_goto(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001873 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001874 error_report("Could not apply snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001875 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001876 }
aliguorif7b4a942009-01-07 17:40:15 +00001877 break;
1878
1879 case SNAPSHOT_DELETE:
1880 ret = bdrv_snapshot_delete(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001881 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001882 error_report("Could not delete snapshot '%s': %d (%s)",
aliguorif7b4a942009-01-07 17:40:15 +00001883 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001884 }
aliguorif7b4a942009-01-07 17:40:15 +00001885 break;
1886 }
1887
1888 /* Cleanup */
1889 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001890 if (ret) {
1891 return 1;
1892 }
Stuart Brady153859b2009-06-07 00:42:17 +01001893 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001894}
1895
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001896static int img_rebase(int argc, char **argv)
1897{
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001898 BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001899 BlockDriver *old_backing_drv, *new_backing_drv;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001900 char *filename;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001901 const char *fmt, *cache, *out_basefmt, *out_baseimg;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001902 int c, flags, ret;
1903 int unsafe = 0;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001904 int progress = 0;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001905 bool quiet = false;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001906
1907 /* Parse commandline parameters */
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001908 fmt = NULL;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001909 cache = BDRV_DEFAULT_CACHE;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001910 out_baseimg = NULL;
1911 out_basefmt = NULL;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001912 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001913 c = getopt(argc, argv, "uhf:F:b:pt:q");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001914 if (c == -1) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001915 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001916 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001917 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001918 case '?':
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001919 case 'h':
1920 help();
1921 return 0;
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001922 case 'f':
1923 fmt = optarg;
1924 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001925 case 'F':
1926 out_basefmt = optarg;
1927 break;
1928 case 'b':
1929 out_baseimg = optarg;
1930 break;
1931 case 'u':
1932 unsafe = 1;
1933 break;
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001934 case 'p':
1935 progress = 1;
1936 break;
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001937 case 't':
1938 cache = optarg;
1939 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001940 case 'q':
1941 quiet = true;
1942 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001943 }
1944 }
1945
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001946 if (quiet) {
1947 progress = 0;
1948 }
1949
Anthony Liguori9a9d9db2011-04-13 15:51:47 +01001950 if ((optind >= argc) || (!unsafe && !out_baseimg)) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001951 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001952 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001953 filename = argv[optind++];
1954
Jes Sorensen6b837bc2011-03-30 14:16:25 +02001955 qemu_progress_init(progress, 2.0);
1956 qemu_progress_print(0, 100);
1957
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001958 flags = BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
Stefan Hajnoczic3993cd2011-08-04 12:26:51 +01001959 ret = bdrv_parse_cache_flags(cache, &flags);
Federico Simoncelli661a0f72011-06-20 12:48:19 -04001960 if (ret < 0) {
1961 error_report("Invalid cache option: %s", cache);
1962 return -1;
1963 }
1964
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001965 /*
1966 * Open the images.
1967 *
1968 * Ignore the old backing file for unsafe rebase in case we want to correct
1969 * the reference to a renamed or moved backing file.
1970 */
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01001971 bs = bdrv_new_open(filename, fmt, flags, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001972 if (!bs) {
1973 return 1;
1974 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001975
1976 /* Find the right drivers for the backing files */
1977 old_backing_drv = NULL;
1978 new_backing_drv = NULL;
1979
1980 if (!unsafe && bs->backing_format[0] != '\0') {
1981 old_backing_drv = bdrv_find_format(bs->backing_format);
1982 if (old_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001983 error_report("Invalid format name: '%s'", bs->backing_format);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001984 ret = -1;
1985 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001986 }
1987 }
1988
1989 if (out_basefmt != NULL) {
1990 new_backing_drv = bdrv_find_format(out_basefmt);
1991 if (new_backing_drv == NULL) {
Jes Sorensen15654a62010-12-16 14:31:53 +01001992 error_report("Invalid format name: '%s'", out_basefmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001993 ret = -1;
1994 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001995 }
1996 }
1997
1998 /* For safe rebasing we need to compare old and new backing file */
1999 if (unsafe) {
2000 /* Make the compiler happy */
2001 bs_old_backing = NULL;
2002 bs_new_backing = NULL;
2003 } else {
2004 char backing_name[1024];
2005
2006 bs_old_backing = bdrv_new("old_backing");
2007 bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
Kevin Wolfde9c0ce2013-03-15 10:35:02 +01002008 ret = bdrv_open(bs_old_backing, backing_name, NULL, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002009 old_backing_drv);
2010 if (ret) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002011 error_report("Could not open old backing file '%s'", backing_name);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002012 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002013 }
Alex Bligha6166732012-10-16 13:46:18 +01002014 if (out_baseimg[0]) {
2015 bs_new_backing = bdrv_new("new_backing");
Kevin Wolfde9c0ce2013-03-15 10:35:02 +01002016 ret = bdrv_open(bs_new_backing, out_baseimg, NULL, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002017 new_backing_drv);
Alex Bligha6166732012-10-16 13:46:18 +01002018 if (ret) {
2019 error_report("Could not open new backing file '%s'",
2020 out_baseimg);
2021 goto out;
2022 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002023 }
2024 }
2025
2026 /*
2027 * Check each unallocated cluster in the COW file. If it is unallocated,
2028 * accesses go to the backing file. We must therefore compare this cluster
2029 * in the old and new backing file, and if they differ we need to copy it
2030 * from the old backing file into the COW file.
2031 *
2032 * If qemu-img crashes during this step, no harm is done. The content of
2033 * the image is the same as the original one at any time.
2034 */
2035 if (!unsafe) {
2036 uint64_t num_sectors;
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002037 uint64_t old_backing_num_sectors;
Alex Bligha6166732012-10-16 13:46:18 +01002038 uint64_t new_backing_num_sectors = 0;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002039 uint64_t sector;
Kevin Wolfcc60e322010-04-29 14:47:48 +02002040 int n;
TeLeMand6771bf2010-02-08 16:20:00 +08002041 uint8_t * buf_old;
2042 uint8_t * buf_new;
Kevin Wolf1f710492012-10-12 14:29:18 +02002043 float local_progress = 0;
TeLeMand6771bf2010-02-08 16:20:00 +08002044
Kevin Wolfbb1c0592011-08-08 14:09:12 +02002045 buf_old = qemu_blockalign(bs, IO_BUF_SIZE);
2046 buf_new = qemu_blockalign(bs, IO_BUF_SIZE);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002047
2048 bdrv_get_geometry(bs, &num_sectors);
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002049 bdrv_get_geometry(bs_old_backing, &old_backing_num_sectors);
Alex Bligha6166732012-10-16 13:46:18 +01002050 if (bs_new_backing) {
2051 bdrv_get_geometry(bs_new_backing, &new_backing_num_sectors);
2052 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002053
Kevin Wolf1f710492012-10-12 14:29:18 +02002054 if (num_sectors != 0) {
2055 local_progress = (float)100 /
2056 (num_sectors / MIN(num_sectors, IO_BUF_SIZE / 512));
2057 }
2058
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002059 for (sector = 0; sector < num_sectors; sector += n) {
2060
2061 /* How many sectors can we handle with the next read? */
2062 if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
2063 n = (IO_BUF_SIZE / 512);
2064 } else {
2065 n = num_sectors - sector;
2066 }
2067
2068 /* If the cluster is allocated, we don't need to take action */
Kevin Wolfcc60e322010-04-29 14:47:48 +02002069 ret = bdrv_is_allocated(bs, sector, n, &n);
2070 if (ret) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002071 continue;
2072 }
2073
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002074 /*
2075 * Read old and new backing file and take into consideration that
2076 * backing files may be smaller than the COW image.
2077 */
2078 if (sector >= old_backing_num_sectors) {
2079 memset(buf_old, 0, n * BDRV_SECTOR_SIZE);
2080 } else {
2081 if (sector + n > old_backing_num_sectors) {
2082 n = old_backing_num_sectors - sector;
2083 }
2084
2085 ret = bdrv_read(bs_old_backing, sector, buf_old, n);
2086 if (ret < 0) {
2087 error_report("error while reading from old backing file");
2088 goto out;
2089 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002090 }
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002091
Alex Bligha6166732012-10-16 13:46:18 +01002092 if (sector >= new_backing_num_sectors || !bs_new_backing) {
Kevin Wolf87a1b3e2011-12-07 12:42:10 +01002093 memset(buf_new, 0, n * BDRV_SECTOR_SIZE);
2094 } else {
2095 if (sector + n > new_backing_num_sectors) {
2096 n = new_backing_num_sectors - sector;
2097 }
2098
2099 ret = bdrv_read(bs_new_backing, sector, buf_new, n);
2100 if (ret < 0) {
2101 error_report("error while reading from new backing file");
2102 goto out;
2103 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002104 }
2105
2106 /* If they differ, we need to write to the COW file */
2107 uint64_t written = 0;
2108
2109 while (written < n) {
2110 int pnum;
2111
2112 if (compare_sectors(buf_old + written * 512,
Kevin Wolf60b1bd42010-02-17 12:32:59 +01002113 buf_new + written * 512, n - written, &pnum))
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002114 {
2115 ret = bdrv_write(bs, sector + written,
2116 buf_old + written * 512, pnum);
2117 if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002118 error_report("Error while writing to COW image: %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002119 strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002120 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002121 }
2122 }
2123
2124 written += pnum;
2125 }
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002126 qemu_progress_print(local_progress, 100);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002127 }
TeLeMand6771bf2010-02-08 16:20:00 +08002128
Kevin Wolfbb1c0592011-08-08 14:09:12 +02002129 qemu_vfree(buf_old);
2130 qemu_vfree(buf_new);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002131 }
2132
2133 /*
2134 * Change the backing file. All clusters that are different from the old
2135 * backing file are overwritten in the COW file now, so the visible content
2136 * doesn't change when we switch the backing file.
2137 */
Alex Bligha6166732012-10-16 13:46:18 +01002138 if (out_baseimg && *out_baseimg) {
2139 ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
2140 } else {
2141 ret = bdrv_change_backing_file(bs, NULL, NULL);
2142 }
2143
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002144 if (ret == -ENOSPC) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002145 error_report("Could not change the backing file to '%s': No "
2146 "space left in the file header", out_baseimg);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002147 } else if (ret < 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002148 error_report("Could not change the backing file to '%s': %s",
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002149 out_baseimg, strerror(-ret));
2150 }
2151
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002152 qemu_progress_print(100, 0);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002153 /*
2154 * TODO At this point it is possible to check if any clusters that are
2155 * allocated in the COW file are the same in the backing file. If so, they
2156 * could be dropped from the COW file. Don't do this before switching the
2157 * backing file, in case of a crash this would lead to corruption.
2158 */
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002159out:
Jes Sorensen6b837bc2011-03-30 14:16:25 +02002160 qemu_progress_end();
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002161 /* Cleanup */
2162 if (!unsafe) {
Kevin Wolfeb863ad2011-03-31 12:39:51 +02002163 if (bs_old_backing != NULL) {
2164 bdrv_delete(bs_old_backing);
2165 }
2166 if (bs_new_backing != NULL) {
2167 bdrv_delete(bs_new_backing);
2168 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002169 }
2170
2171 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002172 if (ret) {
2173 return 1;
2174 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01002175 return 0;
2176}
2177
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002178static int img_resize(int argc, char **argv)
2179{
2180 int c, ret, relative;
2181 const char *filename, *fmt, *size;
2182 int64_t n, total_size;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002183 bool quiet = false;
Jes Sorensen2a819982010-12-06 17:08:31 +01002184 BlockDriverState *bs = NULL;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002185 QemuOpts *param;
2186 static QemuOptsList resize_options = {
2187 .name = "resize_options",
2188 .head = QTAILQ_HEAD_INITIALIZER(resize_options.head),
2189 .desc = {
2190 {
2191 .name = BLOCK_OPT_SIZE,
2192 .type = QEMU_OPT_SIZE,
2193 .help = "Virtual disk size"
2194 }, {
2195 /* end of list */
2196 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002197 },
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002198 };
2199
Kevin Wolfe80fec72011-04-29 10:58:12 +02002200 /* Remove size from argv manually so that negative numbers are not treated
2201 * as options by getopt. */
2202 if (argc < 3) {
2203 help();
2204 return 1;
2205 }
2206
2207 size = argv[--argc];
2208
2209 /* Parse getopt arguments */
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002210 fmt = NULL;
2211 for(;;) {
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002212 c = getopt(argc, argv, "f:hq");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002213 if (c == -1) {
2214 break;
2215 }
2216 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01002217 case '?':
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002218 case 'h':
2219 help();
2220 break;
2221 case 'f':
2222 fmt = optarg;
2223 break;
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002224 case 'q':
2225 quiet = true;
2226 break;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002227 }
2228 }
Kevin Wolfe80fec72011-04-29 10:58:12 +02002229 if (optind >= argc) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002230 help();
2231 }
2232 filename = argv[optind++];
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002233
2234 /* Choose grow, shrink, or absolute resize mode */
2235 switch (size[0]) {
2236 case '+':
2237 relative = 1;
2238 size++;
2239 break;
2240 case '-':
2241 relative = -1;
2242 size++;
2243 break;
2244 default:
2245 relative = 0;
2246 break;
2247 }
2248
2249 /* Parse size */
Dong Xu Wange478b442012-12-06 14:47:22 +08002250 param = qemu_opts_create_nofail(&resize_options);
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002251 if (qemu_opt_set(param, BLOCK_OPT_SIZE, size)) {
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002252 /* Error message already printed when size parsing fails */
Jes Sorensen2a819982010-12-06 17:08:31 +01002253 ret = -1;
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002254 qemu_opts_del(param);
Jes Sorensen2a819982010-12-06 17:08:31 +01002255 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002256 }
Dong Xu Wang20caf0f2012-08-06 10:18:42 +08002257 n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
2258 qemu_opts_del(param);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002259
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002260 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR, true, quiet);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002261 if (!bs) {
Jes Sorensen2a819982010-12-06 17:08:31 +01002262 ret = -1;
2263 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002264 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002265
2266 if (relative) {
2267 total_size = bdrv_getlength(bs) + n * relative;
2268 } else {
2269 total_size = n;
2270 }
2271 if (total_size <= 0) {
Jes Sorensen15654a62010-12-16 14:31:53 +01002272 error_report("New image size must be positive");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002273 ret = -1;
2274 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002275 }
2276
2277 ret = bdrv_truncate(bs, total_size);
2278 switch (ret) {
2279 case 0:
Miroslav Rezaninaf382d432013-02-13 09:09:40 +01002280 qprintf(quiet, "Image resized.\n");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002281 break;
2282 case -ENOTSUP:
Kevin Wolf259b2172012-03-06 12:44:45 +01002283 error_report("This image does not support resize");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002284 break;
2285 case -EACCES:
Jes Sorensen15654a62010-12-16 14:31:53 +01002286 error_report("Image is read-only");
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002287 break;
2288 default:
Jes Sorensen15654a62010-12-16 14:31:53 +01002289 error_report("Error resizing image (%d)", -ret);
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002290 break;
2291 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002292out:
Jes Sorensen2a819982010-12-06 17:08:31 +01002293 if (bs) {
2294 bdrv_delete(bs);
2295 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09002296 if (ret) {
2297 return 1;
2298 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01002299 return 0;
2300}
2301
Anthony Liguoric227f092009-10-01 16:12:16 -05002302static const img_cmd_t img_cmds[] = {
Stuart Brady153859b2009-06-07 00:42:17 +01002303#define DEF(option, callback, arg_string) \
2304 { option, callback },
2305#include "qemu-img-cmds.h"
2306#undef DEF
2307#undef GEN_DOCS
2308 { NULL, NULL, },
2309};
2310
bellardea2384d2004-08-01 21:59:26 +00002311int main(int argc, char **argv)
2312{
Anthony Liguoric227f092009-10-01 16:12:16 -05002313 const img_cmd_t *cmd;
Stuart Brady153859b2009-06-07 00:42:17 +01002314 const char *cmdname;
bellardea2384d2004-08-01 21:59:26 +00002315
Kevin Wolf53f76e52010-12-16 15:10:32 +01002316 error_set_progname(argv[0]);
2317
Paolo Bonzini2592c592012-11-03 18:10:17 +01002318 qemu_init_main_loop();
bellardea2384d2004-08-01 21:59:26 +00002319 bdrv_init();
2320 if (argc < 2)
2321 help();
Stuart Brady153859b2009-06-07 00:42:17 +01002322 cmdname = argv[1];
aurel328f9b1572009-02-09 18:14:31 +00002323 argc--; argv++;
Stuart Brady153859b2009-06-07 00:42:17 +01002324
2325 /* find the command */
2326 for(cmd = img_cmds; cmd->name != NULL; cmd++) {
2327 if (!strcmp(cmdname, cmd->name)) {
2328 return cmd->handler(argc, argv);
2329 }
bellardea2384d2004-08-01 21:59:26 +00002330 }
Stuart Brady153859b2009-06-07 00:42:17 +01002331
2332 /* not found */
2333 help();
bellardea2384d2004-08-01 21:59:26 +00002334 return 0;
2335}