qemu-img: Print available options with -o ?
[armpft.git] / qemu-img.c
blob947e71beab484c517c864611b6a96217a0f603fb
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 void add_old_style_options(const char *fmt, QEMUOptionParameter *list,
219 int flags, const char *base_filename, const char *base_fmt)
221 if (flags & BLOCK_FLAG_ENCRYPT) {
222 if (set_option_parameter(list, BLOCK_OPT_ENCRYPT, "on")) {
223 error("Encryption not supported for file format '%s'", fmt);
226 if (flags & BLOCK_FLAG_COMPAT6) {
227 if (set_option_parameter(list, BLOCK_OPT_COMPAT6, "on")) {
228 error("VMDK version 6 not supported for file format '%s'", fmt);
232 if (base_filename) {
233 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
234 error("Backing file not supported for file format '%s'", fmt);
237 if (base_fmt) {
238 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
239 error("Backing file format not supported for file format '%s'", fmt);
244 static int img_create(int argc, char **argv)
246 int c, ret, flags;
247 const char *fmt = "raw";
248 const char *base_fmt = NULL;
249 const char *filename;
250 const char *base_filename = NULL;
251 BlockDriver *drv;
252 QEMUOptionParameter *param = NULL;
253 char *options = NULL;
255 flags = 0;
256 for(;;) {
257 c = getopt(argc, argv, "F:b:f:he6o:");
258 if (c == -1)
259 break;
260 switch(c) {
261 case 'h':
262 help();
263 break;
264 case 'F':
265 base_fmt = optarg;
266 break;
267 case 'b':
268 base_filename = optarg;
269 break;
270 case 'f':
271 fmt = optarg;
272 break;
273 case 'e':
274 flags |= BLOCK_FLAG_ENCRYPT;
275 break;
276 case '6':
277 flags |= BLOCK_FLAG_COMPAT6;
278 break;
279 case 'o':
280 options = optarg;
281 break;
285 /* Find driver and parse its options */
286 drv = bdrv_find_format(fmt);
287 if (!drv)
288 error("Unknown file format '%s'", fmt);
290 if (options && !strcmp(options, "?")) {
291 print_option_help(drv->create_options);
292 return 0;
295 if (options) {
296 param = parse_option_parameters(options, drv->create_options, param);
297 if (param == NULL) {
298 error("Invalid options for file format '%s'.", fmt);
300 } else {
301 param = parse_option_parameters("", drv->create_options, param);
304 /* Get the filename */
305 if (optind >= argc)
306 help();
307 filename = argv[optind++];
309 /* Add size to parameters */
310 if (optind < argc) {
311 set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
314 /* Add old-style options to parameters */
315 add_old_style_options(fmt, param, flags, base_filename, base_fmt);
317 // The size for the image must always be specified, with one exception:
318 // If we are using a backing file, we can obtain the size from there
319 if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == 0) {
321 QEMUOptionParameter *backing_file =
322 get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
323 QEMUOptionParameter *backing_fmt =
324 get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
326 if (backing_file && backing_file->value.s) {
327 BlockDriverState *bs;
328 uint64_t size;
329 const char *fmt = NULL;
330 char buf[32];
332 if (backing_fmt && backing_fmt->value.s) {
333 if (bdrv_find_format(backing_fmt->value.s)) {
334 fmt = backing_fmt->value.s;
335 } else {
336 error("Unknown backing file format '%s'",
337 backing_fmt->value.s);
341 bs = bdrv_new_open(backing_file->value.s, fmt);
342 bdrv_get_geometry(bs, &size);
343 size *= 512;
344 bdrv_delete(bs);
346 snprintf(buf, sizeof(buf), "%" PRId64, size);
347 set_option_parameter(param, BLOCK_OPT_SIZE, buf);
348 } else {
349 error("Image creation needs a size parameter");
353 printf("Formatting '%s', fmt=%s ", filename, fmt);
354 print_option_parameters(param);
355 puts("");
357 ret = bdrv_create(drv, filename, param);
358 free_option_parameters(param);
360 if (ret < 0) {
361 if (ret == -ENOTSUP) {
362 error("Formatting or formatting option not supported for file format '%s'", fmt);
363 } else if (ret == -EFBIG) {
364 error("The image size is too large for file format '%s'", fmt);
365 } else {
366 error("Error while formatting");
369 return 0;
372 static int img_check(int argc, char **argv)
374 int c, ret;
375 const char *filename, *fmt;
376 BlockDriver *drv;
377 BlockDriverState *bs;
379 fmt = NULL;
380 for(;;) {
381 c = getopt(argc, argv, "f:h");
382 if (c == -1)
383 break;
384 switch(c) {
385 case 'h':
386 help();
387 break;
388 case 'f':
389 fmt = optarg;
390 break;
393 if (optind >= argc)
394 help();
395 filename = argv[optind++];
397 bs = bdrv_new("");
398 if (!bs)
399 error("Not enough memory");
400 if (fmt) {
401 drv = bdrv_find_format(fmt);
402 if (!drv)
403 error("Unknown file format '%s'", fmt);
404 } else {
405 drv = NULL;
407 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
408 error("Could not open '%s'", filename);
410 ret = bdrv_check(bs);
411 switch(ret) {
412 case 0:
413 printf("No errors were found on the image.\n");
414 break;
415 case -ENOTSUP:
416 error("This image format does not support checks");
417 break;
418 default:
419 if (ret < 0) {
420 error("An error occurred during the check");
421 } else {
422 printf("%d errors were found on the image.\n", ret);
424 break;
427 bdrv_delete(bs);
428 return 0;
431 static int img_commit(int argc, char **argv)
433 int c, ret;
434 const char *filename, *fmt;
435 BlockDriver *drv;
436 BlockDriverState *bs;
438 fmt = NULL;
439 for(;;) {
440 c = getopt(argc, argv, "f:h");
441 if (c == -1)
442 break;
443 switch(c) {
444 case 'h':
445 help();
446 break;
447 case 'f':
448 fmt = optarg;
449 break;
452 if (optind >= argc)
453 help();
454 filename = argv[optind++];
456 bs = bdrv_new("");
457 if (!bs)
458 error("Not enough memory");
459 if (fmt) {
460 drv = bdrv_find_format(fmt);
461 if (!drv)
462 error("Unknown file format '%s'", fmt);
463 } else {
464 drv = NULL;
466 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
467 error("Could not open '%s'", filename);
469 ret = bdrv_commit(bs);
470 switch(ret) {
471 case 0:
472 printf("Image committed.\n");
473 break;
474 case -ENOENT:
475 error("No disk inserted");
476 break;
477 case -EACCES:
478 error("Image is read-only");
479 break;
480 case -ENOTSUP:
481 error("Image is already committed");
482 break;
483 default:
484 error("Error while committing image");
485 break;
488 bdrv_delete(bs);
489 return 0;
492 static int is_not_zero(const uint8_t *sector, int len)
494 int i;
495 len >>= 2;
496 for(i = 0;i < len; i++) {
497 if (((uint32_t *)sector)[i] != 0)
498 return 1;
500 return 0;
504 * Returns true iff the first sector pointed to by 'buf' contains at least
505 * a non-NUL byte.
507 * 'pnum' is set to the number of sectors (including and immediately following
508 * the first one) that are known to be in the same allocated/unallocated state.
510 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
512 int v, i;
514 if (n <= 0) {
515 *pnum = 0;
516 return 0;
518 v = is_not_zero(buf, 512);
519 for(i = 1; i < n; i++) {
520 buf += 512;
521 if (v != is_not_zero(buf, 512))
522 break;
524 *pnum = i;
525 return v;
528 #define IO_BUF_SIZE 65536
530 static int img_convert(int argc, char **argv)
532 int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
533 const char *fmt, *out_fmt, *out_baseimg, *out_filename;
534 BlockDriver *drv;
535 BlockDriverState **bs, *out_bs;
536 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
537 uint64_t bs_sectors;
538 uint8_t buf[IO_BUF_SIZE];
539 const uint8_t *buf1;
540 BlockDriverInfo bdi;
541 QEMUOptionParameter *param = NULL;
542 char *options = NULL;
544 fmt = NULL;
545 out_fmt = "raw";
546 out_baseimg = NULL;
547 flags = 0;
548 for(;;) {
549 c = getopt(argc, argv, "f:O:B:hce6o:");
550 if (c == -1)
551 break;
552 switch(c) {
553 case 'h':
554 help();
555 break;
556 case 'f':
557 fmt = optarg;
558 break;
559 case 'O':
560 out_fmt = optarg;
561 break;
562 case 'B':
563 out_baseimg = optarg;
564 break;
565 case 'c':
566 flags |= BLOCK_FLAG_COMPRESS;
567 break;
568 case 'e':
569 flags |= BLOCK_FLAG_ENCRYPT;
570 break;
571 case '6':
572 flags |= BLOCK_FLAG_COMPAT6;
573 break;
574 case 'o':
575 options = optarg;
576 break;
580 bs_n = argc - optind - 1;
581 if (bs_n < 1) help();
583 out_filename = argv[argc - 1];
585 if (bs_n > 1 && out_baseimg)
586 error("-B makes no sense when concatenating multiple input images");
588 bs = calloc(bs_n, sizeof(BlockDriverState *));
589 if (!bs)
590 error("Out of memory");
592 total_sectors = 0;
593 for (bs_i = 0; bs_i < bs_n; bs_i++) {
594 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
595 if (!bs[bs_i])
596 error("Could not open '%s'", argv[optind + bs_i]);
597 bdrv_get_geometry(bs[bs_i], &bs_sectors);
598 total_sectors += bs_sectors;
601 /* Find driver and parse its options */
602 drv = bdrv_find_format(out_fmt);
603 if (!drv)
604 error("Unknown file format '%s'", out_fmt);
606 if (options && !strcmp(options, "?")) {
607 print_option_help(drv->create_options);
608 return 0;
611 if (options) {
612 param = parse_option_parameters(options, drv->create_options, param);
613 if (param == NULL) {
614 error("Invalid options for file format '%s'.", out_fmt);
616 } else {
617 param = parse_option_parameters("", drv->create_options, param);
620 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
621 add_old_style_options(out_fmt, param, flags, out_baseimg, NULL);
623 /* Check if compression is supported */
624 if (flags & BLOCK_FLAG_COMPRESS) {
625 QEMUOptionParameter *encryption =
626 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
628 if (!drv->bdrv_write_compressed) {
629 error("Compression not supported for this file format");
632 if (encryption && encryption->value.n) {
633 error("Compression and encryption not supported at the same time");
637 /* Create the new image */
638 ret = bdrv_create(drv, out_filename, param);
639 free_option_parameters(param);
641 if (ret < 0) {
642 if (ret == -ENOTSUP) {
643 error("Formatting not supported for file format '%s'", out_fmt);
644 } else if (ret == -EFBIG) {
645 error("The image size is too large for file format '%s'", out_fmt);
646 } else {
647 error("Error while formatting '%s'", out_filename);
651 out_bs = bdrv_new_open(out_filename, out_fmt);
653 bs_i = 0;
654 bs_offset = 0;
655 bdrv_get_geometry(bs[0], &bs_sectors);
657 if (flags & BLOCK_FLAG_COMPRESS) {
658 if (bdrv_get_info(out_bs, &bdi) < 0)
659 error("could not get block driver info");
660 cluster_size = bdi.cluster_size;
661 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
662 error("invalid cluster size");
663 cluster_sectors = cluster_size >> 9;
664 sector_num = 0;
665 for(;;) {
666 int64_t bs_num;
667 int remainder;
668 uint8_t *buf2;
670 nb_sectors = total_sectors - sector_num;
671 if (nb_sectors <= 0)
672 break;
673 if (nb_sectors >= cluster_sectors)
674 n = cluster_sectors;
675 else
676 n = nb_sectors;
678 bs_num = sector_num - bs_offset;
679 assert (bs_num >= 0);
680 remainder = n;
681 buf2 = buf;
682 while (remainder > 0) {
683 int nlow;
684 while (bs_num == bs_sectors) {
685 bs_i++;
686 assert (bs_i < bs_n);
687 bs_offset += bs_sectors;
688 bdrv_get_geometry(bs[bs_i], &bs_sectors);
689 bs_num = 0;
690 /* printf("changing part: sector_num=%lld, "
691 "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
692 sector_num, bs_i, bs_offset, bs_sectors); */
694 assert (bs_num < bs_sectors);
696 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
698 if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0)
699 error("error while reading");
701 buf2 += nlow * 512;
702 bs_num += nlow;
704 remainder -= nlow;
706 assert (remainder == 0);
708 if (n < cluster_sectors)
709 memset(buf + n * 512, 0, cluster_size - n * 512);
710 if (is_not_zero(buf, cluster_size)) {
711 if (bdrv_write_compressed(out_bs, sector_num, buf,
712 cluster_sectors) != 0)
713 error("error while compressing sector %" PRId64,
714 sector_num);
716 sector_num += n;
718 /* signal EOF to align */
719 bdrv_write_compressed(out_bs, 0, NULL, 0);
720 } else {
721 sector_num = 0; // total number of sectors converted so far
722 for(;;) {
723 nb_sectors = total_sectors - sector_num;
724 if (nb_sectors <= 0)
725 break;
726 if (nb_sectors >= (IO_BUF_SIZE / 512))
727 n = (IO_BUF_SIZE / 512);
728 else
729 n = nb_sectors;
731 while (sector_num - bs_offset >= bs_sectors) {
732 bs_i ++;
733 assert (bs_i < bs_n);
734 bs_offset += bs_sectors;
735 bdrv_get_geometry(bs[bs_i], &bs_sectors);
736 /* printf("changing part: sector_num=%lld, bs_i=%d, "
737 "bs_offset=%lld, bs_sectors=%lld\n",
738 sector_num, bs_i, bs_offset, bs_sectors); */
741 if (n > bs_offset + bs_sectors - sector_num)
742 n = bs_offset + bs_sectors - sector_num;
744 if (strcmp(drv->format_name, "host_device")) {
745 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
746 n, &n1)) {
747 sector_num += n1;
748 continue;
750 /* The next 'n1' sectors are allocated in the input image. Copy
751 only those as they may be followed by unallocated sectors. */
752 n = n1;
753 } else {
754 n1 = n;
757 if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
758 error("error while reading");
759 /* NOTE: at the same time we convert, we do not write zero
760 sectors to have a chance to compress the image. Ideally, we
761 should add a specific call to have the info to go faster */
762 buf1 = buf;
763 while (n > 0) {
764 /* If the output image is being created as a copy on write image,
765 copy all sectors even the ones containing only NUL bytes,
766 because they may differ from the sectors in the base image.
768 If the output is to a host device, we also write out
769 sectors that are entirely 0, since whatever data was
770 already there is garbage, not 0s. */
771 if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg ||
772 is_allocated_sectors(buf1, n, &n1)) {
773 if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
774 error("error while writing");
776 sector_num += n1;
777 n -= n1;
778 buf1 += n1 * 512;
782 bdrv_delete(out_bs);
783 for (bs_i = 0; bs_i < bs_n; bs_i++)
784 bdrv_delete(bs[bs_i]);
785 free(bs);
786 return 0;
789 #ifdef _WIN32
790 static int64_t get_allocated_file_size(const char *filename)
792 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
793 get_compressed_t get_compressed;
794 struct _stati64 st;
796 /* WinNT support GetCompressedFileSize to determine allocate size */
797 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
798 if (get_compressed) {
799 DWORD high, low;
800 low = get_compressed(filename, &high);
801 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
802 return (((int64_t) high) << 32) + low;
805 if (_stati64(filename, &st) < 0)
806 return -1;
807 return st.st_size;
809 #else
810 static int64_t get_allocated_file_size(const char *filename)
812 struct stat st;
813 if (stat(filename, &st) < 0)
814 return -1;
815 return (int64_t)st.st_blocks * 512;
817 #endif
819 static void dump_snapshots(BlockDriverState *bs)
821 QEMUSnapshotInfo *sn_tab, *sn;
822 int nb_sns, i;
823 char buf[256];
825 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
826 if (nb_sns <= 0)
827 return;
828 printf("Snapshot list:\n");
829 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
830 for(i = 0; i < nb_sns; i++) {
831 sn = &sn_tab[i];
832 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
834 qemu_free(sn_tab);
837 static int img_info(int argc, char **argv)
839 int c;
840 const char *filename, *fmt;
841 BlockDriver *drv;
842 BlockDriverState *bs;
843 char fmt_name[128], size_buf[128], dsize_buf[128];
844 uint64_t total_sectors;
845 int64_t allocated_size;
846 char backing_filename[1024];
847 char backing_filename2[1024];
848 BlockDriverInfo bdi;
850 fmt = NULL;
851 for(;;) {
852 c = getopt(argc, argv, "f:h");
853 if (c == -1)
854 break;
855 switch(c) {
856 case 'h':
857 help();
858 break;
859 case 'f':
860 fmt = optarg;
861 break;
864 if (optind >= argc)
865 help();
866 filename = argv[optind++];
868 bs = bdrv_new("");
869 if (!bs)
870 error("Not enough memory");
871 if (fmt) {
872 drv = bdrv_find_format(fmt);
873 if (!drv)
874 error("Unknown file format '%s'", fmt);
875 } else {
876 drv = NULL;
878 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
879 error("Could not open '%s'", filename);
881 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
882 bdrv_get_geometry(bs, &total_sectors);
883 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
884 allocated_size = get_allocated_file_size(filename);
885 if (allocated_size < 0)
886 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
887 else
888 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
889 allocated_size);
890 printf("image: %s\n"
891 "file format: %s\n"
892 "virtual size: %s (%" PRId64 " bytes)\n"
893 "disk size: %s\n",
894 filename, fmt_name, size_buf,
895 (total_sectors * 512),
896 dsize_buf);
897 if (bdrv_is_encrypted(bs))
898 printf("encrypted: yes\n");
899 if (bdrv_get_info(bs, &bdi) >= 0) {
900 if (bdi.cluster_size != 0)
901 printf("cluster_size: %d\n", bdi.cluster_size);
903 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
904 if (backing_filename[0] != '\0') {
905 path_combine(backing_filename2, sizeof(backing_filename2),
906 filename, backing_filename);
907 printf("backing file: %s (actual path: %s)\n",
908 backing_filename,
909 backing_filename2);
911 dump_snapshots(bs);
912 bdrv_delete(bs);
913 return 0;
916 #define SNAPSHOT_LIST 1
917 #define SNAPSHOT_CREATE 2
918 #define SNAPSHOT_APPLY 3
919 #define SNAPSHOT_DELETE 4
921 static void img_snapshot(int argc, char **argv)
923 BlockDriverState *bs;
924 QEMUSnapshotInfo sn;
925 char *filename, *snapshot_name = NULL;
926 int c, ret;
927 int action = 0;
928 qemu_timeval tv;
930 /* Parse commandline parameters */
931 for(;;) {
932 c = getopt(argc, argv, "la:c:d:h");
933 if (c == -1)
934 break;
935 switch(c) {
936 case 'h':
937 help();
938 return;
939 case 'l':
940 if (action) {
941 help();
942 return;
944 action = SNAPSHOT_LIST;
945 break;
946 case 'a':
947 if (action) {
948 help();
949 return;
951 action = SNAPSHOT_APPLY;
952 snapshot_name = optarg;
953 break;
954 case 'c':
955 if (action) {
956 help();
957 return;
959 action = SNAPSHOT_CREATE;
960 snapshot_name = optarg;
961 break;
962 case 'd':
963 if (action) {
964 help();
965 return;
967 action = SNAPSHOT_DELETE;
968 snapshot_name = optarg;
969 break;
973 if (optind >= argc)
974 help();
975 filename = argv[optind++];
977 /* Open the image */
978 bs = bdrv_new("");
979 if (!bs)
980 error("Not enough memory");
982 if (bdrv_open2(bs, filename, 0, NULL) < 0) {
983 error("Could not open '%s'", filename);
986 /* Perform the requested action */
987 switch(action) {
988 case SNAPSHOT_LIST:
989 dump_snapshots(bs);
990 break;
992 case SNAPSHOT_CREATE:
993 memset(&sn, 0, sizeof(sn));
994 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
996 qemu_gettimeofday(&tv);
997 sn.date_sec = tv.tv_sec;
998 sn.date_nsec = tv.tv_usec * 1000;
1000 ret = bdrv_snapshot_create(bs, &sn);
1001 if (ret)
1002 error("Could not create snapshot '%s': %d (%s)",
1003 snapshot_name, ret, strerror(-ret));
1004 break;
1006 case SNAPSHOT_APPLY:
1007 ret = bdrv_snapshot_goto(bs, snapshot_name);
1008 if (ret)
1009 error("Could not apply snapshot '%s': %d (%s)",
1010 snapshot_name, ret, strerror(-ret));
1011 break;
1013 case SNAPSHOT_DELETE:
1014 ret = bdrv_snapshot_delete(bs, snapshot_name);
1015 if (ret)
1016 error("Could not delete snapshot '%s': %d (%s)",
1017 snapshot_name, ret, strerror(-ret));
1018 break;
1021 /* Cleanup */
1022 bdrv_delete(bs);
1025 int main(int argc, char **argv)
1027 const char *cmd;
1029 bdrv_init();
1030 if (argc < 2)
1031 help();
1032 cmd = argv[1];
1033 argc--; argv++;
1034 if (!strcmp(cmd, "create")) {
1035 img_create(argc, argv);
1036 } else if (!strcmp(cmd, "check")) {
1037 img_check(argc, argv);
1038 } else if (!strcmp(cmd, "commit")) {
1039 img_commit(argc, argv);
1040 } else if (!strcmp(cmd, "convert")) {
1041 img_convert(argc, argv);
1042 } else if (!strcmp(cmd, "info")) {
1043 img_info(argc, argv);
1044 } else if (!strcmp(cmd, "snapshot")) {
1045 img_snapshot(argc, argv);
1046 } else {
1047 help();
1049 return 0;