Remove unused variable
[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 {
310             error("Error while formatting");
311         }
312     }
313     return 0;
314 }
315
316 static int img_commit(int argc, char **argv)
317 {
318     int c, ret;
319     const char *filename, *fmt;
320     BlockDriver *drv;
321     BlockDriverState *bs;
322
323     fmt = NULL;
324     for(;;) {
325         c = getopt(argc, argv, "f:h");
326         if (c == -1)
327             break;
328         switch(c) {
329         case 'h':
330             help();
331             break;
332         case 'f':
333             fmt = optarg;
334             break;
335         }
336     }
337     if (optind >= argc)
338         help();
339     filename = argv[optind++];
340
341     bs = bdrv_new("");
342     if (!bs)
343         error("Not enough memory");
344     if (fmt) {
345         drv = bdrv_find_format(fmt);
346         if (!drv)
347             error("Unknown file format '%s'", fmt);
348     } else {
349         drv = NULL;
350     }
351     if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
352         error("Could not open '%s'", filename);
353     }
354     ret = bdrv_commit(bs);
355     switch(ret) {
356     case 0:
357         printf("Image committed.\n");
358         break;
359     case -ENOENT:
360         error("No disk inserted");
361         break;
362     case -EACCES:
363         error("Image is read-only");
364         break;
365     case -ENOTSUP:
366         error("Image is already committed");
367         break;
368     default:
369         error("Error while committing image");
370         break;
371     }
372
373     bdrv_delete(bs);
374     return 0;
375 }
376
377 static int is_not_zero(const uint8_t *sector, int len)
378 {
379     int i;
380     len >>= 2;
381     for(i = 0;i < len; i++) {
382         if (((uint32_t *)sector)[i] != 0)
383             return 1;
384     }
385     return 0;
386 }
387
388 /*
389  * Returns true iff the first sector pointed to by 'buf' contains at least
390  * a non-NUL byte.
391  *
392  * 'pnum' is set to the number of sectors (including and immediately following
393  * the first one) that are known to be in the same allocated/unallocated state.
394  */
395 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
396 {
397     int v, i;
398
399     if (n <= 0) {
400         *pnum = 0;
401         return 0;
402     }
403     v = is_not_zero(buf, 512);
404     for(i = 1; i < n; i++) {
405         buf += 512;
406         if (v != is_not_zero(buf, 512))
407             break;
408     }
409     *pnum = i;
410     return v;
411 }
412
413 #define IO_BUF_SIZE 65536
414
415 static int img_convert(int argc, char **argv)
416 {
417     int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
418     const char *fmt, *out_fmt, *out_baseimg, *out_filename;
419     BlockDriver *drv;
420     BlockDriverState **bs, *out_bs;
421     int64_t total_sectors, nb_sectors, sector_num, bs_offset;
422     uint64_t bs_sectors;
423     uint8_t buf[IO_BUF_SIZE];
424     const uint8_t *buf1;
425     BlockDriverInfo bdi;
426
427     fmt = NULL;
428     out_fmt = "raw";
429     out_baseimg = NULL;
430     flags = 0;
431     for(;;) {
432         c = getopt(argc, argv, "f:O:B:hce6");
433         if (c == -1)
434             break;
435         switch(c) {
436         case 'h':
437             help();
438             break;
439         case 'f':
440             fmt = optarg;
441             break;
442         case 'O':
443             out_fmt = optarg;
444             break;
445         case 'B':
446             out_baseimg = optarg;
447             break;
448         case 'c':
449             flags |= BLOCK_FLAG_COMPRESS;
450             break;
451         case 'e':
452             flags |= BLOCK_FLAG_ENCRYPT;
453             break;
454         case '6':
455             flags |= BLOCK_FLAG_COMPAT6;
456             break;
457         }
458     }
459
460     bs_n = argc - optind - 1;
461     if (bs_n < 1) help();
462
463     out_filename = argv[argc - 1];
464
465     if (bs_n > 1 && out_baseimg)
466         error("-B makes no sense when concatenating multiple input images");
467         
468     bs = calloc(bs_n, sizeof(BlockDriverState *));
469     if (!bs)
470         error("Out of memory");
471
472     total_sectors = 0;
473     for (bs_i = 0; bs_i < bs_n; bs_i++) {
474         bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
475         if (!bs[bs_i])
476             error("Could not open '%s'", argv[optind + bs_i]);
477         bdrv_get_geometry(bs[bs_i], &bs_sectors);
478         total_sectors += bs_sectors;
479     }
480
481     drv = bdrv_find_format(out_fmt);
482     if (!drv)
483         error("Unknown file format '%s'", out_fmt);
484     if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2)
485         error("Compression not supported for this file format");
486     if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
487         error("Encryption not supported for this file format");
488     if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
489         error("Alternative compatibility level not supported for this file format");
490     if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
491         error("Compression and encryption not supported at the same time");
492
493     ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
494     if (ret < 0) {
495         if (ret == -ENOTSUP) {
496             error("Formatting not supported for file format '%s'", fmt);
497         } else {
498             error("Error while formatting '%s'", out_filename);
499         }
500     }
501
502     out_bs = bdrv_new_open(out_filename, out_fmt);
503
504     bs_i = 0;
505     bs_offset = 0;
506     bdrv_get_geometry(bs[0], &bs_sectors);
507
508     if (flags & BLOCK_FLAG_COMPRESS) {
509         if (bdrv_get_info(out_bs, &bdi) < 0)
510             error("could not get block driver info");
511         cluster_size = bdi.cluster_size;
512         if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
513             error("invalid cluster size");
514         cluster_sectors = cluster_size >> 9;
515         sector_num = 0;
516         for(;;) {
517             int64_t bs_num;
518             int remainder;
519             uint8_t *buf2;
520
521             nb_sectors = total_sectors - sector_num;
522             if (nb_sectors <= 0)
523                 break;
524             if (nb_sectors >= cluster_sectors)
525                 n = cluster_sectors;
526             else
527                 n = nb_sectors;
528
529             bs_num = sector_num - bs_offset;
530             assert (bs_num >= 0);
531             remainder = n;
532             buf2 = buf;
533             while (remainder > 0) {
534                 int nlow;
535                 while (bs_num == bs_sectors) {
536                     bs_i++;
537                     assert (bs_i < bs_n);
538                     bs_offset += bs_sectors;
539                     bdrv_get_geometry(bs[bs_i], &bs_sectors);
540                     bs_num = 0;
541                     /* printf("changing part: sector_num=%lld, "
542                        "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
543                        sector_num, bs_i, bs_offset, bs_sectors); */
544                 }
545                 assert (bs_num < bs_sectors);
546
547                 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
548
549                 if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) 
550                     error("error while reading");
551
552                 buf2 += nlow * 512;
553                 bs_num += nlow;
554
555                 remainder -= nlow;
556             }
557             assert (remainder == 0);
558
559             if (n < cluster_sectors)
560                 memset(buf + n * 512, 0, cluster_size - n * 512);
561             if (is_not_zero(buf, cluster_size)) {
562                 if (bdrv_write_compressed(out_bs, sector_num, buf,
563                                           cluster_sectors) != 0)
564                     error("error while compressing sector %" PRId64,
565                           sector_num);
566             }
567             sector_num += n;
568         }
569         /* signal EOF to align */
570         bdrv_write_compressed(out_bs, 0, NULL, 0);
571     } else {
572         sector_num = 0; // total number of sectors converted so far
573         for(;;) {
574             nb_sectors = total_sectors - sector_num;
575             if (nb_sectors <= 0)
576                 break;
577             if (nb_sectors >= (IO_BUF_SIZE / 512))
578                 n = (IO_BUF_SIZE / 512);
579             else
580                 n = nb_sectors;
581
582             while (sector_num - bs_offset >= bs_sectors) {
583                 bs_i ++;
584                 assert (bs_i < bs_n);
585                 bs_offset += bs_sectors;
586                 bdrv_get_geometry(bs[bs_i], &bs_sectors);
587                 /* printf("changing part: sector_num=%lld, bs_i=%d, "
588                   "bs_offset=%lld, bs_sectors=%lld\n",
589                    sector_num, bs_i, bs_offset, bs_sectors); */
590             }
591
592             if (n > bs_offset + bs_sectors - sector_num)
593                 n = bs_offset + bs_sectors - sector_num;
594
595             /* If the output image is being created as a copy on write image,
596                assume that sectors which are unallocated in the input image
597                are present in both the output's and input's base images (no
598                need to copy them). */
599             if (out_baseimg) {
600                if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset, n, &n1)) {
601                   sector_num += n1;
602                   continue;
603                }
604                /* The next 'n1' sectors are allocated in the input image. Copy
605                   only those as they may be followed by unallocated sectors. */
606                n = n1;
607             }
608
609             if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) 
610                 error("error while reading");
611             /* NOTE: at the same time we convert, we do not write zero
612                sectors to have a chance to compress the image. Ideally, we
613                should add a specific call to have the info to go faster */
614             buf1 = buf;
615             while (n > 0) {
616                 /* If the output image is being created as a copy on write image,
617                    copy all sectors even the ones containing only NUL bytes,
618                    because they may differ from the sectors in the base image. */
619                 if (out_baseimg || is_allocated_sectors(buf1, n, &n1)) {
620                     if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
621                         error("error while writing");
622                 }
623                 sector_num += n1;
624                 n -= n1;
625                 buf1 += n1 * 512;
626             }
627         }
628     }
629     bdrv_delete(out_bs);
630     for (bs_i = 0; bs_i < bs_n; bs_i++)
631         bdrv_delete(bs[bs_i]);
632     free(bs);
633     return 0;
634 }
635
636 #ifdef _WIN32
637 static int64_t get_allocated_file_size(const char *filename)
638 {
639     typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
640     get_compressed_t get_compressed;
641     struct _stati64 st;
642
643     /* WinNT support GetCompressedFileSize to determine allocate size */
644     get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
645     if (get_compressed) {
646         DWORD high, low;
647         low = get_compressed(filename, &high);
648         if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
649             return (((int64_t) high) << 32) + low;
650     }
651
652     if (_stati64(filename, &st) < 0)
653         return -1;
654     return st.st_size;
655 }
656 #else
657 static int64_t get_allocated_file_size(const char *filename)
658 {
659     struct stat st;
660     if (stat(filename, &st) < 0)
661         return -1;
662     return (int64_t)st.st_blocks * 512;
663 }
664 #endif
665
666 static void dump_snapshots(BlockDriverState *bs)
667 {
668     QEMUSnapshotInfo *sn_tab, *sn;
669     int nb_sns, i;
670     char buf[256];
671
672     nb_sns = bdrv_snapshot_list(bs, &sn_tab);
673     if (nb_sns <= 0)
674         return;
675     printf("Snapshot list:\n");
676     printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
677     for(i = 0; i < nb_sns; i++) {
678         sn = &sn_tab[i];
679         printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
680     }
681     qemu_free(sn_tab);
682 }
683
684 static int img_info(int argc, char **argv)
685 {
686     int c;
687     const char *filename, *fmt;
688     BlockDriver *drv;
689     BlockDriverState *bs;
690     char fmt_name[128], size_buf[128], dsize_buf[128];
691     uint64_t total_sectors;
692     int64_t allocated_size;
693     char backing_filename[1024];
694     char backing_filename2[1024];
695     BlockDriverInfo bdi;
696
697     fmt = NULL;
698     for(;;) {
699         c = getopt(argc, argv, "f:h");
700         if (c == -1)
701             break;
702         switch(c) {
703         case 'h':
704             help();
705             break;
706         case 'f':
707             fmt = optarg;
708             break;
709         }
710     }
711     if (optind >= argc)
712         help();
713     filename = argv[optind++];
714
715     bs = bdrv_new("");
716     if (!bs)
717         error("Not enough memory");
718     if (fmt) {
719         drv = bdrv_find_format(fmt);
720         if (!drv)
721             error("Unknown file format '%s'", fmt);
722     } else {
723         drv = NULL;
724     }
725     if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
726         error("Could not open '%s'", filename);
727     }
728     bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
729     bdrv_get_geometry(bs, &total_sectors);
730     get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
731     allocated_size = get_allocated_file_size(filename);
732     if (allocated_size < 0)
733         snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
734     else
735         get_human_readable_size(dsize_buf, sizeof(dsize_buf),
736                                 allocated_size);
737     printf("image: %s\n"
738            "file format: %s\n"
739            "virtual size: %s (%" PRId64 " bytes)\n"
740            "disk size: %s\n",
741            filename, fmt_name, size_buf,
742            (total_sectors * 512),
743            dsize_buf);
744     if (bdrv_is_encrypted(bs))
745         printf("encrypted: yes\n");
746     if (bdrv_get_info(bs, &bdi) >= 0) {
747         if (bdi.cluster_size != 0)
748             printf("cluster_size: %d\n", bdi.cluster_size);
749     }
750     bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
751     if (backing_filename[0] != '\0') {
752         path_combine(backing_filename2, sizeof(backing_filename2),
753                      filename, backing_filename);
754         printf("backing file: %s (actual path: %s)\n",
755                backing_filename,
756                backing_filename2);
757     }
758     dump_snapshots(bs);
759     bdrv_delete(bs);
760     return 0;
761 }
762
763 #define SNAPSHOT_LIST   1
764 #define SNAPSHOT_CREATE 2
765 #define SNAPSHOT_APPLY  3
766 #define SNAPSHOT_DELETE 4
767
768 static void img_snapshot(int argc, char **argv)
769 {
770     BlockDriverState *bs;
771     QEMUSnapshotInfo sn;
772     char *filename, *snapshot_name = NULL;
773     int c, ret;
774     int action = 0;
775     qemu_timeval tv;
776
777     /* Parse commandline parameters */
778     for(;;) {
779         c = getopt(argc, argv, "la:c:d:h");
780         if (c == -1)
781             break;
782         switch(c) {
783         case 'h':
784             help();
785             return;
786         case 'l':
787             if (action) {
788                 help();
789                 return;
790             }
791             action = SNAPSHOT_LIST;
792             break;
793         case 'a':
794             if (action) {
795                 help();
796                 return;
797             }
798             action = SNAPSHOT_APPLY;
799             snapshot_name = optarg;
800             break;
801         case 'c':
802             if (action) {
803                 help();
804                 return;
805             }
806             action = SNAPSHOT_CREATE;
807             snapshot_name = optarg;
808             break;
809         case 'd':
810             if (action) {
811                 help();
812                 return;
813             }
814             action = SNAPSHOT_DELETE;
815             snapshot_name = optarg;
816             break;
817         }
818     }
819
820     if (optind >= argc)
821         help();
822     filename = argv[optind++];
823
824     /* Open the image */
825     bs = bdrv_new("");
826     if (!bs)
827         error("Not enough memory");
828
829     if (bdrv_open2(bs, filename, 0, NULL) < 0) {
830         error("Could not open '%s'", filename);
831     }
832
833     /* Perform the requested action */
834     switch(action) {
835     case SNAPSHOT_LIST:
836         dump_snapshots(bs);
837         break;
838
839     case SNAPSHOT_CREATE:
840         memset(&sn, 0, sizeof(sn));
841         pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
842
843         qemu_gettimeofday(&tv);
844         sn.date_sec = tv.tv_sec;
845         sn.date_nsec = tv.tv_usec * 1000;
846
847         ret = bdrv_snapshot_create(bs, &sn);
848         if (ret)
849             error("Could not create snapshot '%s': %d (%s)",
850                 snapshot_name, ret, strerror(-ret));
851         break;
852
853     case SNAPSHOT_APPLY:
854         ret = bdrv_snapshot_goto(bs, snapshot_name);
855         if (ret)
856             error("Could not apply snapshot '%s': %d (%s)",
857                 snapshot_name, ret, strerror(-ret));
858         break;
859
860     case SNAPSHOT_DELETE:
861         ret = bdrv_snapshot_delete(bs, snapshot_name);
862         if (ret)
863             error("Could not delete snapshot '%s': %d (%s)",
864                 snapshot_name, ret, strerror(-ret));
865         break;
866     }
867
868     /* Cleanup */
869     bdrv_delete(bs);
870 }
871
872 int main(int argc, char **argv)
873 {
874     const char *cmd;
875
876     bdrv_init();
877     if (argc < 2)
878         help();
879     cmd = argv[1];
880     argc--; argv++;
881     if (!strcmp(cmd, "create")) {
882         img_create(argc, argv);
883     } else if (!strcmp(cmd, "commit")) {
884         img_commit(argc, argv);
885     } else if (!strcmp(cmd, "convert")) {
886         img_convert(argc, argv);
887     } else if (!strcmp(cmd, "info")) {
888         img_info(argc, argv);
889     } else if (!strcmp(cmd, "snapshot")) {
890         img_snapshot(argc, argv);
891     } else {
892         help();
893     }
894     return 0;
895 }