blob: 0ff179f00b11619b6b1f00ba77778ee5665c15fc [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 */
pbrookfaf07962007-11-11 02:51:17 +000024#include "qemu-common.h"
Kevin Wolf9ea2ea72009-05-18 16:42:11 +020025#include "qemu-option.h"
Kevin Wolf53f76e52010-12-16 15:10:32 +010026#include "qemu-error.h"
aliguorif7b4a942009-01-07 17:40:15 +000027#include "osdep.h"
Jes Sorensendc786bc2010-10-26 10:39:23 +020028#include "sysemu.h"
thsec36ba12007-09-16 21:59:02 +000029#include "block_int.h"
aliguori9230eaf2009-03-28 17:55:19 +000030#include <stdio.h>
bellardea2384d2004-08-01 21:59:26 +000031
bellarde8445332006-06-14 15:32:10 +000032#ifdef _WIN32
33#include <windows.h>
34#endif
35
Anthony Liguoric227f092009-10-01 16:12:16 -050036typedef struct img_cmd_t {
Stuart Brady153859b2009-06-07 00:42:17 +010037 const char *name;
38 int (*handler)(int argc, char **argv);
Anthony Liguoric227f092009-10-01 16:12:16 -050039} img_cmd_t;
Stuart Brady153859b2009-06-07 00:42:17 +010040
aurel32137519c2008-11-30 19:12:49 +000041/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
Stefan Hajnocziadfe0782010-04-13 10:29:35 +010042#define BDRV_O_FLAGS BDRV_O_CACHE_WB
aurel32137519c2008-11-30 19:12:49 +000043
Stefan Weil8b7968f2010-09-23 21:28:05 +020044static void GCC_FMT_ATTR(1, 2) error(const char *fmt, ...)
bellardea2384d2004-08-01 21:59:26 +000045{
46 va_list ap;
47 va_start(ap, fmt);
bellard57d1a2b2004-08-03 21:15:11 +000048 fprintf(stderr, "qemu-img: ");
bellardea2384d2004-08-01 21:59:26 +000049 vfprintf(stderr, fmt, ap);
50 fprintf(stderr, "\n");
bellardea2384d2004-08-01 21:59:26 +000051 va_end(ap);
52}
53
54static void format_print(void *opaque, const char *name)
55{
56 printf(" %s", name);
57}
58
blueswir1d2c639d2009-01-24 18:19:25 +000059/* Please keep in synch with qemu-img.texi */
pbrook3f379ab2007-11-11 03:33:13 +000060static void help(void)
bellardea2384d2004-08-01 21:59:26 +000061{
Paolo Bonzinie00291c2010-02-04 16:49:56 +010062 const char *help_msg =
63 "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
malc3f020d72010-02-08 12:04:56 +030064 "usage: qemu-img command [command options]\n"
65 "QEMU disk image utility\n"
66 "\n"
67 "Command syntax:\n"
Stuart Brady153859b2009-06-07 00:42:17 +010068#define DEF(option, callback, arg_string) \
69 " " arg_string "\n"
70#include "qemu-img-cmds.h"
71#undef DEF
72#undef GEN_DOCS
malc3f020d72010-02-08 12:04:56 +030073 "\n"
74 "Command parameters:\n"
75 " 'filename' is a disk image filename\n"
76 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
77 " 'size' is the disk image size in bytes. Optional suffixes\n"
78 " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
79 " and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
80 " 'output_filename' is the destination disk image filename\n"
81 " 'output_fmt' is the destination format\n"
82 " 'options' is a comma separated list of format specific options in a\n"
83 " name=value format. Use -o ? for an overview of the options supported by the\n"
84 " used format\n"
85 " '-c' indicates that target image must be compressed (qcow format only)\n"
86 " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
87 " match exactly. The image doesn't need a working backing file before\n"
88 " rebasing in this case (useful for renaming the backing file)\n"
89 " '-h' with or without a command shows this help and lists the supported formats\n"
90 "\n"
91 "Parameters to snapshot subcommand:\n"
92 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
93 " '-a' applies a snapshot (revert disk to saved state)\n"
94 " '-c' creates a snapshot\n"
95 " '-d' deletes a snapshot\n"
Paolo Bonzinie00291c2010-02-04 16:49:56 +010096 " '-l' lists all snapshots in the given image\n";
97
98 printf("%s\nSupported formats:", help_msg);
bellardea2384d2004-08-01 21:59:26 +000099 bdrv_iterate_format(format_print, NULL);
100 printf("\n");
101 exit(1);
102}
103
bellardea2384d2004-08-01 21:59:26 +0000104#if defined(WIN32)
105/* XXX: put correct support for win32 */
106static int read_password(char *buf, int buf_size)
107{
108 int c, i;
109 printf("Password: ");
110 fflush(stdout);
111 i = 0;
112 for(;;) {
113 c = getchar();
114 if (c == '\n')
115 break;
116 if (i < (buf_size - 1))
117 buf[i++] = c;
118 }
119 buf[i] = '\0';
120 return 0;
121}
122
123#else
124
125#include <termios.h>
126
127static struct termios oldtty;
128
129static void term_exit(void)
130{
131 tcsetattr (0, TCSANOW, &oldtty);
132}
133
134static void term_init(void)
135{
136 struct termios tty;
137
138 tcgetattr (0, &tty);
139 oldtty = tty;
140
141 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
142 |INLCR|IGNCR|ICRNL|IXON);
143 tty.c_oflag |= OPOST;
144 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
145 tty.c_cflag &= ~(CSIZE|PARENB);
146 tty.c_cflag |= CS8;
147 tty.c_cc[VMIN] = 1;
148 tty.c_cc[VTIME] = 0;
ths3b46e622007-09-17 08:09:54 +0000149
bellardea2384d2004-08-01 21:59:26 +0000150 tcsetattr (0, TCSANOW, &tty);
151
152 atexit(term_exit);
153}
154
pbrook3f379ab2007-11-11 03:33:13 +0000155static int read_password(char *buf, int buf_size)
bellardea2384d2004-08-01 21:59:26 +0000156{
157 uint8_t ch;
158 int i, ret;
159
160 printf("password: ");
161 fflush(stdout);
162 term_init();
163 i = 0;
164 for(;;) {
165 ret = read(0, &ch, 1);
166 if (ret == -1) {
167 if (errno == EAGAIN || errno == EINTR) {
168 continue;
169 } else {
170 ret = -1;
171 break;
172 }
173 } else if (ret == 0) {
174 ret = -1;
175 break;
176 } else {
177 if (ch == '\r') {
178 ret = 0;
179 break;
180 }
181 if (i < (buf_size - 1))
182 buf[i++] = ch;
183 }
184 }
185 term_exit();
186 buf[i] = '\0';
187 printf("\n");
188 return ret;
189}
190#endif
191
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100192static int print_block_option_help(const char *filename, const char *fmt)
193{
194 BlockDriver *drv, *proto_drv;
195 QEMUOptionParameter *create_options = NULL;
196
197 /* Find driver and parse its options */
198 drv = bdrv_find_format(fmt);
199 if (!drv) {
200 error("Unknown file format '%s'", fmt);
201 return 1;
202 }
203
204 proto_drv = bdrv_find_protocol(filename);
205 if (!proto_drv) {
206 error("Unknown protocol '%s'", filename);
207 return 1;
208 }
209
210 create_options = append_option_parameters(create_options,
211 drv->create_options);
212 create_options = append_option_parameters(create_options,
213 proto_drv->create_options);
214 print_option_help(create_options);
215 free_option_parameters(create_options);
216 return 0;
217}
218
bellard75c23802004-08-27 21:28:58 +0000219static BlockDriverState *bdrv_new_open(const char *filename,
Sheng Yang9bc378c2010-01-29 10:15:06 +0800220 const char *fmt,
Stefan Hajnoczif163d072010-04-13 10:29:34 +0100221 int flags)
bellard75c23802004-08-27 21:28:58 +0000222{
223 BlockDriverState *bs;
224 BlockDriver *drv;
225 char password[256];
226
227 bs = bdrv_new("");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900228 if (!bs) {
bellard75c23802004-08-27 21:28:58 +0000229 error("Not enough memory");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900230 goto fail;
231 }
bellard75c23802004-08-27 21:28:58 +0000232 if (fmt) {
233 drv = bdrv_find_format(fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900234 if (!drv) {
bellard75c23802004-08-27 21:28:58 +0000235 error("Unknown file format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900236 goto fail;
237 }
bellard75c23802004-08-27 21:28:58 +0000238 } else {
239 drv = NULL;
240 }
Kevin Wolfd6e90982010-03-31 14:40:27 +0200241 if (bdrv_open(bs, filename, flags, drv) < 0) {
bellard75c23802004-08-27 21:28:58 +0000242 error("Could not open '%s'", filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900243 goto fail;
bellard75c23802004-08-27 21:28:58 +0000244 }
245 if (bdrv_is_encrypted(bs)) {
246 printf("Disk image '%s' is encrypted.\n", filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900247 if (read_password(password, sizeof(password)) < 0) {
bellard75c23802004-08-27 21:28:58 +0000248 error("No password given");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900249 goto fail;
250 }
251 if (bdrv_set_key(bs, password) < 0) {
bellard75c23802004-08-27 21:28:58 +0000252 error("invalid password");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900253 goto fail;
254 }
bellard75c23802004-08-27 21:28:58 +0000255 }
256 return bs;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900257fail:
258 if (bs) {
259 bdrv_delete(bs);
260 }
261 return NULL;
bellard75c23802004-08-27 21:28:58 +0000262}
263
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900264static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
Jes Sorenseneec77d92010-12-07 17:44:34 +0100265 const char *base_filename,
266 const char *base_fmt)
Kevin Wolfefa84d42009-05-18 16:42:12 +0200267{
Kevin Wolfefa84d42009-05-18 16:42:12 +0200268 if (base_filename) {
269 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
270 error("Backing file not supported for file format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900271 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200272 }
273 }
274 if (base_fmt) {
275 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
276 error("Backing file format not supported for file format '%s'", fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900277 return -1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200278 }
279 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900280 return 0;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200281}
282
bellardea2384d2004-08-01 21:59:26 +0000283static int img_create(int argc, char **argv)
284{
Jes Sorenseneec77d92010-12-07 17:44:34 +0100285 int c, ret = 0;
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100286 uint64_t img_size = -1;
bellardea2384d2004-08-01 21:59:26 +0000287 const char *fmt = "raw";
aliguori9230eaf2009-03-28 17:55:19 +0000288 const char *base_fmt = NULL;
bellardea2384d2004-08-01 21:59:26 +0000289 const char *filename;
290 const char *base_filename = NULL;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200291 char *options = NULL;
ths3b46e622007-09-17 08:09:54 +0000292
bellardea2384d2004-08-01 21:59:26 +0000293 for(;;) {
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200294 c = getopt(argc, argv, "F:b:f:he6o:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100295 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000296 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100297 }
bellardea2384d2004-08-01 21:59:26 +0000298 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100299 case '?':
bellardea2384d2004-08-01 21:59:26 +0000300 case 'h':
301 help();
302 break;
aliguori9230eaf2009-03-28 17:55:19 +0000303 case 'F':
304 base_fmt = optarg;
305 break;
bellardea2384d2004-08-01 21:59:26 +0000306 case 'b':
307 base_filename = optarg;
308 break;
309 case 'f':
310 fmt = optarg;
311 break;
312 case 'e':
Jes Sorenseneec77d92010-12-07 17:44:34 +0100313 error("qemu-img: option -e is deprecated, please use \'-o "
314 "encryption\' instead!");
315 return 1;
thsd8871c52007-10-24 16:11:42 +0000316 case '6':
Jes Sorenseneec77d92010-12-07 17:44:34 +0100317 error("qemu-img: option -6 is deprecated, please use \'-o "
318 "compat6\' instead!");
319 return 1;
Kevin Wolf9ea2ea72009-05-18 16:42:11 +0200320 case 'o':
321 options = optarg;
322 break;
bellardea2384d2004-08-01 21:59:26 +0000323 }
324 }
aliguori9230eaf2009-03-28 17:55:19 +0000325
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900326 /* Get the filename */
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100327 if (optind >= argc) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900328 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100329 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900330 filename = argv[optind++];
331
Jes Sorensen1da7cfb2010-12-09 14:17:25 +0100332 /* Get image size, if specified */
333 if (optind < argc) {
334 ssize_t sval;
335 sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);
336 if (sval < 0) {
337 error("Invalid image size specified! You may use k, M, G or "
338 "T suffixes for ");
339 error("kilobytes, megabytes, gigabytes and terabytes.");
340 ret = -1;
341 goto out;
342 }
343 img_size = (uint64_t)sval;
344 }
345
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100346 if (options && !strcmp(options, "?")) {
347 ret = print_block_option_help(filename, fmt);
348 goto out;
349 }
350
Jes Sorensenf88e1a42010-12-16 13:52:15 +0100351 ret = bdrv_img_create(filename, fmt, base_filename, base_fmt,
352 options, img_size, BDRV_O_FLAGS);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900353out:
354 if (ret) {
355 return 1;
356 }
bellardea2384d2004-08-01 21:59:26 +0000357 return 0;
358}
359
Kevin Wolfe076f332010-06-29 11:43:13 +0200360/*
361 * Checks an image for consistency. Exit codes:
362 *
363 * 0 - Check completed, image is good
364 * 1 - Check not completed because of internal errors
365 * 2 - Check completed, image is corrupted
366 * 3 - Check completed, image has leaked clusters, but is good otherwise
367 */
aliguori15859692009-04-21 23:11:53 +0000368static int img_check(int argc, char **argv)
369{
370 int c, ret;
371 const char *filename, *fmt;
aliguori15859692009-04-21 23:11:53 +0000372 BlockDriverState *bs;
Kevin Wolfe076f332010-06-29 11:43:13 +0200373 BdrvCheckResult result;
aliguori15859692009-04-21 23:11:53 +0000374
375 fmt = NULL;
376 for(;;) {
377 c = getopt(argc, argv, "f:h");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100378 if (c == -1) {
aliguori15859692009-04-21 23:11:53 +0000379 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100380 }
aliguori15859692009-04-21 23:11:53 +0000381 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100382 case '?':
aliguori15859692009-04-21 23:11:53 +0000383 case 'h':
384 help();
385 break;
386 case 'f':
387 fmt = optarg;
388 break;
389 }
390 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100391 if (optind >= argc) {
aliguori15859692009-04-21 23:11:53 +0000392 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100393 }
aliguori15859692009-04-21 23:11:53 +0000394 filename = argv[optind++];
395
Stefan Hajnocziadfe0782010-04-13 10:29:35 +0100396 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900397 if (!bs) {
398 return 1;
399 }
Kevin Wolfe076f332010-06-29 11:43:13 +0200400 ret = bdrv_check(bs, &result);
401
402 if (ret == -ENOTSUP) {
aliguori15859692009-04-21 23:11:53 +0000403 error("This image format does not support checks");
Kevin Wolfe076f332010-06-29 11:43:13 +0200404 bdrv_delete(bs);
405 return 1;
406 }
407
408 if (!(result.corruptions || result.leaks || result.check_errors)) {
409 printf("No errors were found on the image.\n");
410 } else {
411 if (result.corruptions) {
412 printf("\n%d errors were found on the image.\n"
413 "Data may be corrupted, or further writes to the image "
414 "may corrupt it.\n",
415 result.corruptions);
aliguori15859692009-04-21 23:11:53 +0000416 }
Kevin Wolfe076f332010-06-29 11:43:13 +0200417
418 if (result.leaks) {
419 printf("\n%d leaked clusters were found on the image.\n"
420 "This means waste of disk space, but no harm to data.\n",
421 result.leaks);
422 }
423
424 if (result.check_errors) {
425 printf("\n%d internal errors have occurred during the check.\n",
426 result.check_errors);
427 }
aliguori15859692009-04-21 23:11:53 +0000428 }
429
430 bdrv_delete(bs);
Kevin Wolfe076f332010-06-29 11:43:13 +0200431
432 if (ret < 0 || result.check_errors) {
433 printf("\nAn error has occurred during the check: %s\n"
434 "The check is not complete and may have missed error.\n",
435 strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900436 return 1;
437 }
Kevin Wolfe076f332010-06-29 11:43:13 +0200438
439 if (result.corruptions) {
440 return 2;
441 } else if (result.leaks) {
442 return 3;
443 } else {
444 return 0;
445 }
aliguori15859692009-04-21 23:11:53 +0000446}
447
bellardea2384d2004-08-01 21:59:26 +0000448static int img_commit(int argc, char **argv)
449{
450 int c, ret;
451 const char *filename, *fmt;
bellardea2384d2004-08-01 21:59:26 +0000452 BlockDriverState *bs;
453
454 fmt = NULL;
455 for(;;) {
456 c = getopt(argc, argv, "f:h");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100457 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000458 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100459 }
bellardea2384d2004-08-01 21:59:26 +0000460 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100461 case '?':
bellardea2384d2004-08-01 21:59:26 +0000462 case 'h':
463 help();
464 break;
465 case 'f':
466 fmt = optarg;
467 break;
468 }
469 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100470 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +0000471 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100472 }
bellardea2384d2004-08-01 21:59:26 +0000473 filename = argv[optind++];
474
Stefan Hajnocziadfe0782010-04-13 10:29:35 +0100475 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900476 if (!bs) {
477 return 1;
478 }
bellardea2384d2004-08-01 21:59:26 +0000479 ret = bdrv_commit(bs);
480 switch(ret) {
481 case 0:
482 printf("Image committed.\n");
483 break;
484 case -ENOENT:
485 error("No disk inserted");
486 break;
487 case -EACCES:
488 error("Image is read-only");
489 break;
490 case -ENOTSUP:
491 error("Image is already committed");
492 break;
493 default:
494 error("Error while committing image");
495 break;
496 }
497
498 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900499 if (ret) {
500 return 1;
501 }
bellardea2384d2004-08-01 21:59:26 +0000502 return 0;
503}
504
505static int is_not_zero(const uint8_t *sector, int len)
506{
507 int i;
508 len >>= 2;
509 for(i = 0;i < len; i++) {
510 if (((uint32_t *)sector)[i] != 0)
511 return 1;
512 }
513 return 0;
514}
515
thsf58c7b32008-06-05 21:53:49 +0000516/*
517 * Returns true iff the first sector pointed to by 'buf' contains at least
518 * a non-NUL byte.
519 *
520 * 'pnum' is set to the number of sectors (including and immediately following
521 * the first one) that are known to be in the same allocated/unallocated state.
522 */
bellardea2384d2004-08-01 21:59:26 +0000523static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
524{
525 int v, i;
526
527 if (n <= 0) {
528 *pnum = 0;
529 return 0;
530 }
531 v = is_not_zero(buf, 512);
532 for(i = 1; i < n; i++) {
533 buf += 512;
534 if (v != is_not_zero(buf, 512))
535 break;
536 }
537 *pnum = i;
538 return v;
539}
540
Kevin Wolf3e85c6f2010-01-12 12:55:18 +0100541/*
542 * Compares two buffers sector by sector. Returns 0 if the first sector of both
543 * buffers matches, non-zero otherwise.
544 *
545 * pnum is set to the number of sectors (including and immediately following
546 * the first one) that are known to have the same comparison result
547 */
548static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
549 int *pnum)
550{
551 int res, i;
552
553 if (n <= 0) {
554 *pnum = 0;
555 return 0;
556 }
557
558 res = !!memcmp(buf1, buf2, 512);
559 for(i = 1; i < n; i++) {
560 buf1 += 512;
561 buf2 += 512;
562
563 if (!!memcmp(buf1, buf2, 512) != res) {
564 break;
565 }
566 }
567
568 *pnum = i;
569 return res;
570}
571
Kevin Wolf80ee15a2009-09-15 12:30:43 +0200572#define IO_BUF_SIZE (2 * 1024 * 1024)
bellardea2384d2004-08-01 21:59:26 +0000573
574static int img_convert(int argc, char **argv)
575{
Jes Sorenseneec77d92010-12-07 17:44:34 +0100576 int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
thsf58c7b32008-06-05 21:53:49 +0000577 const char *fmt, *out_fmt, *out_baseimg, *out_filename;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900578 BlockDriver *drv, *proto_drv;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900579 BlockDriverState **bs = NULL, *out_bs = NULL;
ths96b8f132007-12-17 01:35:20 +0000580 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
581 uint64_t bs_sectors;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900582 uint8_t * buf = NULL;
bellardea2384d2004-08-01 21:59:26 +0000583 const uint8_t *buf1;
bellardfaea38e2006-08-05 21:31:00 +0000584 BlockDriverInfo bdi;
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900585 QEMUOptionParameter *param = NULL, *create_options = NULL;
Kevin Wolfa18953f2010-10-14 15:46:04 +0200586 QEMUOptionParameter *out_baseimg_param;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200587 char *options = NULL;
edison51ef6722010-09-21 19:58:41 -0700588 const char *snapshot_name = NULL;
bellardea2384d2004-08-01 21:59:26 +0000589
590 fmt = NULL;
591 out_fmt = "raw";
thsf58c7b32008-06-05 21:53:49 +0000592 out_baseimg = NULL;
Jes Sorenseneec77d92010-12-07 17:44:34 +0100593 compress = 0;
bellardea2384d2004-08-01 21:59:26 +0000594 for(;;) {
edison51ef6722010-09-21 19:58:41 -0700595 c = getopt(argc, argv, "f:O:B:s:hce6o:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100596 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +0000597 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100598 }
bellardea2384d2004-08-01 21:59:26 +0000599 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +0100600 case '?':
bellardea2384d2004-08-01 21:59:26 +0000601 case 'h':
602 help();
603 break;
604 case 'f':
605 fmt = optarg;
606 break;
607 case 'O':
608 out_fmt = optarg;
609 break;
thsf58c7b32008-06-05 21:53:49 +0000610 case 'B':
611 out_baseimg = optarg;
612 break;
bellardea2384d2004-08-01 21:59:26 +0000613 case 'c':
Jes Sorenseneec77d92010-12-07 17:44:34 +0100614 compress = 1;
bellardea2384d2004-08-01 21:59:26 +0000615 break;
616 case 'e':
Jes Sorenseneec77d92010-12-07 17:44:34 +0100617 error("qemu-img: option -e is deprecated, please use \'-o "
618 "encryption\' instead!");
619 return 1;
thsec36ba12007-09-16 21:59:02 +0000620 case '6':
Jes Sorenseneec77d92010-12-07 17:44:34 +0100621 error("qemu-img: option -6 is deprecated, please use \'-o "
622 "compat6\' instead!");
623 return 1;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200624 case 'o':
625 options = optarg;
626 break;
edison51ef6722010-09-21 19:58:41 -0700627 case 's':
628 snapshot_name = optarg;
629 break;
bellardea2384d2004-08-01 21:59:26 +0000630 }
631 }
ths3b46e622007-09-17 08:09:54 +0000632
balrog926c2d22007-10-31 01:11:44 +0000633 bs_n = argc - optind - 1;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100634 if (bs_n < 1) {
635 help();
636 }
balrog926c2d22007-10-31 01:11:44 +0000637
638 out_filename = argv[argc - 1];
thsf58c7b32008-06-05 21:53:49 +0000639
Jes Sorensen4ac8aac2010-12-06 15:25:38 +0100640 if (options && !strcmp(options, "?")) {
641 ret = print_block_option_help(out_filename, out_fmt);
642 goto out;
643 }
644
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900645 if (bs_n > 1 && out_baseimg) {
thsf58c7b32008-06-05 21:53:49 +0000646 error("-B makes no sense when concatenating multiple input images");
Jes Sorensen31ca34b2010-12-06 15:25:36 +0100647 ret = -1;
648 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900649 }
balrog926c2d22007-10-31 01:11:44 +0000650
Jes Sorensen5bdf61f2010-12-06 15:25:35 +0100651 bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *));
balrog926c2d22007-10-31 01:11:44 +0000652
653 total_sectors = 0;
654 for (bs_i = 0; bs_i < bs_n; bs_i++) {
Stefan Hajnocziadfe0782010-04-13 10:29:35 +0100655 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900656 if (!bs[bs_i]) {
balrog926c2d22007-10-31 01:11:44 +0000657 error("Could not open '%s'", argv[optind + bs_i]);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900658 ret = -1;
659 goto out;
660 }
balrog926c2d22007-10-31 01:11:44 +0000661 bdrv_get_geometry(bs[bs_i], &bs_sectors);
662 total_sectors += bs_sectors;
663 }
bellardea2384d2004-08-01 21:59:26 +0000664
edison51ef6722010-09-21 19:58:41 -0700665 if (snapshot_name != NULL) {
666 if (bs_n > 1) {
667 error("No support for concatenating multiple snapshot\n");
668 ret = -1;
669 goto out;
670 }
671 if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
672 error("Failed to load snapshot\n");
673 ret = -1;
674 goto out;
675 }
676 }
677
Kevin Wolfefa84d42009-05-18 16:42:12 +0200678 /* Find driver and parse its options */
bellardea2384d2004-08-01 21:59:26 +0000679 drv = bdrv_find_format(out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900680 if (!drv) {
thsd34dda52007-02-10 22:59:40 +0000681 error("Unknown file format '%s'", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900682 ret = -1;
683 goto out;
684 }
balrog926c2d22007-10-31 01:11:44 +0000685
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900686 proto_drv = bdrv_find_protocol(out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900687 if (!proto_drv) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900688 error("Unknown protocol '%s'", out_filename);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900689 ret = -1;
690 goto out;
691 }
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900692
693 create_options = append_option_parameters(create_options,
694 drv->create_options);
695 create_options = append_option_parameters(create_options,
696 proto_drv->create_options);
Kevin Wolfdb08adf2009-06-04 15:39:38 +0200697
Kevin Wolfefa84d42009-05-18 16:42:12 +0200698 if (options) {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900699 param = parse_option_parameters(options, create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +0200700 if (param == NULL) {
701 error("Invalid options for file format '%s'.", out_fmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900702 ret = -1;
703 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200704 }
705 } else {
MORITA Kazutakab50cbab2010-05-26 11:35:36 +0900706 param = parse_option_parameters("", create_options, param);
Kevin Wolfefa84d42009-05-18 16:42:12 +0200707 }
708
709 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
Jes Sorenseneec77d92010-12-07 17:44:34 +0100710 ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900711 if (ret < 0) {
712 goto out;
713 }
Kevin Wolfefa84d42009-05-18 16:42:12 +0200714
Kevin Wolfa18953f2010-10-14 15:46:04 +0200715 /* Get backing file name if -o backing_file was used */
716 out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
717 if (out_baseimg_param) {
718 out_baseimg = out_baseimg_param->value.s;
719 }
720
Kevin Wolfefa84d42009-05-18 16:42:12 +0200721 /* Check if compression is supported */
Jes Sorenseneec77d92010-12-07 17:44:34 +0100722 if (compress) {
Kevin Wolfefa84d42009-05-18 16:42:12 +0200723 QEMUOptionParameter *encryption =
724 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
725
726 if (!drv->bdrv_write_compressed) {
727 error("Compression not supported for this file format");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900728 ret = -1;
729 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200730 }
731
732 if (encryption && encryption->value.n) {
733 error("Compression and encryption not supported at the same time");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900734 ret = -1;
735 goto out;
Kevin Wolfefa84d42009-05-18 16:42:12 +0200736 }
737 }
738
739 /* Create the new image */
740 ret = bdrv_create(drv, out_filename, param);
bellardea2384d2004-08-01 21:59:26 +0000741 if (ret < 0) {
742 if (ret == -ENOTSUP) {
aliguori93c65b42009-04-05 17:40:43 +0000743 error("Formatting not supported for file format '%s'", out_fmt);
aurel326e9ea0c2009-04-15 14:42:46 +0000744 } else if (ret == -EFBIG) {
745 error("The image size is too large for file format '%s'", out_fmt);
bellardea2384d2004-08-01 21:59:26 +0000746 } else {
Juan Quintela3e7896d2010-03-04 10:00:38 +0100747 error("%s: error while converting %s: %s", out_filename, out_fmt, strerror(-ret));
bellardea2384d2004-08-01 21:59:26 +0000748 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900749 goto out;
bellardea2384d2004-08-01 21:59:26 +0000750 }
ths3b46e622007-09-17 08:09:54 +0000751
Kevin Wolf1bd8e172010-08-31 13:44:25 +0200752 out_bs = bdrv_new_open(out_filename, out_fmt,
753 BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900754 if (!out_bs) {
755 ret = -1;
756 goto out;
757 }
bellardea2384d2004-08-01 21:59:26 +0000758
balrog926c2d22007-10-31 01:11:44 +0000759 bs_i = 0;
760 bs_offset = 0;
761 bdrv_get_geometry(bs[0], &bs_sectors);
TeLeMand6771bf2010-02-08 16:20:00 +0800762 buf = qemu_malloc(IO_BUF_SIZE);
balrog926c2d22007-10-31 01:11:44 +0000763
Jes Sorenseneec77d92010-12-07 17:44:34 +0100764 if (compress) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900765 ret = bdrv_get_info(out_bs, &bdi);
766 if (ret < 0) {
bellardfaea38e2006-08-05 21:31:00 +0000767 error("could not get block driver info");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900768 goto out;
769 }
bellardfaea38e2006-08-05 21:31:00 +0000770 cluster_size = bdi.cluster_size;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900771 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
bellardea2384d2004-08-01 21:59:26 +0000772 error("invalid cluster size");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900773 ret = -1;
774 goto out;
775 }
bellardea2384d2004-08-01 21:59:26 +0000776 cluster_sectors = cluster_size >> 9;
777 sector_num = 0;
778 for(;;) {
balrog926c2d22007-10-31 01:11:44 +0000779 int64_t bs_num;
780 int remainder;
781 uint8_t *buf2;
782
bellardea2384d2004-08-01 21:59:26 +0000783 nb_sectors = total_sectors - sector_num;
784 if (nb_sectors <= 0)
785 break;
786 if (nb_sectors >= cluster_sectors)
787 n = cluster_sectors;
788 else
789 n = nb_sectors;
balrog926c2d22007-10-31 01:11:44 +0000790
791 bs_num = sector_num - bs_offset;
792 assert (bs_num >= 0);
793 remainder = n;
794 buf2 = buf;
795 while (remainder > 0) {
796 int nlow;
797 while (bs_num == bs_sectors) {
798 bs_i++;
799 assert (bs_i < bs_n);
800 bs_offset += bs_sectors;
801 bdrv_get_geometry(bs[bs_i], &bs_sectors);
802 bs_num = 0;
Blue Swirl0bfcd592010-05-22 08:02:12 +0000803 /* printf("changing part: sector_num=%" PRId64 ", "
804 "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
805 "\n", sector_num, bs_i, bs_offset, bs_sectors); */
balrog926c2d22007-10-31 01:11:44 +0000806 }
807 assert (bs_num < bs_sectors);
808
809 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
810
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900811 ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
812 if (ret < 0) {
balrog926c2d22007-10-31 01:11:44 +0000813 error("error while reading");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900814 goto out;
815 }
balrog926c2d22007-10-31 01:11:44 +0000816
817 buf2 += nlow * 512;
818 bs_num += nlow;
819
820 remainder -= nlow;
821 }
822 assert (remainder == 0);
823
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100824 if (n < cluster_sectors) {
bellardea2384d2004-08-01 21:59:26 +0000825 memset(buf + n * 512, 0, cluster_size - n * 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100826 }
bellardea2384d2004-08-01 21:59:26 +0000827 if (is_not_zero(buf, cluster_size)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900828 ret = bdrv_write_compressed(out_bs, sector_num, buf,
829 cluster_sectors);
830 if (ret != 0) {
bellardec3757d2006-06-14 15:50:07 +0000831 error("error while compressing sector %" PRId64,
832 sector_num);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900833 goto out;
834 }
bellardea2384d2004-08-01 21:59:26 +0000835 }
836 sector_num += n;
837 }
bellardfaea38e2006-08-05 21:31:00 +0000838 /* signal EOF to align */
839 bdrv_write_compressed(out_bs, 0, NULL, 0);
bellardea2384d2004-08-01 21:59:26 +0000840 } else {
Kevin Wolff2feebb2010-04-14 17:30:35 +0200841 int has_zero_init = bdrv_has_zero_init(out_bs);
842
thsf58c7b32008-06-05 21:53:49 +0000843 sector_num = 0; // total number of sectors converted so far
bellardea2384d2004-08-01 21:59:26 +0000844 for(;;) {
845 nb_sectors = total_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100846 if (nb_sectors <= 0) {
bellardea2384d2004-08-01 21:59:26 +0000847 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100848 }
849 if (nb_sectors >= (IO_BUF_SIZE / 512)) {
bellardea2384d2004-08-01 21:59:26 +0000850 n = (IO_BUF_SIZE / 512);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100851 } else {
bellardea2384d2004-08-01 21:59:26 +0000852 n = nb_sectors;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100853 }
balrog926c2d22007-10-31 01:11:44 +0000854
855 while (sector_num - bs_offset >= bs_sectors) {
856 bs_i ++;
857 assert (bs_i < bs_n);
858 bs_offset += bs_sectors;
859 bdrv_get_geometry(bs[bs_i], &bs_sectors);
Blue Swirl0bfcd592010-05-22 08:02:12 +0000860 /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
861 "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
balrog926c2d22007-10-31 01:11:44 +0000862 sector_num, bs_i, bs_offset, bs_sectors); */
863 }
864
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100865 if (n > bs_offset + bs_sectors - sector_num) {
balrog926c2d22007-10-31 01:11:44 +0000866 n = bs_offset + bs_sectors - sector_num;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +0100867 }
balrog926c2d22007-10-31 01:11:44 +0000868
Kevin Wolff2feebb2010-04-14 17:30:35 +0200869 if (has_zero_init) {
Akkarit Sangpetchd0320442009-07-17 10:02:15 +0200870 /* If the output image is being created as a copy on write image,
871 assume that sectors which are unallocated in the input image
872 are present in both the output's and input's base images (no
873 need to copy them). */
874 if (out_baseimg) {
875 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
876 n, &n1)) {
877 sector_num += n1;
878 continue;
879 }
880 /* The next 'n1' sectors are allocated in the input image. Copy
881 only those as they may be followed by unallocated sectors. */
882 n = n1;
aliguori93c65b42009-04-05 17:40:43 +0000883 }
aliguori93c65b42009-04-05 17:40:43 +0000884 } else {
885 n1 = n;
thsf58c7b32008-06-05 21:53:49 +0000886 }
887
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900888 ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
889 if (ret < 0) {
bellardea2384d2004-08-01 21:59:26 +0000890 error("error while reading");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900891 goto out;
892 }
bellardea2384d2004-08-01 21:59:26 +0000893 /* NOTE: at the same time we convert, we do not write zero
894 sectors to have a chance to compress the image. Ideally, we
895 should add a specific call to have the info to go faster */
896 buf1 = buf;
897 while (n > 0) {
thsf58c7b32008-06-05 21:53:49 +0000898 /* If the output image is being created as a copy on write image,
899 copy all sectors even the ones containing only NUL bytes,
aliguori93c65b42009-04-05 17:40:43 +0000900 because they may differ from the sectors in the base image.
901
902 If the output is to a host device, we also write out
903 sectors that are entirely 0, since whatever data was
904 already there is garbage, not 0s. */
Kevin Wolff2feebb2010-04-14 17:30:35 +0200905 if (!has_zero_init || out_baseimg ||
aliguori93c65b42009-04-05 17:40:43 +0000906 is_allocated_sectors(buf1, n, &n1)) {
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900907 ret = bdrv_write(out_bs, sector_num, buf1, n1);
908 if (ret < 0) {
bellardea2384d2004-08-01 21:59:26 +0000909 error("error while writing");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900910 goto out;
911 }
bellardea2384d2004-08-01 21:59:26 +0000912 }
913 sector_num += n1;
914 n -= n1;
915 buf1 += n1 * 512;
916 }
917 }
918 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900919out:
920 free_option_parameters(create_options);
921 free_option_parameters(param);
TeLeMand6771bf2010-02-08 16:20:00 +0800922 qemu_free(buf);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900923 if (out_bs) {
924 bdrv_delete(out_bs);
925 }
Jes Sorensen31ca34b2010-12-06 15:25:36 +0100926 if (bs) {
927 for (bs_i = 0; bs_i < bs_n; bs_i++) {
928 if (bs[bs_i]) {
929 bdrv_delete(bs[bs_i]);
930 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900931 }
Jes Sorensen31ca34b2010-12-06 15:25:36 +0100932 qemu_free(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900933 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +0900934 if (ret) {
935 return 1;
936 }
bellardea2384d2004-08-01 21:59:26 +0000937 return 0;
938}
939
bellard57d1a2b2004-08-03 21:15:11 +0000940#ifdef _WIN32
941static int64_t get_allocated_file_size(const char *filename)
942{
bellarde8445332006-06-14 15:32:10 +0000943 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
944 get_compressed_t get_compressed;
bellard57d1a2b2004-08-03 21:15:11 +0000945 struct _stati64 st;
bellarde8445332006-06-14 15:32:10 +0000946
947 /* WinNT support GetCompressedFileSize to determine allocate size */
948 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
949 if (get_compressed) {
950 DWORD high, low;
951 low = get_compressed(filename, &high);
952 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
953 return (((int64_t) high) << 32) + low;
954 }
955
ths5fafdf22007-09-16 21:08:06 +0000956 if (_stati64(filename, &st) < 0)
bellard57d1a2b2004-08-03 21:15:11 +0000957 return -1;
958 return st.st_size;
959}
960#else
961static int64_t get_allocated_file_size(const char *filename)
962{
963 struct stat st;
ths5fafdf22007-09-16 21:08:06 +0000964 if (stat(filename, &st) < 0)
bellard57d1a2b2004-08-03 21:15:11 +0000965 return -1;
966 return (int64_t)st.st_blocks * 512;
967}
968#endif
969
bellardfaea38e2006-08-05 21:31:00 +0000970static void dump_snapshots(BlockDriverState *bs)
971{
972 QEMUSnapshotInfo *sn_tab, *sn;
973 int nb_sns, i;
974 char buf[256];
975
976 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
977 if (nb_sns <= 0)
978 return;
979 printf("Snapshot list:\n");
980 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
981 for(i = 0; i < nb_sns; i++) {
982 sn = &sn_tab[i];
983 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
984 }
985 qemu_free(sn_tab);
986}
987
bellardea2384d2004-08-01 21:59:26 +0000988static int img_info(int argc, char **argv)
989{
990 int c;
991 const char *filename, *fmt;
bellardea2384d2004-08-01 21:59:26 +0000992 BlockDriverState *bs;
993 char fmt_name[128], size_buf[128], dsize_buf[128];
ths96b8f132007-12-17 01:35:20 +0000994 uint64_t total_sectors;
995 int64_t allocated_size;
bellard93b6b2a2006-08-01 15:51:11 +0000996 char backing_filename[1024];
997 char backing_filename2[1024];
bellardfaea38e2006-08-05 21:31:00 +0000998 BlockDriverInfo bdi;
bellardea2384d2004-08-01 21:59:26 +0000999
1000 fmt = NULL;
1001 for(;;) {
1002 c = getopt(argc, argv, "f:h");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001003 if (c == -1) {
bellardea2384d2004-08-01 21:59:26 +00001004 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001005 }
bellardea2384d2004-08-01 21:59:26 +00001006 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001007 case '?':
bellardea2384d2004-08-01 21:59:26 +00001008 case 'h':
1009 help();
1010 break;
1011 case 'f':
1012 fmt = optarg;
1013 break;
1014 }
1015 }
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001016 if (optind >= argc) {
bellardea2384d2004-08-01 21:59:26 +00001017 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001018 }
bellardea2384d2004-08-01 21:59:26 +00001019 filename = argv[optind++];
1020
Stefan Hajnocziadfe0782010-04-13 10:29:35 +01001021 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001022 if (!bs) {
1023 return 1;
1024 }
bellardea2384d2004-08-01 21:59:26 +00001025 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
1026 bdrv_get_geometry(bs, &total_sectors);
1027 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
bellard57d1a2b2004-08-03 21:15:11 +00001028 allocated_size = get_allocated_file_size(filename);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001029 if (allocated_size < 0) {
blueswir1a10ea302008-08-24 10:30:33 +00001030 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001031 } else {
ths5fafdf22007-09-16 21:08:06 +00001032 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
bellardde167e42005-04-28 21:15:08 +00001033 allocated_size);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001034 }
bellardea2384d2004-08-01 21:59:26 +00001035 printf("image: %s\n"
1036 "file format: %s\n"
bellardec3757d2006-06-14 15:50:07 +00001037 "virtual size: %s (%" PRId64 " bytes)\n"
bellardea2384d2004-08-01 21:59:26 +00001038 "disk size: %s\n",
ths5fafdf22007-09-16 21:08:06 +00001039 filename, fmt_name, size_buf,
bellardec3757d2006-06-14 15:50:07 +00001040 (total_sectors * 512),
bellardea2384d2004-08-01 21:59:26 +00001041 dsize_buf);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001042 if (bdrv_is_encrypted(bs)) {
bellardea2384d2004-08-01 21:59:26 +00001043 printf("encrypted: yes\n");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001044 }
bellardfaea38e2006-08-05 21:31:00 +00001045 if (bdrv_get_info(bs, &bdi) >= 0) {
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001046 if (bdi.cluster_size != 0) {
bellardfaea38e2006-08-05 21:31:00 +00001047 printf("cluster_size: %d\n", bdi.cluster_size);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001048 }
bellardfaea38e2006-08-05 21:31:00 +00001049 }
bellard93b6b2a2006-08-01 15:51:11 +00001050 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
bellardfaea38e2006-08-05 21:31:00 +00001051 if (backing_filename[0] != '\0') {
bellard93b6b2a2006-08-01 15:51:11 +00001052 path_combine(backing_filename2, sizeof(backing_filename2),
1053 filename, backing_filename);
ths5fafdf22007-09-16 21:08:06 +00001054 printf("backing file: %s (actual path: %s)\n",
bellard93b6b2a2006-08-01 15:51:11 +00001055 backing_filename,
1056 backing_filename2);
bellardfaea38e2006-08-05 21:31:00 +00001057 }
1058 dump_snapshots(bs);
bellardea2384d2004-08-01 21:59:26 +00001059 bdrv_delete(bs);
1060 return 0;
1061}
1062
aliguorif7b4a942009-01-07 17:40:15 +00001063#define SNAPSHOT_LIST 1
1064#define SNAPSHOT_CREATE 2
1065#define SNAPSHOT_APPLY 3
1066#define SNAPSHOT_DELETE 4
1067
Stuart Brady153859b2009-06-07 00:42:17 +01001068static int img_snapshot(int argc, char **argv)
aliguorif7b4a942009-01-07 17:40:15 +00001069{
1070 BlockDriverState *bs;
1071 QEMUSnapshotInfo sn;
1072 char *filename, *snapshot_name = NULL;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001073 int c, ret = 0, bdrv_oflags;
aliguorif7b4a942009-01-07 17:40:15 +00001074 int action = 0;
1075 qemu_timeval tv;
1076
Naphtali Spreif5edb012010-01-17 16:48:13 +02001077 bdrv_oflags = BDRV_O_RDWR;
aliguorif7b4a942009-01-07 17:40:15 +00001078 /* Parse commandline parameters */
1079 for(;;) {
1080 c = getopt(argc, argv, "la:c:d:h");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001081 if (c == -1) {
aliguorif7b4a942009-01-07 17:40:15 +00001082 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001083 }
aliguorif7b4a942009-01-07 17:40:15 +00001084 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001085 case '?':
aliguorif7b4a942009-01-07 17:40:15 +00001086 case 'h':
1087 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001088 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001089 case 'l':
1090 if (action) {
1091 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001092 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001093 }
1094 action = SNAPSHOT_LIST;
Naphtali Spreif5edb012010-01-17 16:48:13 +02001095 bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
aliguorif7b4a942009-01-07 17:40:15 +00001096 break;
1097 case 'a':
1098 if (action) {
1099 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001100 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001101 }
1102 action = SNAPSHOT_APPLY;
1103 snapshot_name = optarg;
1104 break;
1105 case 'c':
1106 if (action) {
1107 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001108 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001109 }
1110 action = SNAPSHOT_CREATE;
1111 snapshot_name = optarg;
1112 break;
1113 case 'd':
1114 if (action) {
1115 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001116 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001117 }
1118 action = SNAPSHOT_DELETE;
1119 snapshot_name = optarg;
1120 break;
1121 }
1122 }
1123
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001124 if (optind >= argc) {
aliguorif7b4a942009-01-07 17:40:15 +00001125 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001126 }
aliguorif7b4a942009-01-07 17:40:15 +00001127 filename = argv[optind++];
1128
1129 /* Open the image */
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001130 bs = bdrv_new_open(filename, NULL, bdrv_oflags);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001131 if (!bs) {
1132 return 1;
1133 }
aliguorif7b4a942009-01-07 17:40:15 +00001134
1135 /* Perform the requested action */
1136 switch(action) {
1137 case SNAPSHOT_LIST:
1138 dump_snapshots(bs);
1139 break;
1140
1141 case SNAPSHOT_CREATE:
1142 memset(&sn, 0, sizeof(sn));
1143 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1144
1145 qemu_gettimeofday(&tv);
1146 sn.date_sec = tv.tv_sec;
1147 sn.date_nsec = tv.tv_usec * 1000;
1148
1149 ret = bdrv_snapshot_create(bs, &sn);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001150 if (ret) {
aliguorif7b4a942009-01-07 17:40:15 +00001151 error("Could not create snapshot '%s': %d (%s)",
1152 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001153 }
aliguorif7b4a942009-01-07 17:40:15 +00001154 break;
1155
1156 case SNAPSHOT_APPLY:
1157 ret = bdrv_snapshot_goto(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001158 if (ret) {
aliguorif7b4a942009-01-07 17:40:15 +00001159 error("Could not apply snapshot '%s': %d (%s)",
1160 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001161 }
aliguorif7b4a942009-01-07 17:40:15 +00001162 break;
1163
1164 case SNAPSHOT_DELETE:
1165 ret = bdrv_snapshot_delete(bs, snapshot_name);
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001166 if (ret) {
aliguorif7b4a942009-01-07 17:40:15 +00001167 error("Could not delete snapshot '%s': %d (%s)",
1168 snapshot_name, ret, strerror(-ret));
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001169 }
aliguorif7b4a942009-01-07 17:40:15 +00001170 break;
1171 }
1172
1173 /* Cleanup */
1174 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001175 if (ret) {
1176 return 1;
1177 }
Stuart Brady153859b2009-06-07 00:42:17 +01001178 return 0;
aliguorif7b4a942009-01-07 17:40:15 +00001179}
1180
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001181static int img_rebase(int argc, char **argv)
1182{
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001183 BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001184 BlockDriver *old_backing_drv, *new_backing_drv;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001185 char *filename;
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001186 const char *fmt, *out_basefmt, *out_baseimg;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001187 int c, flags, ret;
1188 int unsafe = 0;
1189
1190 /* Parse commandline parameters */
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001191 fmt = NULL;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001192 out_baseimg = NULL;
1193 out_basefmt = NULL;
1194
1195 for(;;) {
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001196 c = getopt(argc, argv, "uhf:F:b:");
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001197 if (c == -1) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001198 break;
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001199 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001200 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001201 case '?':
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001202 case 'h':
1203 help();
1204 return 0;
Kevin Wolfe53dbee2010-03-02 12:14:31 +01001205 case 'f':
1206 fmt = optarg;
1207 break;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001208 case 'F':
1209 out_basefmt = optarg;
1210 break;
1211 case 'b':
1212 out_baseimg = optarg;
1213 break;
1214 case 'u':
1215 unsafe = 1;
1216 break;
1217 }
1218 }
1219
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001220 if ((optind >= argc) || !out_baseimg) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001221 help();
Jes Sorensenb8fb60d2010-12-06 15:25:39 +01001222 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001223 filename = argv[optind++];
1224
1225 /*
1226 * Open the images.
1227 *
1228 * Ignore the old backing file for unsafe rebase in case we want to correct
1229 * the reference to a renamed or moved backing file.
1230 */
Stefan Hajnocziadfe0782010-04-13 10:29:35 +01001231 flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
Stefan Hajnoczif163d072010-04-13 10:29:34 +01001232 bs = bdrv_new_open(filename, fmt, flags);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001233 if (!bs) {
1234 return 1;
1235 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001236
1237 /* Find the right drivers for the backing files */
1238 old_backing_drv = NULL;
1239 new_backing_drv = NULL;
1240
1241 if (!unsafe && bs->backing_format[0] != '\0') {
1242 old_backing_drv = bdrv_find_format(bs->backing_format);
1243 if (old_backing_drv == NULL) {
1244 error("Invalid format name: '%s'", bs->backing_format);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001245 ret = -1;
1246 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001247 }
1248 }
1249
1250 if (out_basefmt != NULL) {
1251 new_backing_drv = bdrv_find_format(out_basefmt);
1252 if (new_backing_drv == NULL) {
1253 error("Invalid format name: '%s'", out_basefmt);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001254 ret = -1;
1255 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001256 }
1257 }
1258
1259 /* For safe rebasing we need to compare old and new backing file */
1260 if (unsafe) {
1261 /* Make the compiler happy */
1262 bs_old_backing = NULL;
1263 bs_new_backing = NULL;
1264 } else {
1265 char backing_name[1024];
1266
1267 bs_old_backing = bdrv_new("old_backing");
1268 bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001269 ret = bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,
1270 old_backing_drv);
1271 if (ret) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001272 error("Could not open old backing file '%s'", backing_name);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001273 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001274 }
1275
1276 bs_new_backing = bdrv_new("new_backing");
Kevin Wolfcdbae852010-08-17 18:58:55 +02001277 ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS,
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001278 new_backing_drv);
1279 if (ret) {
Kevin Wolf584771e2010-02-17 12:33:17 +01001280 error("Could not open new backing file '%s'", out_baseimg);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001281 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001282 }
1283 }
1284
1285 /*
1286 * Check each unallocated cluster in the COW file. If it is unallocated,
1287 * accesses go to the backing file. We must therefore compare this cluster
1288 * in the old and new backing file, and if they differ we need to copy it
1289 * from the old backing file into the COW file.
1290 *
1291 * If qemu-img crashes during this step, no harm is done. The content of
1292 * the image is the same as the original one at any time.
1293 */
1294 if (!unsafe) {
1295 uint64_t num_sectors;
1296 uint64_t sector;
Kevin Wolfcc60e322010-04-29 14:47:48 +02001297 int n;
TeLeMand6771bf2010-02-08 16:20:00 +08001298 uint8_t * buf_old;
1299 uint8_t * buf_new;
1300
1301 buf_old = qemu_malloc(IO_BUF_SIZE);
1302 buf_new = qemu_malloc(IO_BUF_SIZE);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001303
1304 bdrv_get_geometry(bs, &num_sectors);
1305
1306 for (sector = 0; sector < num_sectors; sector += n) {
1307
1308 /* How many sectors can we handle with the next read? */
1309 if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
1310 n = (IO_BUF_SIZE / 512);
1311 } else {
1312 n = num_sectors - sector;
1313 }
1314
1315 /* If the cluster is allocated, we don't need to take action */
Kevin Wolfcc60e322010-04-29 14:47:48 +02001316 ret = bdrv_is_allocated(bs, sector, n, &n);
1317 if (ret) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001318 continue;
1319 }
1320
1321 /* Read old and new backing file */
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001322 ret = bdrv_read(bs_old_backing, sector, buf_old, n);
1323 if (ret < 0) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001324 error("error while reading from old backing file");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001325 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001326 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001327 ret = bdrv_read(bs_new_backing, sector, buf_new, n);
1328 if (ret < 0) {
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001329 error("error while reading from new backing file");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001330 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001331 }
1332
1333 /* If they differ, we need to write to the COW file */
1334 uint64_t written = 0;
1335
1336 while (written < n) {
1337 int pnum;
1338
1339 if (compare_sectors(buf_old + written * 512,
Kevin Wolf60b1bd42010-02-17 12:32:59 +01001340 buf_new + written * 512, n - written, &pnum))
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001341 {
1342 ret = bdrv_write(bs, sector + written,
1343 buf_old + written * 512, pnum);
1344 if (ret < 0) {
1345 error("Error while writing to COW image: %s",
1346 strerror(-ret));
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001347 goto out;
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001348 }
1349 }
1350
1351 written += pnum;
1352 }
1353 }
TeLeMand6771bf2010-02-08 16:20:00 +08001354
1355 qemu_free(buf_old);
1356 qemu_free(buf_new);
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001357 }
1358
1359 /*
1360 * Change the backing file. All clusters that are different from the old
1361 * backing file are overwritten in the COW file now, so the visible content
1362 * doesn't change when we switch the backing file.
1363 */
1364 ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
1365 if (ret == -ENOSPC) {
1366 error("Could not change the backing file to '%s': No space left in "
1367 "the file header", out_baseimg);
1368 } else if (ret < 0) {
1369 error("Could not change the backing file to '%s': %s",
1370 out_baseimg, strerror(-ret));
1371 }
1372
1373 /*
1374 * TODO At this point it is possible to check if any clusters that are
1375 * allocated in the COW file are the same in the backing file. If so, they
1376 * could be dropped from the COW file. Don't do this before switching the
1377 * backing file, in case of a crash this would lead to corruption.
1378 */
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001379out:
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001380 /* Cleanup */
1381 if (!unsafe) {
1382 bdrv_delete(bs_old_backing);
1383 bdrv_delete(bs_new_backing);
1384 }
1385
1386 bdrv_delete(bs);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001387 if (ret) {
1388 return 1;
1389 }
Kevin Wolf3e85c6f2010-01-12 12:55:18 +01001390 return 0;
1391}
1392
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001393static int img_resize(int argc, char **argv)
1394{
1395 int c, ret, relative;
1396 const char *filename, *fmt, *size;
1397 int64_t n, total_size;
Jes Sorensen2a819982010-12-06 17:08:31 +01001398 BlockDriverState *bs = NULL;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001399 QEMUOptionParameter *param;
1400 QEMUOptionParameter resize_options[] = {
1401 {
1402 .name = BLOCK_OPT_SIZE,
1403 .type = OPT_SIZE,
1404 .help = "Virtual disk size"
1405 },
1406 { NULL }
1407 };
1408
1409 fmt = NULL;
1410 for(;;) {
1411 c = getopt(argc, argv, "f:h");
1412 if (c == -1) {
1413 break;
1414 }
1415 switch(c) {
Jes Sorensenef873942010-12-06 15:25:40 +01001416 case '?':
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001417 case 'h':
1418 help();
1419 break;
1420 case 'f':
1421 fmt = optarg;
1422 break;
1423 }
1424 }
1425 if (optind + 1 >= argc) {
1426 help();
1427 }
1428 filename = argv[optind++];
1429 size = argv[optind++];
1430
1431 /* Choose grow, shrink, or absolute resize mode */
1432 switch (size[0]) {
1433 case '+':
1434 relative = 1;
1435 size++;
1436 break;
1437 case '-':
1438 relative = -1;
1439 size++;
1440 break;
1441 default:
1442 relative = 0;
1443 break;
1444 }
1445
1446 /* Parse size */
1447 param = parse_option_parameters("", resize_options, NULL);
1448 if (set_option_parameter(param, BLOCK_OPT_SIZE, size)) {
1449 /* Error message already printed when size parsing fails */
Jes Sorensen2a819982010-12-06 17:08:31 +01001450 ret = -1;
1451 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001452 }
1453 n = get_option_parameter(param, BLOCK_OPT_SIZE)->value.n;
1454 free_option_parameters(param);
1455
1456 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001457 if (!bs) {
Jes Sorensen2a819982010-12-06 17:08:31 +01001458 ret = -1;
1459 goto out;
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001460 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001461
1462 if (relative) {
1463 total_size = bdrv_getlength(bs) + n * relative;
1464 } else {
1465 total_size = n;
1466 }
1467 if (total_size <= 0) {
1468 error("New image size must be positive");
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001469 ret = -1;
1470 goto out;
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001471 }
1472
1473 ret = bdrv_truncate(bs, total_size);
1474 switch (ret) {
1475 case 0:
1476 printf("Image resized.\n");
1477 break;
1478 case -ENOTSUP:
1479 error("This image format does not support resize");
1480 break;
1481 case -EACCES:
1482 error("Image is read-only");
1483 break;
1484 default:
1485 error("Error resizing image (%d)", -ret);
1486 break;
1487 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001488out:
Jes Sorensen2a819982010-12-06 17:08:31 +01001489 if (bs) {
1490 bdrv_delete(bs);
1491 }
MORITA Kazutakac2abcce2010-06-21 04:26:35 +09001492 if (ret) {
1493 return 1;
1494 }
Stefan Hajnocziae6b0ed2010-04-24 09:12:12 +01001495 return 0;
1496}
1497
Anthony Liguoric227f092009-10-01 16:12:16 -05001498static const img_cmd_t img_cmds[] = {
Stuart Brady153859b2009-06-07 00:42:17 +01001499#define DEF(option, callback, arg_string) \
1500 { option, callback },
1501#include "qemu-img-cmds.h"
1502#undef DEF
1503#undef GEN_DOCS
1504 { NULL, NULL, },
1505};
1506
bellardea2384d2004-08-01 21:59:26 +00001507int main(int argc, char **argv)
1508{
Anthony Liguoric227f092009-10-01 16:12:16 -05001509 const img_cmd_t *cmd;
Stuart Brady153859b2009-06-07 00:42:17 +01001510 const char *cmdname;
bellardea2384d2004-08-01 21:59:26 +00001511
Kevin Wolf53f76e52010-12-16 15:10:32 +01001512 error_set_progname(argv[0]);
1513
bellardea2384d2004-08-01 21:59:26 +00001514 bdrv_init();
1515 if (argc < 2)
1516 help();
Stuart Brady153859b2009-06-07 00:42:17 +01001517 cmdname = argv[1];
aurel328f9b1572009-02-09 18:14:31 +00001518 argc--; argv++;
Stuart Brady153859b2009-06-07 00:42:17 +01001519
1520 /* find the command */
1521 for(cmd = img_cmds; cmd->name != NULL; cmd++) {
1522 if (!strcmp(cmdname, cmd->name)) {
1523 return cmd->handler(argc, argv);
1524 }
bellardea2384d2004-08-01 21:59:26 +00001525 }
Stuart Brady153859b2009-06-07 00:42:17 +01001526
1527 /* not found */
1528 help();
bellardea2384d2004-08-01 21:59:26 +00001529 return 0;
1530}