Fix x86 feature modifications for features that set multiple bits
[qemu/mdroth.git] / qemu-img.c
blob29149a23c8af3b01ff283c669a295b7fd015220d
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 "osdep.h"
26 #include "block_int.h"
27 #include <assert.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 uint64_t size;
226 double sizef;
227 const char *p;
228 BlockDriver *drv;
230 flags = 0;
231 for(;;) {
232 c = getopt(argc, argv, "F:b:f:he6");
233 if (c == -1)
234 break;
235 switch(c) {
236 case 'h':
237 help();
238 break;
239 case 'F':
240 base_fmt = optarg;
241 break;
242 case 'b':
243 base_filename = optarg;
244 break;
245 case 'f':
246 fmt = optarg;
247 break;
248 case 'e':
249 flags |= BLOCK_FLAG_ENCRYPT;
250 break;
251 case '6':
252 flags |= BLOCK_FLAG_COMPAT6;
253 break;
256 if (optind >= argc)
257 help();
258 filename = argv[optind++];
259 size = 0;
260 if (base_filename) {
261 BlockDriverState *bs;
262 BlockDriver *base_drv = NULL;
264 if (base_fmt) {
265 base_drv = bdrv_find_format(base_fmt);
266 if (base_drv == NULL)
267 error("Unknown basefile format '%s'", base_fmt);
270 bs = bdrv_new_open(base_filename, base_fmt);
271 bdrv_get_geometry(bs, &size);
272 size *= 512;
273 bdrv_delete(bs);
274 } else {
275 if (optind >= argc)
276 help();
277 p = argv[optind];
278 sizef = strtod(p, (char **)&p);
279 if (*p == 'M') {
280 size = (uint64_t)(sizef * 1024 * 1024);
281 } else if (*p == 'G') {
282 size = (uint64_t)(sizef * 1024 * 1024 * 1024);
283 } else if (*p == 'k' || *p == 'K' || *p == '\0') {
284 size = (uint64_t)(sizef * 1024);
285 } else {
286 help();
289 drv = bdrv_find_format(fmt);
290 if (!drv)
291 error("Unknown file format '%s'", fmt);
292 printf("Formatting '%s', fmt=%s",
293 filename, fmt);
294 if (flags & BLOCK_FLAG_ENCRYPT)
295 printf(", encrypted");
296 if (flags & BLOCK_FLAG_COMPAT6)
297 printf(", compatibility level=6");
298 if (base_filename) {
299 printf(", backing_file=%s",
300 base_filename);
301 if (base_fmt)
302 printf(", backing_fmt=%s",
303 base_fmt);
305 printf(", size=%" PRIu64 " kB\n", size / 1024);
306 ret = bdrv_create2(drv, filename, size / 512, base_filename, base_fmt, flags);
307 if (ret < 0) {
308 if (ret == -ENOTSUP) {
309 error("Formatting or formatting option not supported for file format '%s'", fmt);
310 } else if (ret == -EFBIG) {
311 error("The image size is too large for file format '%s'", fmt);
312 } else {
313 error("Error while formatting");
316 return 0;
319 static int img_check(int argc, char **argv)
321 int c, ret;
322 const char *filename, *fmt;
323 BlockDriver *drv;
324 BlockDriverState *bs;
326 fmt = NULL;
327 for(;;) {
328 c = getopt(argc, argv, "f:h");
329 if (c == -1)
330 break;
331 switch(c) {
332 case 'h':
333 help();
334 break;
335 case 'f':
336 fmt = optarg;
337 break;
340 if (optind >= argc)
341 help();
342 filename = argv[optind++];
344 bs = bdrv_new("");
345 if (!bs)
346 error("Not enough memory");
347 if (fmt) {
348 drv = bdrv_find_format(fmt);
349 if (!drv)
350 error("Unknown file format '%s'", fmt);
351 } else {
352 drv = NULL;
354 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
355 error("Could not open '%s'", filename);
357 ret = bdrv_check(bs);
358 switch(ret) {
359 case 0:
360 printf("No errors were found on the image.\n");
361 break;
362 case -ENOTSUP:
363 error("This image format does not support checks");
364 break;
365 default:
366 if (ret < 0) {
367 error("An error occurred during the check");
368 } else {
369 printf("%d errors were found on the image.\n", ret);
371 break;
374 bdrv_delete(bs);
375 return 0;
378 static int img_commit(int argc, char **argv)
380 int c, ret;
381 const char *filename, *fmt;
382 BlockDriver *drv;
383 BlockDriverState *bs;
385 fmt = NULL;
386 for(;;) {
387 c = getopt(argc, argv, "f:h");
388 if (c == -1)
389 break;
390 switch(c) {
391 case 'h':
392 help();
393 break;
394 case 'f':
395 fmt = optarg;
396 break;
399 if (optind >= argc)
400 help();
401 filename = argv[optind++];
403 bs = bdrv_new("");
404 if (!bs)
405 error("Not enough memory");
406 if (fmt) {
407 drv = bdrv_find_format(fmt);
408 if (!drv)
409 error("Unknown file format '%s'", fmt);
410 } else {
411 drv = NULL;
413 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
414 error("Could not open '%s'", filename);
416 ret = bdrv_commit(bs);
417 switch(ret) {
418 case 0:
419 printf("Image committed.\n");
420 break;
421 case -ENOENT:
422 error("No disk inserted");
423 break;
424 case -EACCES:
425 error("Image is read-only");
426 break;
427 case -ENOTSUP:
428 error("Image is already committed");
429 break;
430 default:
431 error("Error while committing image");
432 break;
435 bdrv_delete(bs);
436 return 0;
439 static int is_not_zero(const uint8_t *sector, int len)
441 int i;
442 len >>= 2;
443 for(i = 0;i < len; i++) {
444 if (((uint32_t *)sector)[i] != 0)
445 return 1;
447 return 0;
451 * Returns true iff the first sector pointed to by 'buf' contains at least
452 * a non-NUL byte.
454 * 'pnum' is set to the number of sectors (including and immediately following
455 * the first one) that are known to be in the same allocated/unallocated state.
457 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
459 int v, i;
461 if (n <= 0) {
462 *pnum = 0;
463 return 0;
465 v = is_not_zero(buf, 512);
466 for(i = 1; i < n; i++) {
467 buf += 512;
468 if (v != is_not_zero(buf, 512))
469 break;
471 *pnum = i;
472 return v;
475 #define IO_BUF_SIZE 65536
477 static int img_convert(int argc, char **argv)
479 int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
480 const char *fmt, *out_fmt, *out_baseimg, *out_filename;
481 BlockDriver *drv;
482 BlockDriverState **bs, *out_bs;
483 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
484 uint64_t bs_sectors;
485 uint8_t buf[IO_BUF_SIZE];
486 const uint8_t *buf1;
487 BlockDriverInfo bdi;
489 fmt = NULL;
490 out_fmt = "raw";
491 out_baseimg = NULL;
492 flags = 0;
493 for(;;) {
494 c = getopt(argc, argv, "f:O:B:hce6");
495 if (c == -1)
496 break;
497 switch(c) {
498 case 'h':
499 help();
500 break;
501 case 'f':
502 fmt = optarg;
503 break;
504 case 'O':
505 out_fmt = optarg;
506 break;
507 case 'B':
508 out_baseimg = optarg;
509 break;
510 case 'c':
511 flags |= BLOCK_FLAG_COMPRESS;
512 break;
513 case 'e':
514 flags |= BLOCK_FLAG_ENCRYPT;
515 break;
516 case '6':
517 flags |= BLOCK_FLAG_COMPAT6;
518 break;
522 bs_n = argc - optind - 1;
523 if (bs_n < 1) help();
525 out_filename = argv[argc - 1];
527 if (bs_n > 1 && out_baseimg)
528 error("-B makes no sense when concatenating multiple input images");
530 bs = calloc(bs_n, sizeof(BlockDriverState *));
531 if (!bs)
532 error("Out of memory");
534 total_sectors = 0;
535 for (bs_i = 0; bs_i < bs_n; bs_i++) {
536 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
537 if (!bs[bs_i])
538 error("Could not open '%s'", argv[optind + bs_i]);
539 bdrv_get_geometry(bs[bs_i], &bs_sectors);
540 total_sectors += bs_sectors;
543 drv = bdrv_find_format(out_fmt);
544 if (!drv)
545 error("Unknown file format '%s'", out_fmt);
546 if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2)
547 error("Compression not supported for this file format");
548 if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
549 error("Encryption not supported for this file format");
550 if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
551 error("Alternative compatibility level not supported for this file format");
552 if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
553 error("Compression and encryption not supported at the same time");
555 ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
556 if (ret < 0) {
557 if (ret == -ENOTSUP) {
558 error("Formatting not supported for file format '%s'", out_fmt);
559 } else if (ret == -EFBIG) {
560 error("The image size is too large for file format '%s'", out_fmt);
561 } else {
562 error("Error while formatting '%s'", out_filename);
566 out_bs = bdrv_new_open(out_filename, out_fmt);
568 bs_i = 0;
569 bs_offset = 0;
570 bdrv_get_geometry(bs[0], &bs_sectors);
572 if (flags & BLOCK_FLAG_COMPRESS) {
573 if (bdrv_get_info(out_bs, &bdi) < 0)
574 error("could not get block driver info");
575 cluster_size = bdi.cluster_size;
576 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
577 error("invalid cluster size");
578 cluster_sectors = cluster_size >> 9;
579 sector_num = 0;
580 for(;;) {
581 int64_t bs_num;
582 int remainder;
583 uint8_t *buf2;
585 nb_sectors = total_sectors - sector_num;
586 if (nb_sectors <= 0)
587 break;
588 if (nb_sectors >= cluster_sectors)
589 n = cluster_sectors;
590 else
591 n = nb_sectors;
593 bs_num = sector_num - bs_offset;
594 assert (bs_num >= 0);
595 remainder = n;
596 buf2 = buf;
597 while (remainder > 0) {
598 int nlow;
599 while (bs_num == bs_sectors) {
600 bs_i++;
601 assert (bs_i < bs_n);
602 bs_offset += bs_sectors;
603 bdrv_get_geometry(bs[bs_i], &bs_sectors);
604 bs_num = 0;
605 /* printf("changing part: sector_num=%lld, "
606 "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
607 sector_num, bs_i, bs_offset, bs_sectors); */
609 assert (bs_num < bs_sectors);
611 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
613 if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0)
614 error("error while reading");
616 buf2 += nlow * 512;
617 bs_num += nlow;
619 remainder -= nlow;
621 assert (remainder == 0);
623 if (n < cluster_sectors)
624 memset(buf + n * 512, 0, cluster_size - n * 512);
625 if (is_not_zero(buf, cluster_size)) {
626 if (bdrv_write_compressed(out_bs, sector_num, buf,
627 cluster_sectors) != 0)
628 error("error while compressing sector %" PRId64,
629 sector_num);
631 sector_num += n;
633 /* signal EOF to align */
634 bdrv_write_compressed(out_bs, 0, NULL, 0);
635 } else {
636 sector_num = 0; // total number of sectors converted so far
637 for(;;) {
638 nb_sectors = total_sectors - sector_num;
639 if (nb_sectors <= 0)
640 break;
641 if (nb_sectors >= (IO_BUF_SIZE / 512))
642 n = (IO_BUF_SIZE / 512);
643 else
644 n = nb_sectors;
646 while (sector_num - bs_offset >= bs_sectors) {
647 bs_i ++;
648 assert (bs_i < bs_n);
649 bs_offset += bs_sectors;
650 bdrv_get_geometry(bs[bs_i], &bs_sectors);
651 /* printf("changing part: sector_num=%lld, bs_i=%d, "
652 "bs_offset=%lld, bs_sectors=%lld\n",
653 sector_num, bs_i, bs_offset, bs_sectors); */
656 if (n > bs_offset + bs_sectors - sector_num)
657 n = bs_offset + bs_sectors - sector_num;
659 if (drv != &bdrv_host_device) {
660 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
661 n, &n1)) {
662 sector_num += n1;
663 continue;
665 /* The next 'n1' sectors are allocated in the input image. Copy
666 only those as they may be followed by unallocated sectors. */
667 n = n1;
668 } else {
669 n1 = n;
672 if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
673 error("error while reading");
674 /* NOTE: at the same time we convert, we do not write zero
675 sectors to have a chance to compress the image. Ideally, we
676 should add a specific call to have the info to go faster */
677 buf1 = buf;
678 while (n > 0) {
679 /* If the output image is being created as a copy on write image,
680 copy all sectors even the ones containing only NUL bytes,
681 because they may differ from the sectors in the base image.
683 If the output is to a host device, we also write out
684 sectors that are entirely 0, since whatever data was
685 already there is garbage, not 0s. */
686 if (drv == &bdrv_host_device || out_baseimg ||
687 is_allocated_sectors(buf1, n, &n1)) {
688 if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
689 error("error while writing");
691 sector_num += n1;
692 n -= n1;
693 buf1 += n1 * 512;
697 bdrv_delete(out_bs);
698 for (bs_i = 0; bs_i < bs_n; bs_i++)
699 bdrv_delete(bs[bs_i]);
700 free(bs);
701 return 0;
704 #ifdef _WIN32
705 static int64_t get_allocated_file_size(const char *filename)
707 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
708 get_compressed_t get_compressed;
709 struct _stati64 st;
711 /* WinNT support GetCompressedFileSize to determine allocate size */
712 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
713 if (get_compressed) {
714 DWORD high, low;
715 low = get_compressed(filename, &high);
716 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
717 return (((int64_t) high) << 32) + low;
720 if (_stati64(filename, &st) < 0)
721 return -1;
722 return st.st_size;
724 #else
725 static int64_t get_allocated_file_size(const char *filename)
727 struct stat st;
728 if (stat(filename, &st) < 0)
729 return -1;
730 return (int64_t)st.st_blocks * 512;
732 #endif
734 static void dump_snapshots(BlockDriverState *bs)
736 QEMUSnapshotInfo *sn_tab, *sn;
737 int nb_sns, i;
738 char buf[256];
740 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
741 if (nb_sns <= 0)
742 return;
743 printf("Snapshot list:\n");
744 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
745 for(i = 0; i < nb_sns; i++) {
746 sn = &sn_tab[i];
747 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
749 qemu_free(sn_tab);
752 static int img_info(int argc, char **argv)
754 int c;
755 const char *filename, *fmt;
756 BlockDriver *drv;
757 BlockDriverState *bs;
758 char fmt_name[128], size_buf[128], dsize_buf[128];
759 uint64_t total_sectors;
760 int64_t allocated_size;
761 char backing_filename[1024];
762 char backing_filename2[1024];
763 BlockDriverInfo bdi;
765 fmt = NULL;
766 for(;;) {
767 c = getopt(argc, argv, "f:h");
768 if (c == -1)
769 break;
770 switch(c) {
771 case 'h':
772 help();
773 break;
774 case 'f':
775 fmt = optarg;
776 break;
779 if (optind >= argc)
780 help();
781 filename = argv[optind++];
783 bs = bdrv_new("");
784 if (!bs)
785 error("Not enough memory");
786 if (fmt) {
787 drv = bdrv_find_format(fmt);
788 if (!drv)
789 error("Unknown file format '%s'", fmt);
790 } else {
791 drv = NULL;
793 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
794 error("Could not open '%s'", filename);
796 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
797 bdrv_get_geometry(bs, &total_sectors);
798 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
799 allocated_size = get_allocated_file_size(filename);
800 if (allocated_size < 0)
801 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
802 else
803 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
804 allocated_size);
805 printf("image: %s\n"
806 "file format: %s\n"
807 "virtual size: %s (%" PRId64 " bytes)\n"
808 "disk size: %s\n",
809 filename, fmt_name, size_buf,
810 (total_sectors * 512),
811 dsize_buf);
812 if (bdrv_is_encrypted(bs))
813 printf("encrypted: yes\n");
814 if (bdrv_get_info(bs, &bdi) >= 0) {
815 if (bdi.cluster_size != 0)
816 printf("cluster_size: %d\n", bdi.cluster_size);
818 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
819 if (backing_filename[0] != '\0') {
820 path_combine(backing_filename2, sizeof(backing_filename2),
821 filename, backing_filename);
822 printf("backing file: %s (actual path: %s)\n",
823 backing_filename,
824 backing_filename2);
826 dump_snapshots(bs);
827 bdrv_delete(bs);
828 return 0;
831 #define SNAPSHOT_LIST 1
832 #define SNAPSHOT_CREATE 2
833 #define SNAPSHOT_APPLY 3
834 #define SNAPSHOT_DELETE 4
836 static void img_snapshot(int argc, char **argv)
838 BlockDriverState *bs;
839 QEMUSnapshotInfo sn;
840 char *filename, *snapshot_name = NULL;
841 int c, ret;
842 int action = 0;
843 qemu_timeval tv;
845 /* Parse commandline parameters */
846 for(;;) {
847 c = getopt(argc, argv, "la:c:d:h");
848 if (c == -1)
849 break;
850 switch(c) {
851 case 'h':
852 help();
853 return;
854 case 'l':
855 if (action) {
856 help();
857 return;
859 action = SNAPSHOT_LIST;
860 break;
861 case 'a':
862 if (action) {
863 help();
864 return;
866 action = SNAPSHOT_APPLY;
867 snapshot_name = optarg;
868 break;
869 case 'c':
870 if (action) {
871 help();
872 return;
874 action = SNAPSHOT_CREATE;
875 snapshot_name = optarg;
876 break;
877 case 'd':
878 if (action) {
879 help();
880 return;
882 action = SNAPSHOT_DELETE;
883 snapshot_name = optarg;
884 break;
888 if (optind >= argc)
889 help();
890 filename = argv[optind++];
892 /* Open the image */
893 bs = bdrv_new("");
894 if (!bs)
895 error("Not enough memory");
897 if (bdrv_open2(bs, filename, 0, NULL) < 0) {
898 error("Could not open '%s'", filename);
901 /* Perform the requested action */
902 switch(action) {
903 case SNAPSHOT_LIST:
904 dump_snapshots(bs);
905 break;
907 case SNAPSHOT_CREATE:
908 memset(&sn, 0, sizeof(sn));
909 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
911 qemu_gettimeofday(&tv);
912 sn.date_sec = tv.tv_sec;
913 sn.date_nsec = tv.tv_usec * 1000;
915 ret = bdrv_snapshot_create(bs, &sn);
916 if (ret)
917 error("Could not create snapshot '%s': %d (%s)",
918 snapshot_name, ret, strerror(-ret));
919 break;
921 case SNAPSHOT_APPLY:
922 ret = bdrv_snapshot_goto(bs, snapshot_name);
923 if (ret)
924 error("Could not apply snapshot '%s': %d (%s)",
925 snapshot_name, ret, strerror(-ret));
926 break;
928 case SNAPSHOT_DELETE:
929 ret = bdrv_snapshot_delete(bs, snapshot_name);
930 if (ret)
931 error("Could not delete snapshot '%s': %d (%s)",
932 snapshot_name, ret, strerror(-ret));
933 break;
936 /* Cleanup */
937 bdrv_delete(bs);
940 int main(int argc, char **argv)
942 const char *cmd;
944 bdrv_init();
945 if (argc < 2)
946 help();
947 cmd = argv[1];
948 argc--; argv++;
949 if (!strcmp(cmd, "create")) {
950 img_create(argc, argv);
951 } else if (!strcmp(cmd, "check")) {
952 img_check(argc, argv);
953 } else if (!strcmp(cmd, "commit")) {
954 img_commit(argc, argv);
955 } else if (!strcmp(cmd, "convert")) {
956 img_convert(argc, argv);
957 } else if (!strcmp(cmd, "info")) {
958 img_info(argc, argv);
959 } else if (!strcmp(cmd, "snapshot")) {
960 img_snapshot(argc, argv);
961 } else {
962 help();
964 return 0;