Convert qemu-img create to new bdrv_create
[armpft.git] / qemu-img.c
blob00329790b6af8f8911c2ae5002922933fdc51659
1 /*
2 * QEMU disk image utility
4 * Copyright (c) 2003-2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
24 #include "qemu-common.h"
25 #include "qemu-option.h"
26 #include "osdep.h"
27 #include "block_int.h"
28 #include <stdio.h>
30 #ifdef _WIN32
31 #include <windows.h>
32 #endif
34 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
35 #define BRDV_O_FLAGS BDRV_O_CACHE_WB
37 static void QEMU_NORETURN error(const char *fmt, ...)
39 va_list ap;
40 va_start(ap, fmt);
41 fprintf(stderr, "qemu-img: ");
42 vfprintf(stderr, fmt, ap);
43 fprintf(stderr, "\n");
44 exit(1);
45 va_end(ap);
48 static void format_print(void *opaque, const char *name)
50 printf(" %s", name);
53 /* Please keep in synch with qemu-img.texi */
54 static void help(void)
56 printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
57 "usage: qemu-img command [command options]\n"
58 "QEMU disk image utility\n"
59 "\n"
60 "Command syntax:\n"
61 " check [-f fmt] filename\n"
62 " create [-e] [-6] [-F fmt] [-b base_image] [-f fmt] filename [size]\n"
63 " commit [-f fmt] filename\n"
64 " convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
65 " info [-f fmt] filename\n"
66 " snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename\n"
67 "\n"
68 "Command parameters:\n"
69 " 'filename' is a disk image filename\n"
70 " 'base_image' is the read-only disk image which is used as base for a copy on\n"
71 " write image; the copy on write image only stores the modified data\n"
72 " 'output_base_image' forces the output image to be created as a copy on write\n"
73 " image of the specified base image; 'output_base_image' should have the same\n"
74 " content as the input's base image, however the path, image format, etc may\n"
75 " differ\n"
76 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
77 " 'size' is the disk image size in kilobytes. Optional suffixes\n"
78 " 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
79 " supported any 'k' or 'K' is ignored\n"
80 " 'output_filename' is the destination disk image filename\n"
81 " 'output_fmt' is the destination format\n"
82 " '-c' indicates that target image must be compressed (qcow format only)\n"
83 " '-e' indicates that the target image must be encrypted (qcow format only)\n"
84 " '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
85 " '-h' with or without a command shows this help and lists the supported formats\n"
86 "\n"
87 "Parameters to snapshot subcommand:\n"
88 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
89 " '-a' applies a snapshot (revert disk to saved state)\n"
90 " '-c' creates a snapshot\n"
91 " '-d' deletes a snapshot\n"
92 " '-l' lists all snapshots in the given image\n"
94 printf("\nSupported formats:");
95 bdrv_iterate_format(format_print, NULL);
96 printf("\n");
97 exit(1);
100 #if defined(WIN32)
101 /* XXX: put correct support for win32 */
102 static int read_password(char *buf, int buf_size)
104 int c, i;
105 printf("Password: ");
106 fflush(stdout);
107 i = 0;
108 for(;;) {
109 c = getchar();
110 if (c == '\n')
111 break;
112 if (i < (buf_size - 1))
113 buf[i++] = c;
115 buf[i] = '\0';
116 return 0;
119 #else
121 #include <termios.h>
123 static struct termios oldtty;
125 static void term_exit(void)
127 tcsetattr (0, TCSANOW, &oldtty);
130 static void term_init(void)
132 struct termios tty;
134 tcgetattr (0, &tty);
135 oldtty = tty;
137 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
138 |INLCR|IGNCR|ICRNL|IXON);
139 tty.c_oflag |= OPOST;
140 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
141 tty.c_cflag &= ~(CSIZE|PARENB);
142 tty.c_cflag |= CS8;
143 tty.c_cc[VMIN] = 1;
144 tty.c_cc[VTIME] = 0;
146 tcsetattr (0, TCSANOW, &tty);
148 atexit(term_exit);
151 static int read_password(char *buf, int buf_size)
153 uint8_t ch;
154 int i, ret;
156 printf("password: ");
157 fflush(stdout);
158 term_init();
159 i = 0;
160 for(;;) {
161 ret = read(0, &ch, 1);
162 if (ret == -1) {
163 if (errno == EAGAIN || errno == EINTR) {
164 continue;
165 } else {
166 ret = -1;
167 break;
169 } else if (ret == 0) {
170 ret = -1;
171 break;
172 } else {
173 if (ch == '\r') {
174 ret = 0;
175 break;
177 if (i < (buf_size - 1))
178 buf[i++] = ch;
181 term_exit();
182 buf[i] = '\0';
183 printf("\n");
184 return ret;
186 #endif
188 static BlockDriverState *bdrv_new_open(const char *filename,
189 const char *fmt)
191 BlockDriverState *bs;
192 BlockDriver *drv;
193 char password[256];
195 bs = bdrv_new("");
196 if (!bs)
197 error("Not enough memory");
198 if (fmt) {
199 drv = bdrv_find_format(fmt);
200 if (!drv)
201 error("Unknown file format '%s'", fmt);
202 } else {
203 drv = NULL;
205 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
206 error("Could not open '%s'", filename);
208 if (bdrv_is_encrypted(bs)) {
209 printf("Disk image '%s' is encrypted.\n", filename);
210 if (read_password(password, sizeof(password)) < 0)
211 error("No password given");
212 if (bdrv_set_key(bs, password) < 0)
213 error("invalid password");
215 return bs;
218 static int img_create(int argc, char **argv)
220 int c, ret, flags;
221 const char *fmt = "raw";
222 const char *base_fmt = NULL;
223 const char *filename;
224 const char *base_filename = NULL;
225 BlockDriver *drv;
226 QEMUOptionParameter *param = NULL;
227 char *options = NULL;
229 flags = 0;
230 for(;;) {
231 c = getopt(argc, argv, "F:b:f:he6o:");
232 if (c == -1)
233 break;
234 switch(c) {
235 case 'h':
236 help();
237 break;
238 case 'F':
239 base_fmt = optarg;
240 break;
241 case 'b':
242 base_filename = optarg;
243 break;
244 case 'f':
245 fmt = optarg;
246 break;
247 case 'e':
248 flags |= BLOCK_FLAG_ENCRYPT;
249 break;
250 case '6':
251 flags |= BLOCK_FLAG_COMPAT6;
252 break;
253 case 'o':
254 options = optarg;
255 break;
258 if (optind >= argc)
259 help();
260 filename = argv[optind++];
262 /* Find driver and parse its options */
263 drv = bdrv_find_format(fmt);
264 if (!drv)
265 error("Unknown file format '%s'", fmt);
267 if (options) {
268 param = parse_option_parameters(options, drv->create_options, param);
269 if (param == NULL) {
270 error("Invalid options for file format '%s'.", fmt);
272 } else {
273 param = parse_option_parameters("", drv->create_options, param);
276 /* Add size to parameters */
277 if (optind < argc) {
278 set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
281 /* Add old-style options to parameters */
282 if (flags & BLOCK_FLAG_ENCRYPT) {
283 if (set_option_parameter(param, BLOCK_OPT_ENCRYPT, "on")) {
284 error("Encryption not supported for file format '%s'", fmt);
287 if (flags & BLOCK_FLAG_COMPAT6) {
288 if (set_option_parameter(param, BLOCK_OPT_COMPAT6, "on")) {
289 error("VMDK version 6 not supported for file format '%s'", fmt);
293 if (base_filename) {
294 if (set_option_parameter(param, BLOCK_OPT_BACKING_FILE, base_filename)) {
295 error("Backing file not supported for file format '%s'", fmt);
298 if (base_fmt) {
299 if (set_option_parameter(param, BLOCK_OPT_BACKING_FMT, base_fmt)) {
300 error("Backing file format not supported for file format '%s'", fmt);
304 // The size for the image must always be specified, with one exception:
305 // If we are using a backing file, we can obtain the size from there
306 if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == 0) {
308 QEMUOptionParameter *backing_file =
309 get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
310 QEMUOptionParameter *backing_fmt =
311 get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
313 if (backing_file && backing_file->value.s) {
314 BlockDriverState *bs;
315 uint64_t size;
316 const char *fmt = NULL;
317 char buf[32];
319 if (backing_fmt && backing_fmt->value.s) {
320 if (bdrv_find_format(backing_fmt->value.s)) {
321 fmt = backing_fmt->value.s;
322 } else {
323 error("Unknown backing file format '%s'",
324 backing_fmt->value.s);
328 bs = bdrv_new_open(backing_file->value.s, fmt);
329 bdrv_get_geometry(bs, &size);
330 size *= 512;
331 bdrv_delete(bs);
333 snprintf(buf, sizeof(buf), "%" PRId64, size);
334 set_option_parameter(param, BLOCK_OPT_SIZE, buf);
335 } else {
336 error("Image creation needs a size parameter");
340 printf("Formatting '%s', fmt=%s ", filename, fmt);
341 print_option_parameters(param);
342 puts("");
344 ret = bdrv_create(drv, filename, param);
345 free_option_parameters(param);
347 if (ret < 0) {
348 if (ret == -ENOTSUP) {
349 error("Formatting or formatting option not supported for file format '%s'", fmt);
350 } else if (ret == -EFBIG) {
351 error("The image size is too large for file format '%s'", fmt);
352 } else {
353 error("Error while formatting");
356 return 0;
359 static int img_check(int argc, char **argv)
361 int c, ret;
362 const char *filename, *fmt;
363 BlockDriver *drv;
364 BlockDriverState *bs;
366 fmt = NULL;
367 for(;;) {
368 c = getopt(argc, argv, "f:h");
369 if (c == -1)
370 break;
371 switch(c) {
372 case 'h':
373 help();
374 break;
375 case 'f':
376 fmt = optarg;
377 break;
380 if (optind >= argc)
381 help();
382 filename = argv[optind++];
384 bs = bdrv_new("");
385 if (!bs)
386 error("Not enough memory");
387 if (fmt) {
388 drv = bdrv_find_format(fmt);
389 if (!drv)
390 error("Unknown file format '%s'", fmt);
391 } else {
392 drv = NULL;
394 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
395 error("Could not open '%s'", filename);
397 ret = bdrv_check(bs);
398 switch(ret) {
399 case 0:
400 printf("No errors were found on the image.\n");
401 break;
402 case -ENOTSUP:
403 error("This image format does not support checks");
404 break;
405 default:
406 if (ret < 0) {
407 error("An error occurred during the check");
408 } else {
409 printf("%d errors were found on the image.\n", ret);
411 break;
414 bdrv_delete(bs);
415 return 0;
418 static int img_commit(int argc, char **argv)
420 int c, ret;
421 const char *filename, *fmt;
422 BlockDriver *drv;
423 BlockDriverState *bs;
425 fmt = NULL;
426 for(;;) {
427 c = getopt(argc, argv, "f:h");
428 if (c == -1)
429 break;
430 switch(c) {
431 case 'h':
432 help();
433 break;
434 case 'f':
435 fmt = optarg;
436 break;
439 if (optind >= argc)
440 help();
441 filename = argv[optind++];
443 bs = bdrv_new("");
444 if (!bs)
445 error("Not enough memory");
446 if (fmt) {
447 drv = bdrv_find_format(fmt);
448 if (!drv)
449 error("Unknown file format '%s'", fmt);
450 } else {
451 drv = NULL;
453 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
454 error("Could not open '%s'", filename);
456 ret = bdrv_commit(bs);
457 switch(ret) {
458 case 0:
459 printf("Image committed.\n");
460 break;
461 case -ENOENT:
462 error("No disk inserted");
463 break;
464 case -EACCES:
465 error("Image is read-only");
466 break;
467 case -ENOTSUP:
468 error("Image is already committed");
469 break;
470 default:
471 error("Error while committing image");
472 break;
475 bdrv_delete(bs);
476 return 0;
479 static int is_not_zero(const uint8_t *sector, int len)
481 int i;
482 len >>= 2;
483 for(i = 0;i < len; i++) {
484 if (((uint32_t *)sector)[i] != 0)
485 return 1;
487 return 0;
491 * Returns true iff the first sector pointed to by 'buf' contains at least
492 * a non-NUL byte.
494 * 'pnum' is set to the number of sectors (including and immediately following
495 * the first one) that are known to be in the same allocated/unallocated state.
497 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
499 int v, i;
501 if (n <= 0) {
502 *pnum = 0;
503 return 0;
505 v = is_not_zero(buf, 512);
506 for(i = 1; i < n; i++) {
507 buf += 512;
508 if (v != is_not_zero(buf, 512))
509 break;
511 *pnum = i;
512 return v;
515 #define IO_BUF_SIZE 65536
517 static int img_convert(int argc, char **argv)
519 int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
520 const char *fmt, *out_fmt, *out_baseimg, *out_filename;
521 BlockDriver *drv;
522 BlockDriverState **bs, *out_bs;
523 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
524 uint64_t bs_sectors;
525 uint8_t buf[IO_BUF_SIZE];
526 const uint8_t *buf1;
527 BlockDriverInfo bdi;
529 fmt = NULL;
530 out_fmt = "raw";
531 out_baseimg = NULL;
532 flags = 0;
533 for(;;) {
534 c = getopt(argc, argv, "f:O:B:hce6");
535 if (c == -1)
536 break;
537 switch(c) {
538 case 'h':
539 help();
540 break;
541 case 'f':
542 fmt = optarg;
543 break;
544 case 'O':
545 out_fmt = optarg;
546 break;
547 case 'B':
548 out_baseimg = optarg;
549 break;
550 case 'c':
551 flags |= BLOCK_FLAG_COMPRESS;
552 break;
553 case 'e':
554 flags |= BLOCK_FLAG_ENCRYPT;
555 break;
556 case '6':
557 flags |= BLOCK_FLAG_COMPAT6;
558 break;
562 bs_n = argc - optind - 1;
563 if (bs_n < 1) help();
565 out_filename = argv[argc - 1];
567 if (bs_n > 1 && out_baseimg)
568 error("-B makes no sense when concatenating multiple input images");
570 bs = calloc(bs_n, sizeof(BlockDriverState *));
571 if (!bs)
572 error("Out of memory");
574 total_sectors = 0;
575 for (bs_i = 0; bs_i < bs_n; bs_i++) {
576 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
577 if (!bs[bs_i])
578 error("Could not open '%s'", argv[optind + bs_i]);
579 bdrv_get_geometry(bs[bs_i], &bs_sectors);
580 total_sectors += bs_sectors;
583 drv = bdrv_find_format(out_fmt);
584 if (!drv)
585 error("Unknown file format '%s'", out_fmt);
586 if (flags & BLOCK_FLAG_COMPRESS && strcmp(drv->format_name, "qcow") && strcmp(drv->format_name, "qcow2"))
587 error("Compression not supported for this file format");
588 if (flags & BLOCK_FLAG_ENCRYPT && strcmp(drv->format_name, "qcow") && strcmp(drv->format_name, "qcow2"))
589 error("Encryption not supported for this file format");
590 if (flags & BLOCK_FLAG_COMPAT6 && strcmp(drv->format_name, "vmdk"))
591 error("Alternative compatibility level not supported for this file format");
592 if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
593 error("Compression and encryption not supported at the same time");
595 ret = bdrv_create2(drv, out_filename, total_sectors, out_baseimg, NULL, flags);
596 if (ret < 0) {
597 if (ret == -ENOTSUP) {
598 error("Formatting not supported for file format '%s'", out_fmt);
599 } else if (ret == -EFBIG) {
600 error("The image size is too large for file format '%s'", out_fmt);
601 } else {
602 error("Error while formatting '%s'", out_filename);
606 out_bs = bdrv_new_open(out_filename, out_fmt);
608 bs_i = 0;
609 bs_offset = 0;
610 bdrv_get_geometry(bs[0], &bs_sectors);
612 if (flags & BLOCK_FLAG_COMPRESS) {
613 if (bdrv_get_info(out_bs, &bdi) < 0)
614 error("could not get block driver info");
615 cluster_size = bdi.cluster_size;
616 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
617 error("invalid cluster size");
618 cluster_sectors = cluster_size >> 9;
619 sector_num = 0;
620 for(;;) {
621 int64_t bs_num;
622 int remainder;
623 uint8_t *buf2;
625 nb_sectors = total_sectors - sector_num;
626 if (nb_sectors <= 0)
627 break;
628 if (nb_sectors >= cluster_sectors)
629 n = cluster_sectors;
630 else
631 n = nb_sectors;
633 bs_num = sector_num - bs_offset;
634 assert (bs_num >= 0);
635 remainder = n;
636 buf2 = buf;
637 while (remainder > 0) {
638 int nlow;
639 while (bs_num == bs_sectors) {
640 bs_i++;
641 assert (bs_i < bs_n);
642 bs_offset += bs_sectors;
643 bdrv_get_geometry(bs[bs_i], &bs_sectors);
644 bs_num = 0;
645 /* printf("changing part: sector_num=%lld, "
646 "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
647 sector_num, bs_i, bs_offset, bs_sectors); */
649 assert (bs_num < bs_sectors);
651 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
653 if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0)
654 error("error while reading");
656 buf2 += nlow * 512;
657 bs_num += nlow;
659 remainder -= nlow;
661 assert (remainder == 0);
663 if (n < cluster_sectors)
664 memset(buf + n * 512, 0, cluster_size - n * 512);
665 if (is_not_zero(buf, cluster_size)) {
666 if (bdrv_write_compressed(out_bs, sector_num, buf,
667 cluster_sectors) != 0)
668 error("error while compressing sector %" PRId64,
669 sector_num);
671 sector_num += n;
673 /* signal EOF to align */
674 bdrv_write_compressed(out_bs, 0, NULL, 0);
675 } else {
676 sector_num = 0; // total number of sectors converted so far
677 for(;;) {
678 nb_sectors = total_sectors - sector_num;
679 if (nb_sectors <= 0)
680 break;
681 if (nb_sectors >= (IO_BUF_SIZE / 512))
682 n = (IO_BUF_SIZE / 512);
683 else
684 n = nb_sectors;
686 while (sector_num - bs_offset >= bs_sectors) {
687 bs_i ++;
688 assert (bs_i < bs_n);
689 bs_offset += bs_sectors;
690 bdrv_get_geometry(bs[bs_i], &bs_sectors);
691 /* printf("changing part: sector_num=%lld, bs_i=%d, "
692 "bs_offset=%lld, bs_sectors=%lld\n",
693 sector_num, bs_i, bs_offset, bs_sectors); */
696 if (n > bs_offset + bs_sectors - sector_num)
697 n = bs_offset + bs_sectors - sector_num;
699 if (strcmp(drv->format_name, "host_device")) {
700 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
701 n, &n1)) {
702 sector_num += n1;
703 continue;
705 /* The next 'n1' sectors are allocated in the input image. Copy
706 only those as they may be followed by unallocated sectors. */
707 n = n1;
708 } else {
709 n1 = n;
712 if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
713 error("error while reading");
714 /* NOTE: at the same time we convert, we do not write zero
715 sectors to have a chance to compress the image. Ideally, we
716 should add a specific call to have the info to go faster */
717 buf1 = buf;
718 while (n > 0) {
719 /* If the output image is being created as a copy on write image,
720 copy all sectors even the ones containing only NUL bytes,
721 because they may differ from the sectors in the base image.
723 If the output is to a host device, we also write out
724 sectors that are entirely 0, since whatever data was
725 already there is garbage, not 0s. */
726 if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg ||
727 is_allocated_sectors(buf1, n, &n1)) {
728 if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
729 error("error while writing");
731 sector_num += n1;
732 n -= n1;
733 buf1 += n1 * 512;
737 bdrv_delete(out_bs);
738 for (bs_i = 0; bs_i < bs_n; bs_i++)
739 bdrv_delete(bs[bs_i]);
740 free(bs);
741 return 0;
744 #ifdef _WIN32
745 static int64_t get_allocated_file_size(const char *filename)
747 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
748 get_compressed_t get_compressed;
749 struct _stati64 st;
751 /* WinNT support GetCompressedFileSize to determine allocate size */
752 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
753 if (get_compressed) {
754 DWORD high, low;
755 low = get_compressed(filename, &high);
756 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
757 return (((int64_t) high) << 32) + low;
760 if (_stati64(filename, &st) < 0)
761 return -1;
762 return st.st_size;
764 #else
765 static int64_t get_allocated_file_size(const char *filename)
767 struct stat st;
768 if (stat(filename, &st) < 0)
769 return -1;
770 return (int64_t)st.st_blocks * 512;
772 #endif
774 static void dump_snapshots(BlockDriverState *bs)
776 QEMUSnapshotInfo *sn_tab, *sn;
777 int nb_sns, i;
778 char buf[256];
780 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
781 if (nb_sns <= 0)
782 return;
783 printf("Snapshot list:\n");
784 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
785 for(i = 0; i < nb_sns; i++) {
786 sn = &sn_tab[i];
787 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
789 qemu_free(sn_tab);
792 static int img_info(int argc, char **argv)
794 int c;
795 const char *filename, *fmt;
796 BlockDriver *drv;
797 BlockDriverState *bs;
798 char fmt_name[128], size_buf[128], dsize_buf[128];
799 uint64_t total_sectors;
800 int64_t allocated_size;
801 char backing_filename[1024];
802 char backing_filename2[1024];
803 BlockDriverInfo bdi;
805 fmt = NULL;
806 for(;;) {
807 c = getopt(argc, argv, "f:h");
808 if (c == -1)
809 break;
810 switch(c) {
811 case 'h':
812 help();
813 break;
814 case 'f':
815 fmt = optarg;
816 break;
819 if (optind >= argc)
820 help();
821 filename = argv[optind++];
823 bs = bdrv_new("");
824 if (!bs)
825 error("Not enough memory");
826 if (fmt) {
827 drv = bdrv_find_format(fmt);
828 if (!drv)
829 error("Unknown file format '%s'", fmt);
830 } else {
831 drv = NULL;
833 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
834 error("Could not open '%s'", filename);
836 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
837 bdrv_get_geometry(bs, &total_sectors);
838 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
839 allocated_size = get_allocated_file_size(filename);
840 if (allocated_size < 0)
841 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
842 else
843 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
844 allocated_size);
845 printf("image: %s\n"
846 "file format: %s\n"
847 "virtual size: %s (%" PRId64 " bytes)\n"
848 "disk size: %s\n",
849 filename, fmt_name, size_buf,
850 (total_sectors * 512),
851 dsize_buf);
852 if (bdrv_is_encrypted(bs))
853 printf("encrypted: yes\n");
854 if (bdrv_get_info(bs, &bdi) >= 0) {
855 if (bdi.cluster_size != 0)
856 printf("cluster_size: %d\n", bdi.cluster_size);
858 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
859 if (backing_filename[0] != '\0') {
860 path_combine(backing_filename2, sizeof(backing_filename2),
861 filename, backing_filename);
862 printf("backing file: %s (actual path: %s)\n",
863 backing_filename,
864 backing_filename2);
866 dump_snapshots(bs);
867 bdrv_delete(bs);
868 return 0;
871 #define SNAPSHOT_LIST 1
872 #define SNAPSHOT_CREATE 2
873 #define SNAPSHOT_APPLY 3
874 #define SNAPSHOT_DELETE 4
876 static void img_snapshot(int argc, char **argv)
878 BlockDriverState *bs;
879 QEMUSnapshotInfo sn;
880 char *filename, *snapshot_name = NULL;
881 int c, ret;
882 int action = 0;
883 qemu_timeval tv;
885 /* Parse commandline parameters */
886 for(;;) {
887 c = getopt(argc, argv, "la:c:d:h");
888 if (c == -1)
889 break;
890 switch(c) {
891 case 'h':
892 help();
893 return;
894 case 'l':
895 if (action) {
896 help();
897 return;
899 action = SNAPSHOT_LIST;
900 break;
901 case 'a':
902 if (action) {
903 help();
904 return;
906 action = SNAPSHOT_APPLY;
907 snapshot_name = optarg;
908 break;
909 case 'c':
910 if (action) {
911 help();
912 return;
914 action = SNAPSHOT_CREATE;
915 snapshot_name = optarg;
916 break;
917 case 'd':
918 if (action) {
919 help();
920 return;
922 action = SNAPSHOT_DELETE;
923 snapshot_name = optarg;
924 break;
928 if (optind >= argc)
929 help();
930 filename = argv[optind++];
932 /* Open the image */
933 bs = bdrv_new("");
934 if (!bs)
935 error("Not enough memory");
937 if (bdrv_open2(bs, filename, 0, NULL) < 0) {
938 error("Could not open '%s'", filename);
941 /* Perform the requested action */
942 switch(action) {
943 case SNAPSHOT_LIST:
944 dump_snapshots(bs);
945 break;
947 case SNAPSHOT_CREATE:
948 memset(&sn, 0, sizeof(sn));
949 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
951 qemu_gettimeofday(&tv);
952 sn.date_sec = tv.tv_sec;
953 sn.date_nsec = tv.tv_usec * 1000;
955 ret = bdrv_snapshot_create(bs, &sn);
956 if (ret)
957 error("Could not create snapshot '%s': %d (%s)",
958 snapshot_name, ret, strerror(-ret));
959 break;
961 case SNAPSHOT_APPLY:
962 ret = bdrv_snapshot_goto(bs, snapshot_name);
963 if (ret)
964 error("Could not apply snapshot '%s': %d (%s)",
965 snapshot_name, ret, strerror(-ret));
966 break;
968 case SNAPSHOT_DELETE:
969 ret = bdrv_snapshot_delete(bs, snapshot_name);
970 if (ret)
971 error("Could not delete snapshot '%s': %d (%s)",
972 snapshot_name, ret, strerror(-ret));
973 break;
976 /* Cleanup */
977 bdrv_delete(bs);
980 int main(int argc, char **argv)
982 const char *cmd;
984 bdrv_init();
985 if (argc < 2)
986 help();
987 cmd = argv[1];
988 argc--; argv++;
989 if (!strcmp(cmd, "create")) {
990 img_create(argc, argv);
991 } else if (!strcmp(cmd, "check")) {
992 img_check(argc, argv);
993 } else if (!strcmp(cmd, "commit")) {
994 img_commit(argc, argv);
995 } else if (!strcmp(cmd, "convert")) {
996 img_convert(argc, argv);
997 } else if (!strcmp(cmd, "info")) {
998 img_info(argc, argv);
999 } else if (!strcmp(cmd, "snapshot")) {
1000 img_snapshot(argc, argv);
1001 } else {
1002 help();
1004 return 0;