block-vpc: Don't silently create smaller image than requested
[qemu] / qemu-img.c
1 /*
2  * QEMU disk image utility
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  *
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  */
24 #include "qemu-common.h"
25 #include "osdep.h"
26 #include "block_int.h"
27 #include <assert.h>
28 #include <stdio.h>
29
30 #ifdef _WIN32
31 #include <windows.h>
32 #endif
33
34 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
35 #define BRDV_O_FLAGS BDRV_O_CACHE_WB
36
37 static void QEMU_NORETURN error(const char *fmt, ...)
38 {
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);
46 }
47
48 static void format_print(void *opaque, const char *name)
49 {
50     printf(" %s", name);
51 }
52
53 /* Please keep in synch with qemu-img.texi */
54 static void help(void)
55 {
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            "  create [-e] [-6] [-F fmt] [-b base_image] [-f fmt] filename [size]\n"
62            "  commit [-f fmt] filename\n"
63            "  convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
64            "  info [-f fmt] filename\n"
65            "  snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename\n"
66            "\n"
67            "Command parameters:\n"
68            "  'filename' is a disk image filename\n"
69            "  'base_image' is the read-only disk image which is used as base for a copy on\n"
70            "    write image; the copy on write image only stores the modified data\n"
71            "  'output_base_image' forces the output image to be created as a copy on write\n"
72            "    image of the specified base image; 'output_base_image' should have the same\n"
73            "    content as the input's base image, however the path, image format, etc may\n"
74            "    differ\n"
75            "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
76            "  'size' is the disk image size in kilobytes. Optional suffixes\n"
77            "    'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
78            "    supported any 'k' or 'K' is ignored\n"
79            "  'output_filename' is the destination disk image filename\n"
80            "  'output_fmt' is the destination format\n"
81            "  '-c' indicates that target image must be compressed (qcow format only)\n"
82            "  '-e' indicates that the target image must be encrypted (qcow format only)\n"
83            "  '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
84            "  '-h' with or without a command shows this help and lists the supported formats\n"
85            "\n"
86            "Parameters to snapshot subcommand:\n"
87            "  'snapshot' is the name of the snapshot to create, apply or delete\n"
88            "  '-a' applies a snapshot (revert disk to saved state)\n"
89            "  '-c' creates a snapshot\n"
90            "  '-d' deletes a snapshot\n"
91            "  '-l' lists all snapshots in the given image\n"
92            );
93     printf("\nSupported formats:");
94     bdrv_iterate_format(format_print, NULL);
95     printf("\n");
96     exit(1);
97 }
98
99 #if defined(WIN32)
100 /* XXX: put correct support for win32 */
101 static int read_password(char *buf, int buf_size)
102 {
103     int c, i;
104     printf("Password: ");
105     fflush(stdout);
106     i = 0;
107     for(;;) {
108         c = getchar();
109         if (c == '\n')
110             break;
111         if (i < (buf_size - 1))
112             buf[i++] = c;
113     }
114     buf[i] = '\0';
115     return 0;
116 }
117
118 #else
119
120 #include <termios.h>
121
122 static struct termios oldtty;
123
124 static void term_exit(void)
125 {
126     tcsetattr (0, TCSANOW, &oldtty);
127 }
128
129 static void term_init(void)
130 {
131     struct termios tty;
132
133     tcgetattr (0, &tty);
134     oldtty = tty;
135
136     tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
137                           |INLCR|IGNCR|ICRNL|IXON);
138     tty.c_oflag |= OPOST;
139     tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
140     tty.c_cflag &= ~(CSIZE|PARENB);
141     tty.c_cflag |= CS8;
142     tty.c_cc[VMIN] = 1;
143     tty.c_cc[VTIME] = 0;
144
145     tcsetattr (0, TCSANOW, &tty);
146
147     atexit(term_exit);
148 }
149
150 static int read_password(char *buf, int buf_size)
151 {
152     uint8_t ch;
153     int i, ret;
154
155     printf("password: ");
156     fflush(stdout);
157     term_init();
158     i = 0;
159     for(;;) {
160         ret = read(0, &ch, 1);
161         if (ret == -1) {
162             if (errno == EAGAIN || errno == EINTR) {
163                 continue;
164             } else {
165                 ret = -1;
166                 break;
167             }
168         } else if (ret == 0) {
169             ret = -1;
170             break;
171         } else {
172             if (ch == '\r') {
173                 ret = 0;
174                 break;
175             }
176             if (i < (buf_size - 1))
177                 buf[i++] = ch;
178         }
179     }
180     term_exit();
181     buf[i] = '\0';
182     printf("\n");
183     return ret;
184 }
185 #endif
186
187 static BlockDriverState *bdrv_new_open(const char *filename,
188                                        const char *fmt)
189 {
190     BlockDriverState *bs;
191     BlockDriver *drv;
192     char password[256];
193
194     bs = bdrv_new("");
195     if (!bs)
196         error("Not enough memory");
197     if (fmt) {
198         drv = bdrv_find_format(fmt);
199         if (!drv)
200             error("Unknown file format '%s'", fmt);
201     } else {
202         drv = NULL;
203     }
204     if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
205         error("Could not open '%s'", filename);
206     }
207     if (bdrv_is_encrypted(bs)) {
208         printf("Disk image '%s' is encrypted.\n", filename);
209         if (read_password(password, sizeof(password)) < 0)
210             error("No password given");
211         if (bdrv_set_key(bs, password) < 0)
212             error("invalid password");
213     }
214     return bs;
215 }
216
217 static int img_create(int argc, char **argv)
218 {
219     int c, ret, flags;
220     const char *fmt = "raw";
221     const char *base_fmt = NULL;
222     const char *filename;
223     const char *base_filename = NULL;
224     uint64_t size;
225     double sizef;
226     const char *p;
227     BlockDriver *drv;
228
229     flags = 0;
230     for(;;) {
231         c = getopt(argc, argv, "F:b:f:he6");
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         }
254     }
255     if (optind >= argc)
256         help();
257     filename = argv[optind++];
258     size = 0;
259     if (base_filename) {
260         BlockDriverState *bs;
261         BlockDriver *base_drv = NULL;
262
263         if (base_fmt) {
264             base_drv = bdrv_find_format(base_fmt);
265             if (base_drv == NULL)
266                 error("Unknown basefile format '%s'", base_fmt);
267         }
268
269         bs = bdrv_new_open(base_filename, base_fmt);
270         bdrv_get_geometry(bs, &size);
271         size *= 512;
272         bdrv_delete(bs);
273     } else {
274         if (optind >= argc)
275             help();
276         p = argv[optind];
277         sizef = strtod(p, (char **)&p);
278         if (*p == 'M') {
279             size = (uint64_t)(sizef * 1024 * 1024);
280         } else if (*p == 'G') {
281             size = (uint64_t)(sizef * 1024 * 1024 * 1024);
282         } else if (*p == 'k' || *p == 'K' || *p == '\0') {
283             size = (uint64_t)(sizef * 1024);
284         } else {
285             help();
286         }
287     }
288     drv = bdrv_find_format(fmt);
289     if (!drv)
290         error("Unknown file format '%s'", fmt);
291     printf("Formatting '%s', fmt=%s",
292            filename, fmt);
293     if (flags & BLOCK_FLAG_ENCRYPT)
294         printf(", encrypted");
295     if (flags & BLOCK_FLAG_COMPAT6)
296         printf(", compatibility level=6");
297     if (base_filename) {
298         printf(", backing_file=%s",
299                base_filename);
300          if (base_fmt)
301              printf(", backing_fmt=%s",
302                     base_fmt);
303     }
304     printf(", size=%" PRIu64 " kB\n", size / 1024);
305     ret = bdrv_create2(drv, filename, size / 512, base_filename, base_fmt, flags);
306     if (ret < 0) {
307         if (ret == -ENOTSUP) {
308             error("Formatting or formatting option not supported for file format '%s'", fmt);
309         } else if (ret == -EFBIG) {
310             error("The image size is too large for file format '%s'", fmt);
311         } else {
312             error("Error while formatting");
313         }
314     }
315     return 0;
316 }
317
318 static int img_commit(int argc, char **argv)
319 {
320     int c, ret;
321     const char *filename, *fmt;
322     BlockDriver *drv;
323     BlockDriverState *bs;
324
325     fmt = NULL;
326     for(;;) {
327         c = getopt(argc, argv, "f:h");
328         if (c == -1)
329             break;
330         switch(c) {
331         case 'h':
332             help();
333             break;
334         case 'f':
335             fmt = optarg;
336             break;
337         }
338     }
339     if (optind >= argc)
340         help();
341     filename = argv[optind++];
342
343     bs = bdrv_new("");
344     if (!bs)
345         error("Not enough memory");
346     if (fmt) {
347         drv = bdrv_find_format(fmt);
348         if (!drv)
349             error("Unknown file format '%s'", fmt);
350     } else {
351         drv = NULL;
352     }
353     if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
354         error("Could not open '%s'", filename);
355     }
356     ret = bdrv_commit(bs);
357     switch(ret) {
358     case 0:
359         printf("Image committed.\n");
360         break;
361     case -ENOENT:
362         error("No disk inserted");
363         break;
364     case -EACCES:
365         error("Image is read-only");
366         break;
367     case -ENOTSUP:
368         error("Image is already committed");
369         break;
370     default:
371         error("Error while committing image");
372         break;
373     }
374
375     bdrv_delete(bs);
376     return 0;
377 }
378
379 static int is_not_zero(const uint8_t *sector, int len)
380 {
381     int i;
382     len >>= 2;
383     for(i = 0;i < len; i++) {
384         if (((uint32_t *)sector)[i] != 0)
385             return 1;
386     }
387     return 0;
388 }
389
390 /*
391  * Returns true iff the first sector pointed to by 'buf' contains at least
392  * a non-NUL byte.
393  *
394  * 'pnum' is set to the number of sectors (including and immediately following
395  * the first one) that are known to be in the same allocated/unallocated state.
396  */
397 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
398 {
399     int v, i;
400
401     if (n <= 0) {
402         *pnum = 0;
403         return 0;
404     }
405     v = is_not_zero(buf, 512);
406     for(i = 1; i < n; i++) {
407         buf += 512;
408         if (v != is_not_zero(buf, 512))
409             break;
410     }
411     *pnum = i;
412     return v;
413 }
414
415 #define IO_BUF_SIZE 65536
416
417 static int img_convert(int argc, char **argv)
418 {
419     int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
420     const char *fmt, *out_fmt, *out_baseimg, *out_filename;
421     BlockDriver *drv;
422     BlockDriverState **bs, *out_bs;
423     int64_t total_sectors, nb_sectors, sector_num, bs_offset;
424     uint64_t bs_sectors;
425     uint8_t buf[IO_BUF_SIZE];
426     const uint8_t *buf1;
427     BlockDriverInfo bdi;
428
429     fmt = NULL;
430     out_fmt = "raw";
431     out_baseimg = NULL;
432     flags = 0;
433     for(;;) {
434         c = getopt(argc, argv, "f:O:B:hce6");
435         if (c == -1)
436             break;
437         switch(c) {
438         case 'h':
439             help();
440             break;
441         case 'f':
442             fmt = optarg;
443             break;
444         case 'O':
445             out_fmt = optarg;
446             break;
447         case 'B':
448             out_baseimg = optarg;
449             break;
450         case 'c':
451             flags |= BLOCK_FLAG_COMPRESS;
452             break;
453         case 'e':
454             flags |= BLOCK_FLAG_ENCRYPT;
455             break;
456         case '6':
457             flags |= BLOCK_FLAG_COMPAT6;
458             break;
459         }
460     }
461
462     bs_n = argc - optind - 1;
463     if (bs_n < 1) help();
464
465     out_filename = argv[argc - 1];
466
467     if (bs_n > 1 && out_baseimg)
468         error("-B makes no sense when concatenating multiple input images");
469         
470     bs = calloc(bs_n, sizeof(BlockDriverState *));
471     if (!bs)
472         error("Out of memory");
473
474     total_sectors = 0;
475     for (bs_i = 0; bs_i < bs_n; bs_i++) {
476         bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
477         if (!bs[bs_i])
478             error("Could not open '%s'", argv[optind + bs_i]);
479         bdrv_get_geometry(bs[bs_i], &bs_sectors);
480         total_sectors += bs_sectors;
481     }
482
483     drv = bdrv_find_format(out_fmt);
484     if (!drv)
485         error("Unknown file format '%s'", out_fmt);
486     if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2)
487         error("Compression not supported for this file format");
488     if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
489         error("Encryption not supported for this file format");
490     if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
491         error("Alternative compatibility level not supported for this file format");
492     if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
493         error("Compression and encryption not supported at the same time");
494
495     ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
496     if (ret < 0) {
497         if (ret == -ENOTSUP) {
498             error("Formatting not supported for file format '%s'", out_fmt);
499         } else if (ret == -EFBIG) {
500             error("The image size is too large for file format '%s'", out_fmt);
501         } else {
502             error("Error while formatting '%s'", out_filename);
503         }
504     }
505
506     out_bs = bdrv_new_open(out_filename, out_fmt);
507
508     bs_i = 0;
509     bs_offset = 0;
510     bdrv_get_geometry(bs[0], &bs_sectors);
511
512     if (flags & BLOCK_FLAG_COMPRESS) {
513         if (bdrv_get_info(out_bs, &bdi) < 0)
514             error("could not get block driver info");
515         cluster_size = bdi.cluster_size;
516         if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
517             error("invalid cluster size");
518         cluster_sectors = cluster_size >> 9;
519         sector_num = 0;
520         for(;;) {
521             int64_t bs_num;
522             int remainder;
523             uint8_t *buf2;
524
525             nb_sectors = total_sectors - sector_num;
526             if (nb_sectors <= 0)
527                 break;
528             if (nb_sectors >= cluster_sectors)
529                 n = cluster_sectors;
530             else
531                 n = nb_sectors;
532
533             bs_num = sector_num - bs_offset;
534             assert (bs_num >= 0);
535             remainder = n;
536             buf2 = buf;
537             while (remainder > 0) {
538                 int nlow;
539                 while (bs_num == bs_sectors) {
540                     bs_i++;
541                     assert (bs_i < bs_n);
542                     bs_offset += bs_sectors;
543                     bdrv_get_geometry(bs[bs_i], &bs_sectors);
544                     bs_num = 0;
545                     /* printf("changing part: sector_num=%lld, "
546                        "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
547                        sector_num, bs_i, bs_offset, bs_sectors); */
548                 }
549                 assert (bs_num < bs_sectors);
550
551                 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
552
553                 if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) 
554                     error("error while reading");
555
556                 buf2 += nlow * 512;
557                 bs_num += nlow;
558
559                 remainder -= nlow;
560             }
561             assert (remainder == 0);
562
563             if (n < cluster_sectors)
564                 memset(buf + n * 512, 0, cluster_size - n * 512);
565             if (is_not_zero(buf, cluster_size)) {
566                 if (bdrv_write_compressed(out_bs, sector_num, buf,
567                                           cluster_sectors) != 0)
568                     error("error while compressing sector %" PRId64,
569                           sector_num);
570             }
571             sector_num += n;
572         }
573         /* signal EOF to align */
574         bdrv_write_compressed(out_bs, 0, NULL, 0);
575     } else {
576         sector_num = 0; // total number of sectors converted so far
577         for(;;) {
578             nb_sectors = total_sectors - sector_num;
579             if (nb_sectors <= 0)
580                 break;
581             if (nb_sectors >= (IO_BUF_SIZE / 512))
582                 n = (IO_BUF_SIZE / 512);
583             else
584                 n = nb_sectors;
585
586             while (sector_num - bs_offset >= bs_sectors) {
587                 bs_i ++;
588                 assert (bs_i < bs_n);
589                 bs_offset += bs_sectors;
590                 bdrv_get_geometry(bs[bs_i], &bs_sectors);
591                 /* printf("changing part: sector_num=%lld, bs_i=%d, "
592                   "bs_offset=%lld, bs_sectors=%lld\n",
593                    sector_num, bs_i, bs_offset, bs_sectors); */
594             }
595
596             if (n > bs_offset + bs_sectors - sector_num)
597                 n = bs_offset + bs_sectors - sector_num;
598
599             if (drv != &bdrv_host_device) {
600                 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
601                                        n, &n1)) {
602                     sector_num += n1;
603                     continue;
604                 }
605                 /* The next 'n1' sectors are allocated in the input image. Copy
606                    only those as they may be followed by unallocated sectors. */
607                 n = n1;
608             } else {
609                 n1 = n;
610             }
611
612             if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) 
613                 error("error while reading");
614             /* NOTE: at the same time we convert, we do not write zero
615                sectors to have a chance to compress the image. Ideally, we
616                should add a specific call to have the info to go faster */
617             buf1 = buf;
618             while (n > 0) {
619                 /* If the output image is being created as a copy on write image,
620                    copy all sectors even the ones containing only NUL bytes,
621                    because they may differ from the sectors in the base image.
622
623                    If the output is to a host device, we also write out
624                    sectors that are entirely 0, since whatever data was
625                    already there is garbage, not 0s. */
626                 if (drv == &bdrv_host_device || out_baseimg ||
627                     is_allocated_sectors(buf1, n, &n1)) {
628                     if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
629                         error("error while writing");
630                 }
631                 sector_num += n1;
632                 n -= n1;
633                 buf1 += n1 * 512;
634             }
635         }
636     }
637     bdrv_delete(out_bs);
638     for (bs_i = 0; bs_i < bs_n; bs_i++)
639         bdrv_delete(bs[bs_i]);
640     free(bs);
641     return 0;
642 }
643
644 #ifdef _WIN32
645 static int64_t get_allocated_file_size(const char *filename)
646 {
647     typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
648     get_compressed_t get_compressed;
649     struct _stati64 st;
650
651     /* WinNT support GetCompressedFileSize to determine allocate size */
652     get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
653     if (get_compressed) {
654         DWORD high, low;
655         low = get_compressed(filename, &high);
656         if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
657             return (((int64_t) high) << 32) + low;
658     }
659
660     if (_stati64(filename, &st) < 0)
661         return -1;
662     return st.st_size;
663 }
664 #else
665 static int64_t get_allocated_file_size(const char *filename)
666 {
667     struct stat st;
668     if (stat(filename, &st) < 0)
669         return -1;
670     return (int64_t)st.st_blocks * 512;
671 }
672 #endif
673
674 static void dump_snapshots(BlockDriverState *bs)
675 {
676     QEMUSnapshotInfo *sn_tab, *sn;
677     int nb_sns, i;
678     char buf[256];
679
680     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
681     if (nb_sns <= 0)
682         return;
683     printf("Snapshot list:\n");
684     printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
685     for(i = 0; i < nb_sns; i++) {
686         sn = &sn_tab[i];
687         printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
688     }
689     qemu_free(sn_tab);
690 }
691
692 static int img_info(int argc, char **argv)
693 {
694     int c;
695     const char *filename, *fmt;
696     BlockDriver *drv;
697     BlockDriverState *bs;
698     char fmt_name[128], size_buf[128], dsize_buf[128];
699     uint64_t total_sectors;
700     int64_t allocated_size;
701     char backing_filename[1024];
702     char backing_filename2[1024];
703     BlockDriverInfo bdi;
704
705     fmt = NULL;
706     for(;;) {
707         c = getopt(argc, argv, "f:h");
708         if (c == -1)
709             break;
710         switch(c) {
711         case 'h':
712             help();
713             break;
714         case 'f':
715             fmt = optarg;
716             break;
717         }
718     }
719     if (optind >= argc)
720         help();
721     filename = argv[optind++];
722
723     bs = bdrv_new("");
724     if (!bs)
725         error("Not enough memory");
726     if (fmt) {
727         drv = bdrv_find_format(fmt);
728         if (!drv)
729             error("Unknown file format '%s'", fmt);
730     } else {
731         drv = NULL;
732     }
733     if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
734         error("Could not open '%s'", filename);
735     }
736     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
737     bdrv_get_geometry(bs, &total_sectors);
738     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
739     allocated_size = get_allocated_file_size(filename);
740     if (allocated_size < 0)
741         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
742     else
743         get_human_readable_size(dsize_buf, sizeof(dsize_buf),
744                                 allocated_size);
745     printf("image: %s\n"
746            "file format: %s\n"
747            "virtual size: %s (%" PRId64 " bytes)\n"
748            "disk size: %s\n",
749            filename, fmt_name, size_buf,
750            (total_sectors * 512),
751            dsize_buf);
752     if (bdrv_is_encrypted(bs))
753         printf("encrypted: yes\n");
754     if (bdrv_get_info(bs, &bdi) >= 0) {
755         if (bdi.cluster_size != 0)
756             printf("cluster_size: %d\n", bdi.cluster_size);
757     }
758     bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
759     if (backing_filename[0] != '\0') {
760         path_combine(backing_filename2, sizeof(backing_filename2),
761                      filename, backing_filename);
762         printf("backing file: %s (actual path: %s)\n",
763                backing_filename,
764                backing_filename2);
765     }
766     dump_snapshots(bs);
767     bdrv_delete(bs);
768     return 0;
769 }
770
771 #define SNAPSHOT_LIST   1
772 #define SNAPSHOT_CREATE 2
773 #define SNAPSHOT_APPLY  3
774 #define SNAPSHOT_DELETE 4
775
776 static void img_snapshot(int argc, char **argv)
777 {
778     BlockDriverState *bs;
779     QEMUSnapshotInfo sn;
780     char *filename, *snapshot_name = NULL;
781     int c, ret;
782     int action = 0;
783     qemu_timeval tv;
784
785     /* Parse commandline parameters */
786     for(;;) {
787         c = getopt(argc, argv, "la:c:d:h");
788         if (c == -1)
789             break;
790         switch(c) {
791         case 'h':
792             help();
793             return;
794         case 'l':
795             if (action) {
796                 help();
797                 return;
798             }
799             action = SNAPSHOT_LIST;
800             break;
801         case 'a':
802             if (action) {
803                 help();
804                 return;
805             }
806             action = SNAPSHOT_APPLY;
807             snapshot_name = optarg;
808             break;
809         case 'c':
810             if (action) {
811                 help();
812                 return;
813             }
814             action = SNAPSHOT_CREATE;
815             snapshot_name = optarg;
816             break;
817         case 'd':
818             if (action) {
819                 help();
820                 return;
821             }
822             action = SNAPSHOT_DELETE;
823             snapshot_name = optarg;
824             break;
825         }
826     }
827
828     if (optind >= argc)
829         help();
830     filename = argv[optind++];
831
832     /* Open the image */
833     bs = bdrv_new("");
834     if (!bs)
835         error("Not enough memory");
836
837     if (bdrv_open2(bs, filename, 0, NULL) < 0) {
838         error("Could not open '%s'", filename);
839     }
840
841     /* Perform the requested action */
842     switch(action) {
843     case SNAPSHOT_LIST:
844         dump_snapshots(bs);
845         break;
846
847     case SNAPSHOT_CREATE:
848         memset(&sn, 0, sizeof(sn));
849         pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
850
851         qemu_gettimeofday(&tv);
852         sn.date_sec = tv.tv_sec;
853         sn.date_nsec = tv.tv_usec * 1000;
854
855         ret = bdrv_snapshot_create(bs, &sn);
856         if (ret)
857             error("Could not create snapshot '%s': %d (%s)",
858                 snapshot_name, ret, strerror(-ret));
859         break;
860
861     case SNAPSHOT_APPLY:
862         ret = bdrv_snapshot_goto(bs, snapshot_name);
863         if (ret)
864             error("Could not apply snapshot '%s': %d (%s)",
865                 snapshot_name, ret, strerror(-ret));
866         break;
867
868     case SNAPSHOT_DELETE:
869         ret = bdrv_snapshot_delete(bs, snapshot_name);
870         if (ret)
871             error("Could not delete snapshot '%s': %d (%s)",
872                 snapshot_name, ret, strerror(-ret));
873         break;
874     }
875
876     /* Cleanup */
877     bdrv_delete(bs);
878 }
879
880 int main(int argc, char **argv)
881 {
882     const char *cmd;
883
884     bdrv_init();
885     if (argc < 2)
886         help();
887     cmd = argv[1];
888     argc--; argv++;
889     if (!strcmp(cmd, "create")) {
890         img_create(argc, argv);
891     } else if (!strcmp(cmd, "commit")) {
892         img_commit(argc, argv);
893     } else if (!strcmp(cmd, "convert")) {
894         img_convert(argc, argv);
895     } else if (!strcmp(cmd, "info")) {
896         img_info(argc, argv);
897     } else if (!strcmp(cmd, "snapshot")) {
898         img_snapshot(argc, argv);
899     } else {
900         help();
901     }
902     return 0;
903 }