Annotation of qemu/qemu-img.c, revision 1.1.1.11
1.1 root 1: /*
1.1.1.3 root 2: * QEMU disk image utility
1.1.1.4 root 3: *
4: * Copyright (c) 2003-2008 Fabrice Bellard
5: *
1.1 root 6: * 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: */
1.1.1.4 root 24: #include "qemu-common.h"
1.1.1.8 root 25: #include "qemu-option.h"
1.1.1.5 root 26: #include "osdep.h"
1.1.1.4 root 27: #include "block_int.h"
1.1.1.8 root 28: #include <stdio.h>
1.1 root 29:
1.1.1.2 root 30: #ifdef _WIN32
31: #include <windows.h>
32: #endif
33:
1.1.1.8 root 34: typedef struct img_cmd_t {
35: const char *name;
36: int (*handler)(int argc, char **argv);
37: } img_cmd_t;
38:
1.1.1.5 root 39: /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
1.1.1.11! root 40: #define BDRV_O_FLAGS BDRV_O_CACHE_WB
1.1 root 41:
1.1.1.11! root 42: static void error(const char *fmt, ...)
1.1 root 43: {
44: va_list ap;
45: va_start(ap, fmt);
46: fprintf(stderr, "qemu-img: ");
47: vfprintf(stderr, fmt, ap);
48: fprintf(stderr, "\n");
49: va_end(ap);
50: }
51:
52: static void format_print(void *opaque, const char *name)
53: {
54: printf(" %s", name);
55: }
56:
1.1.1.5 root 57: /* Please keep in synch with qemu-img.texi */
1.1.1.4 root 58: static void help(void)
1.1 root 59: {
1.1.1.11! root 60: const char *help_msg =
! 61: "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
1.1 root 62: "usage: qemu-img command [command options]\n"
63: "QEMU disk image utility\n"
64: "\n"
65: "Command syntax:\n"
1.1.1.8 root 66: #define DEF(option, callback, arg_string) \
67: " " arg_string "\n"
68: #include "qemu-img-cmds.h"
69: #undef DEF
70: #undef GEN_DOCS
1.1 root 71: "\n"
72: "Command parameters:\n"
73: " 'filename' is a disk image filename\n"
74: " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
1.1.1.9 root 75: " 'size' is the disk image size in bytes. Optional suffixes\n"
76: " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
77: " and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
1.1 root 78: " 'output_filename' is the destination disk image filename\n"
79: " 'output_fmt' is the destination format\n"
1.1.1.8 root 80: " 'options' is a comma separated list of format specific options in a\n"
81: " name=value format. Use -o ? for an overview of the options supported by the\n"
82: " used format\n"
1.1 root 83: " '-c' indicates that target image must be compressed (qcow format only)\n"
1.1.1.11! root 84: " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
! 85: " match exactly. The image doesn't need a working backing file before\n"
! 86: " rebasing in this case (useful for renaming the backing file)\n"
1.1.1.5 root 87: " '-h' with or without a command shows this help and lists the supported formats\n"
88: "\n"
89: "Parameters to snapshot subcommand:\n"
90: " 'snapshot' is the name of the snapshot to create, apply or delete\n"
91: " '-a' applies a snapshot (revert disk to saved state)\n"
92: " '-c' creates a snapshot\n"
93: " '-d' deletes a snapshot\n"
1.1.1.11! root 94: " '-l' lists all snapshots in the given image\n";
! 95:
! 96: printf("%s\nSupported formats:", help_msg);
1.1 root 97: bdrv_iterate_format(format_print, NULL);
98: printf("\n");
99: exit(1);
100: }
101:
102: #if defined(WIN32)
103: /* XXX: put correct support for win32 */
104: static int read_password(char *buf, int buf_size)
105: {
106: int c, i;
107: printf("Password: ");
108: fflush(stdout);
109: i = 0;
110: for(;;) {
111: c = getchar();
112: if (c == '\n')
113: break;
114: if (i < (buf_size - 1))
115: buf[i++] = c;
116: }
117: buf[i] = '\0';
118: return 0;
119: }
120:
121: #else
122:
123: #include <termios.h>
124:
125: static struct termios oldtty;
126:
127: static void term_exit(void)
128: {
129: tcsetattr (0, TCSANOW, &oldtty);
130: }
131:
132: static void term_init(void)
133: {
134: struct termios tty;
135:
136: tcgetattr (0, &tty);
137: oldtty = tty;
138:
139: tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
140: |INLCR|IGNCR|ICRNL|IXON);
141: tty.c_oflag |= OPOST;
142: tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
143: tty.c_cflag &= ~(CSIZE|PARENB);
144: tty.c_cflag |= CS8;
145: tty.c_cc[VMIN] = 1;
146: tty.c_cc[VTIME] = 0;
1.1.1.4 root 147:
1.1 root 148: tcsetattr (0, TCSANOW, &tty);
149:
150: atexit(term_exit);
151: }
152:
1.1.1.4 root 153: static int read_password(char *buf, int buf_size)
1.1 root 154: {
155: uint8_t ch;
156: int i, ret;
157:
158: printf("password: ");
159: fflush(stdout);
160: term_init();
161: i = 0;
162: for(;;) {
163: ret = read(0, &ch, 1);
164: if (ret == -1) {
165: if (errno == EAGAIN || errno == EINTR) {
166: continue;
167: } else {
168: ret = -1;
169: break;
170: }
171: } else if (ret == 0) {
172: ret = -1;
173: break;
174: } else {
175: if (ch == '\r') {
176: ret = 0;
177: break;
178: }
179: if (i < (buf_size - 1))
180: buf[i++] = ch;
181: }
182: }
183: term_exit();
184: buf[i] = '\0';
185: printf("\n");
186: return ret;
187: }
188: #endif
189:
190: static BlockDriverState *bdrv_new_open(const char *filename,
1.1.1.11! root 191: const char *fmt,
! 192: int flags)
1.1 root 193: {
194: BlockDriverState *bs;
195: BlockDriver *drv;
196: char password[256];
197:
198: bs = bdrv_new("");
1.1.1.11! root 199: if (!bs) {
1.1 root 200: error("Not enough memory");
1.1.1.11! root 201: goto fail;
! 202: }
1.1 root 203: if (fmt) {
204: drv = bdrv_find_format(fmt);
1.1.1.11! root 205: if (!drv) {
1.1 root 206: error("Unknown file format '%s'", fmt);
1.1.1.11! root 207: goto fail;
! 208: }
1.1 root 209: } else {
210: drv = NULL;
211: }
1.1.1.11! root 212: if (bdrv_open(bs, filename, flags, drv) < 0) {
1.1 root 213: error("Could not open '%s'", filename);
1.1.1.11! root 214: goto fail;
1.1 root 215: }
216: if (bdrv_is_encrypted(bs)) {
217: printf("Disk image '%s' is encrypted.\n", filename);
1.1.1.11! root 218: if (read_password(password, sizeof(password)) < 0) {
1.1 root 219: error("No password given");
1.1.1.11! root 220: goto fail;
! 221: }
! 222: if (bdrv_set_key(bs, password) < 0) {
1.1 root 223: error("invalid password");
1.1.1.11! root 224: goto fail;
! 225: }
1.1 root 226: }
227: return bs;
1.1.1.11! root 228: fail:
! 229: if (bs) {
! 230: bdrv_delete(bs);
! 231: }
! 232: return NULL;
1.1 root 233: }
234:
1.1.1.11! root 235: static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
1.1.1.8 root 236: int flags, const char *base_filename, const char *base_fmt)
237: {
238: if (flags & BLOCK_FLAG_ENCRYPT) {
239: if (set_option_parameter(list, BLOCK_OPT_ENCRYPT, "on")) {
240: error("Encryption not supported for file format '%s'", fmt);
1.1.1.11! root 241: return -1;
1.1.1.8 root 242: }
243: }
244: if (flags & BLOCK_FLAG_COMPAT6) {
245: if (set_option_parameter(list, BLOCK_OPT_COMPAT6, "on")) {
246: error("VMDK version 6 not supported for file format '%s'", fmt);
1.1.1.11! root 247: return -1;
1.1.1.8 root 248: }
249: }
250:
251: if (base_filename) {
252: if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
253: error("Backing file not supported for file format '%s'", fmt);
1.1.1.11! root 254: return -1;
1.1.1.8 root 255: }
256: }
257: if (base_fmt) {
258: if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
259: error("Backing file format not supported for file format '%s'", fmt);
1.1.1.11! root 260: return -1;
1.1.1.8 root 261: }
262: }
1.1.1.11! root 263: return 0;
1.1.1.8 root 264: }
265:
1.1 root 266: static int img_create(int argc, char **argv)
267: {
1.1.1.11! root 268: int c, ret = 0, flags;
1.1 root 269: const char *fmt = "raw";
1.1.1.8 root 270: const char *base_fmt = NULL;
1.1 root 271: const char *filename;
272: const char *base_filename = NULL;
1.1.1.11! root 273: BlockDriver *drv, *proto_drv;
! 274: QEMUOptionParameter *param = NULL, *create_options = NULL;
1.1.1.8 root 275: char *options = NULL;
1.1.1.4 root 276:
277: flags = 0;
1.1 root 278: for(;;) {
1.1.1.8 root 279: c = getopt(argc, argv, "F:b:f:he6o:");
1.1 root 280: if (c == -1)
281: break;
282: switch(c) {
283: case 'h':
284: help();
285: break;
1.1.1.8 root 286: case 'F':
287: base_fmt = optarg;
288: break;
1.1 root 289: case 'b':
290: base_filename = optarg;
291: break;
292: case 'f':
293: fmt = optarg;
294: break;
295: case 'e':
1.1.1.4 root 296: flags |= BLOCK_FLAG_ENCRYPT;
297: break;
298: case '6':
299: flags |= BLOCK_FLAG_COMPAT6;
1.1 root 300: break;
1.1.1.8 root 301: case 'o':
302: options = optarg;
303: break;
1.1 root 304: }
305: }
1.1.1.8 root 306:
1.1.1.11! root 307: /* Get the filename */
! 308: if (optind >= argc)
! 309: help();
! 310: filename = argv[optind++];
! 311:
1.1.1.8 root 312: /* Find driver and parse its options */
313: drv = bdrv_find_format(fmt);
1.1.1.11! root 314: if (!drv) {
1.1.1.8 root 315: error("Unknown file format '%s'", fmt);
1.1.1.11! root 316: return 1;
! 317: }
! 318:
! 319: proto_drv = bdrv_find_protocol(filename);
! 320: if (!proto_drv) {
! 321: error("Unknown protocol '%s'", filename);
! 322: return 1;
! 323: }
! 324:
! 325: create_options = append_option_parameters(create_options,
! 326: drv->create_options);
! 327: create_options = append_option_parameters(create_options,
! 328: proto_drv->create_options);
1.1.1.8 root 329:
330: if (options && !strcmp(options, "?")) {
1.1.1.11! root 331: print_option_help(create_options);
! 332: goto out;
1.1.1.8 root 333: }
334:
1.1.1.9 root 335: /* Create parameter list with default values */
1.1.1.11! root 336: param = parse_option_parameters("", create_options, param);
1.1.1.9 root 337: set_option_parameter_int(param, BLOCK_OPT_SIZE, -1);
338:
339: /* Parse -o options */
1.1.1.8 root 340: if (options) {
1.1.1.11! root 341: param = parse_option_parameters(options, create_options, param);
1.1.1.8 root 342: if (param == NULL) {
343: error("Invalid options for file format '%s'.", fmt);
1.1.1.11! root 344: ret = -1;
! 345: goto out;
1.1.1.8 root 346: }
347: }
348:
349: /* Add size to parameters */
350: if (optind < argc) {
351: set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
352: }
353:
354: /* Add old-style options to parameters */
1.1.1.11! root 355: ret = add_old_style_options(fmt, param, flags, base_filename, base_fmt);
! 356: if (ret < 0) {
! 357: goto out;
! 358: }
1.1.1.8 root 359:
360: // The size for the image must always be specified, with one exception:
361: // If we are using a backing file, we can obtain the size from there
1.1.1.9 root 362: if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
1.1.1.8 root 363:
364: QEMUOptionParameter *backing_file =
365: get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
366: QEMUOptionParameter *backing_fmt =
367: get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
368:
369: if (backing_file && backing_file->value.s) {
370: BlockDriverState *bs;
371: uint64_t size;
372: const char *fmt = NULL;
373: char buf[32];
374:
375: if (backing_fmt && backing_fmt->value.s) {
376: if (bdrv_find_format(backing_fmt->value.s)) {
377: fmt = backing_fmt->value.s;
378: } else {
379: error("Unknown backing file format '%s'",
380: backing_fmt->value.s);
1.1.1.11! root 381: ret = -1;
! 382: goto out;
1.1.1.8 root 383: }
384: }
385:
1.1.1.11! root 386: bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS);
! 387: if (!bs) {
! 388: ret = -1;
! 389: goto out;
! 390: }
1.1.1.8 root 391: bdrv_get_geometry(bs, &size);
392: size *= 512;
393: bdrv_delete(bs);
394:
395: snprintf(buf, sizeof(buf), "%" PRId64, size);
396: set_option_parameter(param, BLOCK_OPT_SIZE, buf);
1.1 root 397: } else {
1.1.1.8 root 398: error("Image creation needs a size parameter");
1.1.1.11! root 399: ret = -1;
! 400: goto out;
1.1 root 401: }
402: }
1.1.1.8 root 403:
404: printf("Formatting '%s', fmt=%s ", filename, fmt);
405: print_option_parameters(param);
406: puts("");
407:
408: ret = bdrv_create(drv, filename, param);
1.1.1.11! root 409: free_option_parameters(create_options);
1.1.1.8 root 410: free_option_parameters(param);
411:
1.1 root 412: if (ret < 0) {
413: if (ret == -ENOTSUP) {
414: error("Formatting or formatting option not supported for file format '%s'", fmt);
1.1.1.7 root 415: } else if (ret == -EFBIG) {
416: error("The image size is too large for file format '%s'", fmt);
1.1 root 417: } else {
1.1.1.11! root 418: error("%s: error while creating %s: %s", filename, fmt, strerror(-ret));
1.1 root 419: }
420: }
1.1.1.11! root 421: out:
! 422: if (ret) {
! 423: return 1;
! 424: }
1.1 root 425: return 0;
426: }
427:
1.1.1.11! root 428: /*
! 429: * Checks an image for consistency. Exit codes:
! 430: *
! 431: * 0 - Check completed, image is good
! 432: * 1 - Check not completed because of internal errors
! 433: * 2 - Check completed, image is corrupted
! 434: * 3 - Check completed, image has leaked clusters, but is good otherwise
! 435: */
1.1.1.8 root 436: static int img_check(int argc, char **argv)
437: {
438: int c, ret;
439: const char *filename, *fmt;
440: BlockDriverState *bs;
1.1.1.11! root 441: BdrvCheckResult result;
1.1.1.8 root 442:
443: fmt = NULL;
444: for(;;) {
445: c = getopt(argc, argv, "f:h");
446: if (c == -1)
447: break;
448: switch(c) {
449: case 'h':
450: help();
451: break;
452: case 'f':
453: fmt = optarg;
454: break;
455: }
456: }
457: if (optind >= argc)
458: help();
459: filename = argv[optind++];
460:
1.1.1.11! root 461: bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS);
! 462: if (!bs) {
! 463: return 1;
1.1.1.8 root 464: }
1.1.1.11! root 465: ret = bdrv_check(bs, &result);
! 466:
! 467: if (ret == -ENOTSUP) {
! 468: error("This image format does not support checks");
! 469: bdrv_delete(bs);
! 470: return 1;
1.1.1.8 root 471: }
1.1.1.11! root 472:
! 473: if (!(result.corruptions || result.leaks || result.check_errors)) {
1.1.1.8 root 474: printf("No errors were found on the image.\n");
1.1.1.11! root 475: } else {
! 476: if (result.corruptions) {
! 477: printf("\n%d errors were found on the image.\n"
! 478: "Data may be corrupted, or further writes to the image "
! 479: "may corrupt it.\n",
! 480: result.corruptions);
! 481: }
! 482:
! 483: if (result.leaks) {
! 484: printf("\n%d leaked clusters were found on the image.\n"
! 485: "This means waste of disk space, but no harm to data.\n",
! 486: result.leaks);
! 487: }
! 488:
! 489: if (result.check_errors) {
! 490: printf("\n%d internal errors have occurred during the check.\n",
! 491: result.check_errors);
1.1.1.8 root 492: }
493: }
494:
495: bdrv_delete(bs);
1.1.1.11! root 496:
! 497: if (ret < 0 || result.check_errors) {
! 498: printf("\nAn error has occurred during the check: %s\n"
! 499: "The check is not complete and may have missed error.\n",
! 500: strerror(-ret));
! 501: return 1;
! 502: }
! 503:
! 504: if (result.corruptions) {
! 505: return 2;
! 506: } else if (result.leaks) {
! 507: return 3;
! 508: } else {
! 509: return 0;
! 510: }
1.1.1.8 root 511: }
512:
1.1 root 513: static int img_commit(int argc, char **argv)
514: {
515: int c, ret;
516: const char *filename, *fmt;
517: BlockDriverState *bs;
518:
519: fmt = NULL;
520: for(;;) {
521: c = getopt(argc, argv, "f:h");
522: if (c == -1)
523: break;
524: switch(c) {
525: case 'h':
526: help();
527: break;
528: case 'f':
529: fmt = optarg;
530: break;
531: }
532: }
1.1.1.4 root 533: if (optind >= argc)
1.1 root 534: help();
535: filename = argv[optind++];
536:
1.1.1.11! root 537: bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
! 538: if (!bs) {
! 539: return 1;
1.1 root 540: }
541: ret = bdrv_commit(bs);
542: switch(ret) {
543: case 0:
544: printf("Image committed.\n");
545: break;
546: case -ENOENT:
547: error("No disk inserted");
548: break;
549: case -EACCES:
550: error("Image is read-only");
551: break;
552: case -ENOTSUP:
553: error("Image is already committed");
554: break;
555: default:
556: error("Error while committing image");
557: break;
558: }
559:
560: bdrv_delete(bs);
1.1.1.11! root 561: if (ret) {
! 562: return 1;
! 563: }
1.1 root 564: return 0;
565: }
566:
567: static int is_not_zero(const uint8_t *sector, int len)
568: {
569: int i;
570: len >>= 2;
571: for(i = 0;i < len; i++) {
572: if (((uint32_t *)sector)[i] != 0)
573: return 1;
574: }
575: return 0;
576: }
577:
1.1.1.5 root 578: /*
579: * Returns true iff the first sector pointed to by 'buf' contains at least
580: * a non-NUL byte.
581: *
582: * 'pnum' is set to the number of sectors (including and immediately following
583: * the first one) that are known to be in the same allocated/unallocated state.
584: */
1.1 root 585: static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
586: {
587: int v, i;
588:
589: if (n <= 0) {
590: *pnum = 0;
591: return 0;
592: }
593: v = is_not_zero(buf, 512);
594: for(i = 1; i < n; i++) {
595: buf += 512;
596: if (v != is_not_zero(buf, 512))
597: break;
598: }
599: *pnum = i;
600: return v;
601: }
602:
1.1.1.11! root 603: /*
! 604: * Compares two buffers sector by sector. Returns 0 if the first sector of both
! 605: * buffers matches, non-zero otherwise.
! 606: *
! 607: * pnum is set to the number of sectors (including and immediately following
! 608: * the first one) that are known to have the same comparison result
! 609: */
! 610: static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
! 611: int *pnum)
! 612: {
! 613: int res, i;
! 614:
! 615: if (n <= 0) {
! 616: *pnum = 0;
! 617: return 0;
! 618: }
! 619:
! 620: res = !!memcmp(buf1, buf2, 512);
! 621: for(i = 1; i < n; i++) {
! 622: buf1 += 512;
! 623: buf2 += 512;
! 624:
! 625: if (!!memcmp(buf1, buf2, 512) != res) {
! 626: break;
! 627: }
! 628: }
! 629:
! 630: *pnum = i;
! 631: return res;
! 632: }
! 633:
1.1.1.9 root 634: #define IO_BUF_SIZE (2 * 1024 * 1024)
1.1 root 635:
636: static int img_convert(int argc, char **argv)
637: {
1.1.1.11! root 638: int c, ret = 0, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
1.1.1.5 root 639: const char *fmt, *out_fmt, *out_baseimg, *out_filename;
1.1.1.11! root 640: BlockDriver *drv, *proto_drv;
! 641: BlockDriverState **bs = NULL, *out_bs = NULL;
1.1.1.4 root 642: int64_t total_sectors, nb_sectors, sector_num, bs_offset;
643: uint64_t bs_sectors;
1.1.1.11! root 644: uint8_t * buf = NULL;
1.1 root 645: const uint8_t *buf1;
1.1.1.3 root 646: BlockDriverInfo bdi;
1.1.1.11! root 647: QEMUOptionParameter *param = NULL, *create_options = NULL;
1.1.1.8 root 648: char *options = NULL;
1.1 root 649:
650: fmt = NULL;
651: out_fmt = "raw";
1.1.1.5 root 652: out_baseimg = NULL;
1.1.1.4 root 653: flags = 0;
1.1 root 654: for(;;) {
1.1.1.8 root 655: c = getopt(argc, argv, "f:O:B:hce6o:");
1.1 root 656: if (c == -1)
657: break;
658: switch(c) {
659: case 'h':
660: help();
661: break;
662: case 'f':
663: fmt = optarg;
664: break;
665: case 'O':
666: out_fmt = optarg;
667: break;
1.1.1.5 root 668: case 'B':
669: out_baseimg = optarg;
670: break;
1.1 root 671: case 'c':
1.1.1.4 root 672: flags |= BLOCK_FLAG_COMPRESS;
1.1 root 673: break;
674: case 'e':
1.1.1.4 root 675: flags |= BLOCK_FLAG_ENCRYPT;
676: break;
677: case '6':
678: flags |= BLOCK_FLAG_COMPAT6;
1.1 root 679: break;
1.1.1.8 root 680: case 'o':
681: options = optarg;
682: break;
1.1 root 683: }
684: }
1.1.1.4 root 685:
686: bs_n = argc - optind - 1;
687: if (bs_n < 1) help();
688:
689: out_filename = argv[argc - 1];
1.1.1.5 root 690:
1.1.1.11! root 691: if (bs_n > 1 && out_baseimg) {
1.1.1.5 root 692: error("-B makes no sense when concatenating multiple input images");
1.1.1.11! root 693: return 1;
! 694: }
1.1.1.4 root 695:
696: bs = calloc(bs_n, sizeof(BlockDriverState *));
1.1.1.11! root 697: if (!bs) {
1.1.1.4 root 698: error("Out of memory");
1.1.1.11! root 699: return 1;
! 700: }
1.1.1.4 root 701:
702: total_sectors = 0;
703: for (bs_i = 0; bs_i < bs_n; bs_i++) {
1.1.1.11! root 704: bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
! 705: if (!bs[bs_i]) {
1.1.1.4 root 706: error("Could not open '%s'", argv[optind + bs_i]);
1.1.1.11! root 707: ret = -1;
! 708: goto out;
! 709: }
1.1.1.4 root 710: bdrv_get_geometry(bs[bs_i], &bs_sectors);
711: total_sectors += bs_sectors;
712: }
1.1 root 713:
1.1.1.8 root 714: /* Find driver and parse its options */
1.1 root 715: drv = bdrv_find_format(out_fmt);
1.1.1.11! root 716: if (!drv) {
1.1.1.4 root 717: error("Unknown file format '%s'", out_fmt);
1.1.1.11! root 718: ret = -1;
! 719: goto out;
! 720: }
! 721:
! 722: proto_drv = bdrv_find_protocol(out_filename);
! 723: if (!proto_drv) {
! 724: error("Unknown protocol '%s'", out_filename);
! 725: ret = -1;
! 726: goto out;
! 727: }
1.1.1.4 root 728:
1.1.1.11! root 729: create_options = append_option_parameters(create_options,
! 730: drv->create_options);
! 731: create_options = append_option_parameters(create_options,
! 732: proto_drv->create_options);
1.1.1.8 root 733: if (options && !strcmp(options, "?")) {
1.1.1.11! root 734: print_option_help(create_options);
! 735: goto out;
1.1.1.8 root 736: }
737:
738: if (options) {
1.1.1.11! root 739: param = parse_option_parameters(options, create_options, param);
1.1.1.8 root 740: if (param == NULL) {
741: error("Invalid options for file format '%s'.", out_fmt);
1.1.1.11! root 742: ret = -1;
! 743: goto out;
1.1.1.8 root 744: }
745: } else {
1.1.1.11! root 746: param = parse_option_parameters("", create_options, param);
1.1.1.8 root 747: }
748:
749: set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
1.1.1.11! root 750: ret = add_old_style_options(out_fmt, param, flags, out_baseimg, NULL);
! 751: if (ret < 0) {
! 752: goto out;
! 753: }
1.1.1.8 root 754:
755: /* Check if compression is supported */
756: if (flags & BLOCK_FLAG_COMPRESS) {
757: QEMUOptionParameter *encryption =
758: get_option_parameter(param, BLOCK_OPT_ENCRYPT);
759:
760: if (!drv->bdrv_write_compressed) {
761: error("Compression not supported for this file format");
1.1.1.11! root 762: ret = -1;
! 763: goto out;
1.1.1.8 root 764: }
765:
766: if (encryption && encryption->value.n) {
767: error("Compression and encryption not supported at the same time");
1.1.1.11! root 768: ret = -1;
! 769: goto out;
1.1.1.8 root 770: }
771: }
772:
773: /* Create the new image */
774: ret = bdrv_create(drv, out_filename, param);
1.1 root 775: if (ret < 0) {
776: if (ret == -ENOTSUP) {
1.1.1.7 root 777: error("Formatting not supported for file format '%s'", out_fmt);
778: } else if (ret == -EFBIG) {
779: error("The image size is too large for file format '%s'", out_fmt);
1.1 root 780: } else {
1.1.1.11! root 781: error("%s: error while converting %s: %s", out_filename, out_fmt, strerror(-ret));
1.1 root 782: }
1.1.1.11! root 783: goto out;
1.1 root 784: }
1.1.1.4 root 785:
1.1.1.11! root 786: out_bs = bdrv_new_open(out_filename, out_fmt,
! 787: BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
! 788: if (!out_bs) {
! 789: ret = -1;
! 790: goto out;
! 791: }
1.1 root 792:
1.1.1.4 root 793: bs_i = 0;
794: bs_offset = 0;
795: bdrv_get_geometry(bs[0], &bs_sectors);
1.1.1.10 root 796: buf = qemu_malloc(IO_BUF_SIZE);
1.1.1.4 root 797:
798: if (flags & BLOCK_FLAG_COMPRESS) {
1.1.1.11! root 799: ret = bdrv_get_info(out_bs, &bdi);
! 800: if (ret < 0) {
1.1.1.3 root 801: error("could not get block driver info");
1.1.1.11! root 802: goto out;
! 803: }
1.1.1.3 root 804: cluster_size = bdi.cluster_size;
1.1.1.11! root 805: if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
1.1 root 806: error("invalid cluster size");
1.1.1.11! root 807: ret = -1;
! 808: goto out;
! 809: }
1.1 root 810: cluster_sectors = cluster_size >> 9;
811: sector_num = 0;
812: for(;;) {
1.1.1.4 root 813: int64_t bs_num;
814: int remainder;
815: uint8_t *buf2;
816:
1.1 root 817: nb_sectors = total_sectors - sector_num;
818: if (nb_sectors <= 0)
819: break;
820: if (nb_sectors >= cluster_sectors)
821: n = cluster_sectors;
822: else
823: n = nb_sectors;
1.1.1.4 root 824:
825: bs_num = sector_num - bs_offset;
826: assert (bs_num >= 0);
827: remainder = n;
828: buf2 = buf;
829: while (remainder > 0) {
830: int nlow;
831: while (bs_num == bs_sectors) {
832: bs_i++;
833: assert (bs_i < bs_n);
834: bs_offset += bs_sectors;
835: bdrv_get_geometry(bs[bs_i], &bs_sectors);
836: bs_num = 0;
1.1.1.11! root 837: /* printf("changing part: sector_num=%" PRId64 ", "
! 838: "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
! 839: "\n", sector_num, bs_i, bs_offset, bs_sectors); */
1.1.1.4 root 840: }
841: assert (bs_num < bs_sectors);
842:
843: nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
844:
1.1.1.11! root 845: ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
! 846: if (ret < 0) {
1.1.1.4 root 847: error("error while reading");
1.1.1.11! root 848: goto out;
! 849: }
1.1.1.4 root 850:
851: buf2 += nlow * 512;
852: bs_num += nlow;
853:
854: remainder -= nlow;
855: }
856: assert (remainder == 0);
857:
1.1 root 858: if (n < cluster_sectors)
859: memset(buf + n * 512, 0, cluster_size - n * 512);
860: if (is_not_zero(buf, cluster_size)) {
1.1.1.11! root 861: ret = bdrv_write_compressed(out_bs, sector_num, buf,
! 862: cluster_sectors);
! 863: if (ret != 0) {
1.1.1.2 root 864: error("error while compressing sector %" PRId64,
865: sector_num);
1.1.1.11! root 866: goto out;
! 867: }
1.1 root 868: }
869: sector_num += n;
870: }
1.1.1.3 root 871: /* signal EOF to align */
872: bdrv_write_compressed(out_bs, 0, NULL, 0);
1.1 root 873: } else {
1.1.1.11! root 874: int has_zero_init = bdrv_has_zero_init(out_bs);
! 875:
1.1.1.5 root 876: sector_num = 0; // total number of sectors converted so far
1.1 root 877: for(;;) {
878: nb_sectors = total_sectors - sector_num;
879: if (nb_sectors <= 0)
880: break;
881: if (nb_sectors >= (IO_BUF_SIZE / 512))
882: n = (IO_BUF_SIZE / 512);
883: else
884: n = nb_sectors;
1.1.1.4 root 885:
886: while (sector_num - bs_offset >= bs_sectors) {
887: bs_i ++;
888: assert (bs_i < bs_n);
889: bs_offset += bs_sectors;
890: bdrv_get_geometry(bs[bs_i], &bs_sectors);
1.1.1.11! root 891: /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
! 892: "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
1.1.1.4 root 893: sector_num, bs_i, bs_offset, bs_sectors); */
894: }
895:
896: if (n > bs_offset + bs_sectors - sector_num)
897: n = bs_offset + bs_sectors - sector_num;
898:
1.1.1.11! root 899: if (has_zero_init) {
1.1.1.8 root 900: /* If the output image is being created as a copy on write image,
901: assume that sectors which are unallocated in the input image
902: are present in both the output's and input's base images (no
903: need to copy them). */
904: if (out_baseimg) {
905: if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
906: n, &n1)) {
907: sector_num += n1;
908: continue;
909: }
910: /* The next 'n1' sectors are allocated in the input image. Copy
911: only those as they may be followed by unallocated sectors. */
912: n = n1;
913: }
914: } else {
915: n1 = n;
1.1.1.5 root 916: }
917:
1.1.1.11! root 918: ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
! 919: if (ret < 0) {
1.1 root 920: error("error while reading");
1.1.1.11! root 921: goto out;
! 922: }
1.1 root 923: /* NOTE: at the same time we convert, we do not write zero
924: sectors to have a chance to compress the image. Ideally, we
925: should add a specific call to have the info to go faster */
926: buf1 = buf;
927: while (n > 0) {
1.1.1.5 root 928: /* If the output image is being created as a copy on write image,
929: copy all sectors even the ones containing only NUL bytes,
1.1.1.8 root 930: because they may differ from the sectors in the base image.
931:
932: If the output is to a host device, we also write out
933: sectors that are entirely 0, since whatever data was
934: already there is garbage, not 0s. */
1.1.1.11! root 935: if (!has_zero_init || out_baseimg ||
1.1.1.8 root 936: is_allocated_sectors(buf1, n, &n1)) {
1.1.1.11! root 937: ret = bdrv_write(out_bs, sector_num, buf1, n1);
! 938: if (ret < 0) {
1.1 root 939: error("error while writing");
1.1.1.11! root 940: goto out;
! 941: }
1.1 root 942: }
943: sector_num += n1;
944: n -= n1;
945: buf1 += n1 * 512;
946: }
947: }
948: }
1.1.1.11! root 949: out:
! 950: free_option_parameters(create_options);
! 951: free_option_parameters(param);
1.1.1.10 root 952: qemu_free(buf);
1.1.1.11! root 953: if (out_bs) {
! 954: bdrv_delete(out_bs);
! 955: }
! 956: for (bs_i = 0; bs_i < bs_n; bs_i++) {
! 957: if (bs[bs_i]) {
! 958: bdrv_delete(bs[bs_i]);
! 959: }
! 960: }
1.1.1.4 root 961: free(bs);
1.1.1.11! root 962: if (ret) {
! 963: return 1;
! 964: }
1.1 root 965: return 0;
966: }
967:
968: #ifdef _WIN32
969: static int64_t get_allocated_file_size(const char *filename)
970: {
1.1.1.2 root 971: typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
972: get_compressed_t get_compressed;
1.1 root 973: struct _stati64 st;
1.1.1.2 root 974:
975: /* WinNT support GetCompressedFileSize to determine allocate size */
976: get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
977: if (get_compressed) {
978: DWORD high, low;
979: low = get_compressed(filename, &high);
980: if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
981: return (((int64_t) high) << 32) + low;
982: }
983:
1.1.1.4 root 984: if (_stati64(filename, &st) < 0)
1.1 root 985: return -1;
986: return st.st_size;
987: }
988: #else
989: static int64_t get_allocated_file_size(const char *filename)
990: {
991: struct stat st;
1.1.1.4 root 992: if (stat(filename, &st) < 0)
1.1 root 993: return -1;
994: return (int64_t)st.st_blocks * 512;
995: }
996: #endif
997:
1.1.1.3 root 998: static void dump_snapshots(BlockDriverState *bs)
999: {
1000: QEMUSnapshotInfo *sn_tab, *sn;
1001: int nb_sns, i;
1002: char buf[256];
1003:
1004: nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1005: if (nb_sns <= 0)
1006: return;
1007: printf("Snapshot list:\n");
1008: printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
1009: for(i = 0; i < nb_sns; i++) {
1010: sn = &sn_tab[i];
1011: printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
1012: }
1013: qemu_free(sn_tab);
1014: }
1015:
1.1 root 1016: static int img_info(int argc, char **argv)
1017: {
1018: int c;
1019: const char *filename, *fmt;
1020: BlockDriverState *bs;
1021: char fmt_name[128], size_buf[128], dsize_buf[128];
1.1.1.4 root 1022: uint64_t total_sectors;
1023: int64_t allocated_size;
1.1.1.3 root 1024: char backing_filename[1024];
1025: char backing_filename2[1024];
1026: BlockDriverInfo bdi;
1.1 root 1027:
1028: fmt = NULL;
1029: for(;;) {
1030: c = getopt(argc, argv, "f:h");
1031: if (c == -1)
1032: break;
1033: switch(c) {
1034: case 'h':
1035: help();
1036: break;
1037: case 'f':
1038: fmt = optarg;
1039: break;
1040: }
1041: }
1.1.1.4 root 1042: if (optind >= argc)
1.1 root 1043: help();
1044: filename = argv[optind++];
1045:
1.1.1.11! root 1046: bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
! 1047: if (!bs) {
! 1048: return 1;
1.1 root 1049: }
1050: bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
1051: bdrv_get_geometry(bs, &total_sectors);
1052: get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
1053: allocated_size = get_allocated_file_size(filename);
1054: if (allocated_size < 0)
1.1.1.5 root 1055: snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
1.1 root 1056: else
1.1.1.4 root 1057: get_human_readable_size(dsize_buf, sizeof(dsize_buf),
1.1 root 1058: allocated_size);
1059: printf("image: %s\n"
1060: "file format: %s\n"
1.1.1.2 root 1061: "virtual size: %s (%" PRId64 " bytes)\n"
1.1 root 1062: "disk size: %s\n",
1.1.1.4 root 1063: filename, fmt_name, size_buf,
1.1.1.2 root 1064: (total_sectors * 512),
1.1 root 1065: dsize_buf);
1066: if (bdrv_is_encrypted(bs))
1067: printf("encrypted: yes\n");
1.1.1.3 root 1068: if (bdrv_get_info(bs, &bdi) >= 0) {
1.1.1.4 root 1069: if (bdi.cluster_size != 0)
1.1.1.3 root 1070: printf("cluster_size: %d\n", bdi.cluster_size);
1071: }
1072: bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
1073: if (backing_filename[0] != '\0') {
1074: path_combine(backing_filename2, sizeof(backing_filename2),
1075: filename, backing_filename);
1.1.1.4 root 1076: printf("backing file: %s (actual path: %s)\n",
1.1.1.3 root 1077: backing_filename,
1078: backing_filename2);
1079: }
1080: dump_snapshots(bs);
1.1 root 1081: bdrv_delete(bs);
1082: return 0;
1083: }
1084:
1.1.1.5 root 1085: #define SNAPSHOT_LIST 1
1086: #define SNAPSHOT_CREATE 2
1087: #define SNAPSHOT_APPLY 3
1088: #define SNAPSHOT_DELETE 4
1089:
1.1.1.8 root 1090: static int img_snapshot(int argc, char **argv)
1.1.1.5 root 1091: {
1092: BlockDriverState *bs;
1093: QEMUSnapshotInfo sn;
1094: char *filename, *snapshot_name = NULL;
1.1.1.11! root 1095: int c, ret = 0, bdrv_oflags;
1.1.1.5 root 1096: int action = 0;
1097: qemu_timeval tv;
1098:
1.1.1.11! root 1099: bdrv_oflags = BDRV_O_RDWR;
1.1.1.5 root 1100: /* Parse commandline parameters */
1101: for(;;) {
1102: c = getopt(argc, argv, "la:c:d:h");
1103: if (c == -1)
1104: break;
1105: switch(c) {
1106: case 'h':
1107: help();
1.1.1.8 root 1108: return 0;
1.1.1.5 root 1109: case 'l':
1110: if (action) {
1111: help();
1.1.1.8 root 1112: return 0;
1.1.1.5 root 1113: }
1114: action = SNAPSHOT_LIST;
1.1.1.11! root 1115: bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
1.1.1.5 root 1116: break;
1117: case 'a':
1118: if (action) {
1119: help();
1.1.1.8 root 1120: return 0;
1.1.1.5 root 1121: }
1122: action = SNAPSHOT_APPLY;
1123: snapshot_name = optarg;
1124: break;
1125: case 'c':
1126: if (action) {
1127: help();
1.1.1.8 root 1128: return 0;
1.1.1.5 root 1129: }
1130: action = SNAPSHOT_CREATE;
1131: snapshot_name = optarg;
1132: break;
1133: case 'd':
1134: if (action) {
1135: help();
1.1.1.8 root 1136: return 0;
1.1.1.5 root 1137: }
1138: action = SNAPSHOT_DELETE;
1139: snapshot_name = optarg;
1140: break;
1141: }
1142: }
1143:
1144: if (optind >= argc)
1145: help();
1146: filename = argv[optind++];
1147:
1148: /* Open the image */
1.1.1.11! root 1149: bs = bdrv_new_open(filename, NULL, bdrv_oflags);
! 1150: if (!bs) {
! 1151: return 1;
1.1.1.5 root 1152: }
1153:
1154: /* Perform the requested action */
1155: switch(action) {
1156: case SNAPSHOT_LIST:
1157: dump_snapshots(bs);
1158: break;
1159:
1160: case SNAPSHOT_CREATE:
1161: memset(&sn, 0, sizeof(sn));
1162: pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1163:
1164: qemu_gettimeofday(&tv);
1165: sn.date_sec = tv.tv_sec;
1166: sn.date_nsec = tv.tv_usec * 1000;
1167:
1168: ret = bdrv_snapshot_create(bs, &sn);
1169: if (ret)
1170: error("Could not create snapshot '%s': %d (%s)",
1171: snapshot_name, ret, strerror(-ret));
1172: break;
1173:
1174: case SNAPSHOT_APPLY:
1175: ret = bdrv_snapshot_goto(bs, snapshot_name);
1176: if (ret)
1177: error("Could not apply snapshot '%s': %d (%s)",
1178: snapshot_name, ret, strerror(-ret));
1179: break;
1180:
1181: case SNAPSHOT_DELETE:
1182: ret = bdrv_snapshot_delete(bs, snapshot_name);
1183: if (ret)
1184: error("Could not delete snapshot '%s': %d (%s)",
1185: snapshot_name, ret, strerror(-ret));
1186: break;
1187: }
1188:
1189: /* Cleanup */
1190: bdrv_delete(bs);
1.1.1.11! root 1191: if (ret) {
! 1192: return 1;
! 1193: }
! 1194: return 0;
! 1195: }
! 1196:
! 1197: static int img_rebase(int argc, char **argv)
! 1198: {
! 1199: BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
! 1200: BlockDriver *old_backing_drv, *new_backing_drv;
! 1201: char *filename;
! 1202: const char *fmt, *out_basefmt, *out_baseimg;
! 1203: int c, flags, ret;
! 1204: int unsafe = 0;
! 1205:
! 1206: /* Parse commandline parameters */
! 1207: fmt = NULL;
! 1208: out_baseimg = NULL;
! 1209: out_basefmt = NULL;
! 1210:
! 1211: for(;;) {
! 1212: c = getopt(argc, argv, "uhf:F:b:");
! 1213: if (c == -1)
! 1214: break;
! 1215: switch(c) {
! 1216: case 'h':
! 1217: help();
! 1218: return 0;
! 1219: case 'f':
! 1220: fmt = optarg;
! 1221: break;
! 1222: case 'F':
! 1223: out_basefmt = optarg;
! 1224: break;
! 1225: case 'b':
! 1226: out_baseimg = optarg;
! 1227: break;
! 1228: case 'u':
! 1229: unsafe = 1;
! 1230: break;
! 1231: }
! 1232: }
! 1233:
! 1234: if ((optind >= argc) || !out_baseimg)
! 1235: help();
! 1236: filename = argv[optind++];
! 1237:
! 1238: /*
! 1239: * Open the images.
! 1240: *
! 1241: * Ignore the old backing file for unsafe rebase in case we want to correct
! 1242: * the reference to a renamed or moved backing file.
! 1243: */
! 1244: flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
! 1245: bs = bdrv_new_open(filename, fmt, flags);
! 1246: if (!bs) {
! 1247: return 1;
! 1248: }
! 1249:
! 1250: /* Find the right drivers for the backing files */
! 1251: old_backing_drv = NULL;
! 1252: new_backing_drv = NULL;
! 1253:
! 1254: if (!unsafe && bs->backing_format[0] != '\0') {
! 1255: old_backing_drv = bdrv_find_format(bs->backing_format);
! 1256: if (old_backing_drv == NULL) {
! 1257: error("Invalid format name: '%s'", bs->backing_format);
! 1258: ret = -1;
! 1259: goto out;
! 1260: }
! 1261: }
! 1262:
! 1263: if (out_basefmt != NULL) {
! 1264: new_backing_drv = bdrv_find_format(out_basefmt);
! 1265: if (new_backing_drv == NULL) {
! 1266: error("Invalid format name: '%s'", out_basefmt);
! 1267: ret = -1;
! 1268: goto out;
! 1269: }
! 1270: }
! 1271:
! 1272: /* For safe rebasing we need to compare old and new backing file */
! 1273: if (unsafe) {
! 1274: /* Make the compiler happy */
! 1275: bs_old_backing = NULL;
! 1276: bs_new_backing = NULL;
! 1277: } else {
! 1278: char backing_name[1024];
! 1279:
! 1280: bs_old_backing = bdrv_new("old_backing");
! 1281: bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
! 1282: ret = bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,
! 1283: old_backing_drv);
! 1284: if (ret) {
! 1285: error("Could not open old backing file '%s'", backing_name);
! 1286: goto out;
! 1287: }
! 1288:
! 1289: bs_new_backing = bdrv_new("new_backing");
! 1290: ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS,
! 1291: new_backing_drv);
! 1292: if (ret) {
! 1293: error("Could not open new backing file '%s'", out_baseimg);
! 1294: goto out;
! 1295: }
! 1296: }
! 1297:
! 1298: /*
! 1299: * Check each unallocated cluster in the COW file. If it is unallocated,
! 1300: * accesses go to the backing file. We must therefore compare this cluster
! 1301: * in the old and new backing file, and if they differ we need to copy it
! 1302: * from the old backing file into the COW file.
! 1303: *
! 1304: * If qemu-img crashes during this step, no harm is done. The content of
! 1305: * the image is the same as the original one at any time.
! 1306: */
! 1307: if (!unsafe) {
! 1308: uint64_t num_sectors;
! 1309: uint64_t sector;
! 1310: int n;
! 1311: uint8_t * buf_old;
! 1312: uint8_t * buf_new;
! 1313:
! 1314: buf_old = qemu_malloc(IO_BUF_SIZE);
! 1315: buf_new = qemu_malloc(IO_BUF_SIZE);
! 1316:
! 1317: bdrv_get_geometry(bs, &num_sectors);
! 1318:
! 1319: for (sector = 0; sector < num_sectors; sector += n) {
! 1320:
! 1321: /* How many sectors can we handle with the next read? */
! 1322: if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
! 1323: n = (IO_BUF_SIZE / 512);
! 1324: } else {
! 1325: n = num_sectors - sector;
! 1326: }
! 1327:
! 1328: /* If the cluster is allocated, we don't need to take action */
! 1329: ret = bdrv_is_allocated(bs, sector, n, &n);
! 1330: if (ret) {
! 1331: continue;
! 1332: }
! 1333:
! 1334: /* Read old and new backing file */
! 1335: ret = bdrv_read(bs_old_backing, sector, buf_old, n);
! 1336: if (ret < 0) {
! 1337: error("error while reading from old backing file");
! 1338: goto out;
! 1339: }
! 1340: ret = bdrv_read(bs_new_backing, sector, buf_new, n);
! 1341: if (ret < 0) {
! 1342: error("error while reading from new backing file");
! 1343: goto out;
! 1344: }
! 1345:
! 1346: /* If they differ, we need to write to the COW file */
! 1347: uint64_t written = 0;
! 1348:
! 1349: while (written < n) {
! 1350: int pnum;
! 1351:
! 1352: if (compare_sectors(buf_old + written * 512,
! 1353: buf_new + written * 512, n - written, &pnum))
! 1354: {
! 1355: ret = bdrv_write(bs, sector + written,
! 1356: buf_old + written * 512, pnum);
! 1357: if (ret < 0) {
! 1358: error("Error while writing to COW image: %s",
! 1359: strerror(-ret));
! 1360: goto out;
! 1361: }
! 1362: }
! 1363:
! 1364: written += pnum;
! 1365: }
! 1366: }
! 1367:
! 1368: qemu_free(buf_old);
! 1369: qemu_free(buf_new);
! 1370: }
! 1371:
! 1372: /*
! 1373: * Change the backing file. All clusters that are different from the old
! 1374: * backing file are overwritten in the COW file now, so the visible content
! 1375: * doesn't change when we switch the backing file.
! 1376: */
! 1377: ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
! 1378: if (ret == -ENOSPC) {
! 1379: error("Could not change the backing file to '%s': No space left in "
! 1380: "the file header", out_baseimg);
! 1381: } else if (ret < 0) {
! 1382: error("Could not change the backing file to '%s': %s",
! 1383: out_baseimg, strerror(-ret));
! 1384: }
! 1385:
! 1386: /*
! 1387: * TODO At this point it is possible to check if any clusters that are
! 1388: * allocated in the COW file are the same in the backing file. If so, they
! 1389: * could be dropped from the COW file. Don't do this before switching the
! 1390: * backing file, in case of a crash this would lead to corruption.
! 1391: */
! 1392: out:
! 1393: /* Cleanup */
! 1394: if (!unsafe) {
! 1395: bdrv_delete(bs_old_backing);
! 1396: bdrv_delete(bs_new_backing);
! 1397: }
! 1398:
! 1399: bdrv_delete(bs);
! 1400: if (ret) {
! 1401: return 1;
! 1402: }
! 1403: return 0;
! 1404: }
! 1405:
! 1406: static int img_resize(int argc, char **argv)
! 1407: {
! 1408: int c, ret, relative;
! 1409: const char *filename, *fmt, *size;
! 1410: int64_t n, total_size;
! 1411: BlockDriverState *bs;
! 1412: QEMUOptionParameter *param;
! 1413: QEMUOptionParameter resize_options[] = {
! 1414: {
! 1415: .name = BLOCK_OPT_SIZE,
! 1416: .type = OPT_SIZE,
! 1417: .help = "Virtual disk size"
! 1418: },
! 1419: { NULL }
! 1420: };
! 1421:
! 1422: fmt = NULL;
! 1423: for(;;) {
! 1424: c = getopt(argc, argv, "f:h");
! 1425: if (c == -1) {
! 1426: break;
! 1427: }
! 1428: switch(c) {
! 1429: case 'h':
! 1430: help();
! 1431: break;
! 1432: case 'f':
! 1433: fmt = optarg;
! 1434: break;
! 1435: }
! 1436: }
! 1437: if (optind + 1 >= argc) {
! 1438: help();
! 1439: }
! 1440: filename = argv[optind++];
! 1441: size = argv[optind++];
! 1442:
! 1443: /* Choose grow, shrink, or absolute resize mode */
! 1444: switch (size[0]) {
! 1445: case '+':
! 1446: relative = 1;
! 1447: size++;
! 1448: break;
! 1449: case '-':
! 1450: relative = -1;
! 1451: size++;
! 1452: break;
! 1453: default:
! 1454: relative = 0;
! 1455: break;
! 1456: }
! 1457:
! 1458: /* Parse size */
! 1459: param = parse_option_parameters("", resize_options, NULL);
! 1460: if (set_option_parameter(param, BLOCK_OPT_SIZE, size)) {
! 1461: /* Error message already printed when size parsing fails */
! 1462: exit(1);
! 1463: }
! 1464: n = get_option_parameter(param, BLOCK_OPT_SIZE)->value.n;
! 1465: free_option_parameters(param);
! 1466:
! 1467: bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
! 1468: if (!bs) {
! 1469: return 1;
! 1470: }
1.1.1.8 root 1471:
1.1.1.11! root 1472: if (relative) {
! 1473: total_size = bdrv_getlength(bs) + n * relative;
! 1474: } else {
! 1475: total_size = n;
! 1476: }
! 1477: if (total_size <= 0) {
! 1478: error("New image size must be positive");
! 1479: ret = -1;
! 1480: goto out;
! 1481: }
! 1482:
! 1483: ret = bdrv_truncate(bs, total_size);
! 1484: switch (ret) {
! 1485: case 0:
! 1486: printf("Image resized.\n");
! 1487: break;
! 1488: case -ENOTSUP:
! 1489: error("This image format does not support resize");
! 1490: break;
! 1491: case -EACCES:
! 1492: error("Image is read-only");
! 1493: break;
! 1494: default:
! 1495: error("Error resizing image (%d)", -ret);
! 1496: break;
! 1497: }
! 1498: out:
! 1499: bdrv_delete(bs);
! 1500: if (ret) {
! 1501: return 1;
! 1502: }
1.1.1.8 root 1503: return 0;
1.1.1.5 root 1504: }
1505:
1.1.1.8 root 1506: static const img_cmd_t img_cmds[] = {
1507: #define DEF(option, callback, arg_string) \
1508: { option, callback },
1509: #include "qemu-img-cmds.h"
1510: #undef DEF
1511: #undef GEN_DOCS
1512: { NULL, NULL, },
1513: };
1514:
1.1 root 1515: int main(int argc, char **argv)
1516: {
1.1.1.8 root 1517: const img_cmd_t *cmd;
1518: const char *cmdname;
1.1 root 1519:
1520: bdrv_init();
1521: if (argc < 2)
1522: help();
1.1.1.8 root 1523: cmdname = argv[1];
1.1.1.5 root 1524: argc--; argv++;
1.1.1.8 root 1525:
1526: /* find the command */
1527: for(cmd = img_cmds; cmd->name != NULL; cmd++) {
1528: if (!strcmp(cmdname, cmd->name)) {
1529: return cmd->handler(argc, argv);
1530: }
1.1 root 1531: }
1.1.1.8 root 1532:
1533: /* not found */
1534: help();
1.1 root 1535: return 0;
1536: }
unix.superglobalmegacorp.com