ELF codedump build failures
[qemu/ar7.git] / qemu-img.c
blobd806cfa1934e347d8f1c20737d5578767e623f13
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 typedef struct img_cmd_t {
35 const char *name;
36 int (*handler)(int argc, char **argv);
37 } img_cmd_t;
39 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
40 #define BRDV_O_FLAGS BDRV_O_CACHE_WB
42 static void QEMU_NORETURN error(const char *fmt, ...)
44 va_list ap;
45 va_start(ap, fmt);
46 fprintf(stderr, "qemu-img: ");
47 vfprintf(stderr, fmt, ap);
48 fprintf(stderr, "\n");
49 exit(1);
50 va_end(ap);
53 static void format_print(void *opaque, const char *name)
55 printf(" %s", name);
58 /* Please keep in synch with qemu-img.texi */
59 static void help(void)
61 printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
62 "usage: qemu-img command [command options]\n"
63 "QEMU disk image utility\n"
64 "\n"
65 "Command syntax:\n"
66 #define DEF(option, callback, arg_string) \
67 " " arg_string "\n"
68 #include "qemu-img-cmds.h"
69 #undef DEF
70 #undef GEN_DOCS
71 "\n"
72 "Command parameters:\n"
73 " 'filename' is a disk image filename\n"
74 " 'base_image' is the read-only disk image which is used as base for a copy on\n"
75 " write image; the copy on write image only stores the modified data\n"
76 " 'output_base_image' forces the output image to be created as a copy on write\n"
77 " image of the specified base image; 'output_base_image' should have the same\n"
78 " content as the input's base image, however the path, image format, etc may\n"
79 " differ\n"
80 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
81 " 'size' is the disk image size in kilobytes. Optional suffixes\n"
82 " 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
83 " supported any 'k' or 'K' is ignored\n"
84 " 'output_filename' is the destination disk image filename\n"
85 " 'output_fmt' is the destination format\n"
86 " 'options' is a comma separated list of format specific options in a\n"
87 " name=value format. Use -o ? for an overview of the options supported by the\n"
88 " used format\n"
89 " '-c' indicates that target image must be compressed (qcow format only)\n"
90 " '-h' with or without a command shows this help and lists the supported formats\n"
91 "\n"
92 "Parameters to snapshot subcommand:\n"
93 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
94 " '-a' applies a snapshot (revert disk to saved state)\n"
95 " '-c' creates a snapshot\n"
96 " '-d' deletes a snapshot\n"
97 " '-l' lists all snapshots in the given image\n"
99 printf("\nSupported formats:");
100 bdrv_iterate_format(format_print, NULL);
101 printf("\n");
102 exit(1);
105 #if defined(WIN32)
106 /* XXX: put correct support for win32 */
107 static int read_password(char *buf, int buf_size)
109 int c, i;
110 printf("Password: ");
111 fflush(stdout);
112 i = 0;
113 for(;;) {
114 c = getchar();
115 if (c == '\n')
116 break;
117 if (i < (buf_size - 1))
118 buf[i++] = c;
120 buf[i] = '\0';
121 return 0;
124 #else
126 #include <termios.h>
128 static struct termios oldtty;
130 static void term_exit(void)
132 tcsetattr (0, TCSANOW, &oldtty);
135 static void term_init(void)
137 struct termios tty;
139 tcgetattr (0, &tty);
140 oldtty = tty;
142 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
143 |INLCR|IGNCR|ICRNL|IXON);
144 tty.c_oflag |= OPOST;
145 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
146 tty.c_cflag &= ~(CSIZE|PARENB);
147 tty.c_cflag |= CS8;
148 tty.c_cc[VMIN] = 1;
149 tty.c_cc[VTIME] = 0;
151 tcsetattr (0, TCSANOW, &tty);
153 atexit(term_exit);
156 static int read_password(char *buf, int buf_size)
158 uint8_t ch;
159 int i, ret;
161 printf("password: ");
162 fflush(stdout);
163 term_init();
164 i = 0;
165 for(;;) {
166 ret = read(0, &ch, 1);
167 if (ret == -1) {
168 if (errno == EAGAIN || errno == EINTR) {
169 continue;
170 } else {
171 ret = -1;
172 break;
174 } else if (ret == 0) {
175 ret = -1;
176 break;
177 } else {
178 if (ch == '\r') {
179 ret = 0;
180 break;
182 if (i < (buf_size - 1))
183 buf[i++] = ch;
186 term_exit();
187 buf[i] = '\0';
188 printf("\n");
189 return ret;
191 #endif
193 static BlockDriverState *bdrv_new_open(const char *filename,
194 const char *fmt)
196 BlockDriverState *bs;
197 BlockDriver *drv;
198 char password[256];
200 bs = bdrv_new("");
201 if (!bs)
202 error("Not enough memory");
203 if (fmt) {
204 drv = bdrv_find_format(fmt);
205 if (!drv)
206 error("Unknown file format '%s'", fmt);
207 } else {
208 drv = NULL;
210 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
211 error("Could not open '%s'", filename);
213 if (bdrv_is_encrypted(bs)) {
214 printf("Disk image '%s' is encrypted.\n", filename);
215 if (read_password(password, sizeof(password)) < 0)
216 error("No password given");
217 if (bdrv_set_key(bs, password) < 0)
218 error("invalid password");
220 return bs;
223 static void add_old_style_options(const char *fmt, QEMUOptionParameter *list,
224 int flags, const char *base_filename, const char *base_fmt)
226 if (flags & BLOCK_FLAG_ENCRYPT) {
227 if (set_option_parameter(list, BLOCK_OPT_ENCRYPT, "on")) {
228 error("Encryption not supported for file format '%s'", fmt);
231 if (flags & BLOCK_FLAG_COMPAT6) {
232 if (set_option_parameter(list, BLOCK_OPT_COMPAT6, "on")) {
233 error("VMDK version 6 not supported for file format '%s'", fmt);
237 if (base_filename) {
238 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
239 error("Backing file not supported for file format '%s'", fmt);
242 if (base_fmt) {
243 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
244 error("Backing file format not supported for file format '%s'", fmt);
249 static int img_create(int argc, char **argv)
251 int c, ret, flags;
252 const char *fmt = "raw";
253 const char *base_fmt = NULL;
254 const char *filename;
255 const char *base_filename = NULL;
256 BlockDriver *drv;
257 QEMUOptionParameter *param = NULL;
258 char *options = NULL;
260 flags = 0;
261 for(;;) {
262 c = getopt(argc, argv, "F:b:f:he6o:");
263 if (c == -1)
264 break;
265 switch(c) {
266 case 'h':
267 help();
268 break;
269 case 'F':
270 base_fmt = optarg;
271 break;
272 case 'b':
273 base_filename = optarg;
274 break;
275 case 'f':
276 fmt = optarg;
277 break;
278 case 'e':
279 flags |= BLOCK_FLAG_ENCRYPT;
280 break;
281 case '6':
282 flags |= BLOCK_FLAG_COMPAT6;
283 break;
284 case 'o':
285 options = optarg;
286 break;
290 /* Find driver and parse its options */
291 drv = bdrv_find_format(fmt);
292 if (!drv)
293 error("Unknown file format '%s'", fmt);
295 if (options && !strcmp(options, "?")) {
296 print_option_help(drv->create_options);
297 return 0;
300 if (options) {
301 param = parse_option_parameters(options, drv->create_options, param);
302 if (param == NULL) {
303 error("Invalid options for file format '%s'.", fmt);
305 } else {
306 param = parse_option_parameters("", drv->create_options, param);
309 /* Get the filename */
310 if (optind >= argc)
311 help();
312 filename = argv[optind++];
314 /* Add size to parameters */
315 if (optind < argc) {
316 set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
319 /* Add old-style options to parameters */
320 add_old_style_options(fmt, param, flags, base_filename, base_fmt);
322 // The size for the image must always be specified, with one exception:
323 // If we are using a backing file, we can obtain the size from there
324 if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == 0) {
326 QEMUOptionParameter *backing_file =
327 get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
328 QEMUOptionParameter *backing_fmt =
329 get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
331 if (backing_file && backing_file->value.s) {
332 BlockDriverState *bs;
333 uint64_t size;
334 const char *fmt = NULL;
335 char buf[32];
337 if (backing_fmt && backing_fmt->value.s) {
338 if (bdrv_find_format(backing_fmt->value.s)) {
339 fmt = backing_fmt->value.s;
340 } else {
341 error("Unknown backing file format '%s'",
342 backing_fmt->value.s);
346 bs = bdrv_new_open(backing_file->value.s, fmt);
347 bdrv_get_geometry(bs, &size);
348 size *= 512;
349 bdrv_delete(bs);
351 snprintf(buf, sizeof(buf), "%" PRId64, size);
352 set_option_parameter(param, BLOCK_OPT_SIZE, buf);
353 } else {
354 error("Image creation needs a size parameter");
358 printf("Formatting '%s', fmt=%s ", filename, fmt);
359 print_option_parameters(param);
360 puts("");
362 ret = bdrv_create(drv, filename, param);
363 free_option_parameters(param);
365 if (ret < 0) {
366 if (ret == -ENOTSUP) {
367 error("Formatting or formatting option not supported for file format '%s'", fmt);
368 } else if (ret == -EFBIG) {
369 error("The image size is too large for file format '%s'", fmt);
370 } else {
371 error("Error while formatting");
374 return 0;
377 static int img_check(int argc, char **argv)
379 int c, ret;
380 const char *filename, *fmt;
381 BlockDriver *drv;
382 BlockDriverState *bs;
384 fmt = NULL;
385 for(;;) {
386 c = getopt(argc, argv, "f:h");
387 if (c == -1)
388 break;
389 switch(c) {
390 case 'h':
391 help();
392 break;
393 case 'f':
394 fmt = optarg;
395 break;
398 if (optind >= argc)
399 help();
400 filename = argv[optind++];
402 bs = bdrv_new("");
403 if (!bs)
404 error("Not enough memory");
405 if (fmt) {
406 drv = bdrv_find_format(fmt);
407 if (!drv)
408 error("Unknown file format '%s'", fmt);
409 } else {
410 drv = NULL;
412 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
413 error("Could not open '%s'", filename);
415 ret = bdrv_check(bs);
416 switch(ret) {
417 case 0:
418 printf("No errors were found on the image.\n");
419 break;
420 case -ENOTSUP:
421 error("This image format does not support checks");
422 break;
423 default:
424 if (ret < 0) {
425 error("An error occurred during the check");
426 } else {
427 printf("%d errors were found on the image.\n", ret);
429 break;
432 bdrv_delete(bs);
433 return 0;
436 static int img_commit(int argc, char **argv)
438 int c, ret;
439 const char *filename, *fmt;
440 BlockDriver *drv;
441 BlockDriverState *bs;
443 fmt = NULL;
444 for(;;) {
445 c = getopt(argc, argv, "f:h");
446 if (c == -1)
447 break;
448 switch(c) {
449 case 'h':
450 help();
451 break;
452 case 'f':
453 fmt = optarg;
454 break;
457 if (optind >= argc)
458 help();
459 filename = argv[optind++];
461 bs = bdrv_new("");
462 if (!bs)
463 error("Not enough memory");
464 if (fmt) {
465 drv = bdrv_find_format(fmt);
466 if (!drv)
467 error("Unknown file format '%s'", fmt);
468 } else {
469 drv = NULL;
471 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
472 error("Could not open '%s'", filename);
474 ret = bdrv_commit(bs);
475 switch(ret) {
476 case 0:
477 printf("Image committed.\n");
478 break;
479 case -ENOENT:
480 error("No disk inserted");
481 break;
482 case -EACCES:
483 error("Image is read-only");
484 break;
485 case -ENOTSUP:
486 error("Image is already committed");
487 break;
488 default:
489 error("Error while committing image");
490 break;
493 bdrv_delete(bs);
494 return 0;
497 static int is_not_zero(const uint8_t *sector, int len)
499 int i;
500 len >>= 2;
501 for(i = 0;i < len; i++) {
502 if (((uint32_t *)sector)[i] != 0)
503 return 1;
505 return 0;
509 * Returns true iff the first sector pointed to by 'buf' contains at least
510 * a non-NUL byte.
512 * 'pnum' is set to the number of sectors (including and immediately following
513 * the first one) that are known to be in the same allocated/unallocated state.
515 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
517 int v, i;
519 if (n <= 0) {
520 *pnum = 0;
521 return 0;
523 v = is_not_zero(buf, 512);
524 for(i = 1; i < n; i++) {
525 buf += 512;
526 if (v != is_not_zero(buf, 512))
527 break;
529 *pnum = i;
530 return v;
533 #define IO_BUF_SIZE 65536
535 static int img_convert(int argc, char **argv)
537 int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
538 const char *fmt, *out_fmt, *out_baseimg, *out_filename;
539 BlockDriver *drv;
540 BlockDriverState **bs, *out_bs;
541 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
542 uint64_t bs_sectors;
543 uint8_t buf[IO_BUF_SIZE];
544 const uint8_t *buf1;
545 BlockDriverInfo bdi;
546 QEMUOptionParameter *param = NULL;
547 char *options = NULL;
549 fmt = NULL;
550 out_fmt = "raw";
551 out_baseimg = NULL;
552 flags = 0;
553 for(;;) {
554 c = getopt(argc, argv, "f:O:B:hce6o:");
555 if (c == -1)
556 break;
557 switch(c) {
558 case 'h':
559 help();
560 break;
561 case 'f':
562 fmt = optarg;
563 break;
564 case 'O':
565 out_fmt = optarg;
566 break;
567 case 'B':
568 out_baseimg = optarg;
569 break;
570 case 'c':
571 flags |= BLOCK_FLAG_COMPRESS;
572 break;
573 case 'e':
574 flags |= BLOCK_FLAG_ENCRYPT;
575 break;
576 case '6':
577 flags |= BLOCK_FLAG_COMPAT6;
578 break;
579 case 'o':
580 options = optarg;
581 break;
585 bs_n = argc - optind - 1;
586 if (bs_n < 1) help();
588 out_filename = argv[argc - 1];
590 if (bs_n > 1 && out_baseimg)
591 error("-B makes no sense when concatenating multiple input images");
593 bs = calloc(bs_n, sizeof(BlockDriverState *));
594 if (!bs)
595 error("Out of memory");
597 total_sectors = 0;
598 for (bs_i = 0; bs_i < bs_n; bs_i++) {
599 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
600 if (!bs[bs_i])
601 error("Could not open '%s'", argv[optind + bs_i]);
602 bdrv_get_geometry(bs[bs_i], &bs_sectors);
603 total_sectors += bs_sectors;
606 /* Find driver and parse its options */
607 drv = bdrv_find_format(out_fmt);
608 if (!drv)
609 error("Unknown file format '%s'", out_fmt);
611 if (options && !strcmp(options, "?")) {
612 print_option_help(drv->create_options);
613 return 0;
616 if (options) {
617 param = parse_option_parameters(options, drv->create_options, param);
618 if (param == NULL) {
619 error("Invalid options for file format '%s'.", out_fmt);
621 } else {
622 param = parse_option_parameters("", drv->create_options, param);
625 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
626 add_old_style_options(out_fmt, param, flags, out_baseimg, NULL);
628 /* Check if compression is supported */
629 if (flags & BLOCK_FLAG_COMPRESS) {
630 QEMUOptionParameter *encryption =
631 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
633 if (!drv->bdrv_write_compressed) {
634 error("Compression not supported for this file format");
637 if (encryption && encryption->value.n) {
638 error("Compression and encryption not supported at the same time");
642 /* Create the new image */
643 ret = bdrv_create(drv, out_filename, param);
644 free_option_parameters(param);
646 if (ret < 0) {
647 if (ret == -ENOTSUP) {
648 error("Formatting not supported for file format '%s'", out_fmt);
649 } else if (ret == -EFBIG) {
650 error("The image size is too large for file format '%s'", out_fmt);
651 } else {
652 error("Error while formatting '%s'", out_filename);
656 out_bs = bdrv_new_open(out_filename, out_fmt);
658 bs_i = 0;
659 bs_offset = 0;
660 bdrv_get_geometry(bs[0], &bs_sectors);
662 if (flags & BLOCK_FLAG_COMPRESS) {
663 if (bdrv_get_info(out_bs, &bdi) < 0)
664 error("could not get block driver info");
665 cluster_size = bdi.cluster_size;
666 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
667 error("invalid cluster size");
668 cluster_sectors = cluster_size >> 9;
669 sector_num = 0;
670 for(;;) {
671 int64_t bs_num;
672 int remainder;
673 uint8_t *buf2;
675 nb_sectors = total_sectors - sector_num;
676 if (nb_sectors <= 0)
677 break;
678 if (nb_sectors >= cluster_sectors)
679 n = cluster_sectors;
680 else
681 n = nb_sectors;
683 bs_num = sector_num - bs_offset;
684 assert (bs_num >= 0);
685 remainder = n;
686 buf2 = buf;
687 while (remainder > 0) {
688 int nlow;
689 while (bs_num == bs_sectors) {
690 bs_i++;
691 assert (bs_i < bs_n);
692 bs_offset += bs_sectors;
693 bdrv_get_geometry(bs[bs_i], &bs_sectors);
694 bs_num = 0;
695 /* printf("changing part: sector_num=%lld, "
696 "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
697 sector_num, bs_i, bs_offset, bs_sectors); */
699 assert (bs_num < bs_sectors);
701 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
703 if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0)
704 error("error while reading");
706 buf2 += nlow * 512;
707 bs_num += nlow;
709 remainder -= nlow;
711 assert (remainder == 0);
713 if (n < cluster_sectors)
714 memset(buf + n * 512, 0, cluster_size - n * 512);
715 if (is_not_zero(buf, cluster_size)) {
716 if (bdrv_write_compressed(out_bs, sector_num, buf,
717 cluster_sectors) != 0)
718 error("error while compressing sector %" PRId64,
719 sector_num);
721 sector_num += n;
723 /* signal EOF to align */
724 bdrv_write_compressed(out_bs, 0, NULL, 0);
725 } else {
726 sector_num = 0; // total number of sectors converted so far
727 for(;;) {
728 nb_sectors = total_sectors - sector_num;
729 if (nb_sectors <= 0)
730 break;
731 if (nb_sectors >= (IO_BUF_SIZE / 512))
732 n = (IO_BUF_SIZE / 512);
733 else
734 n = nb_sectors;
736 while (sector_num - bs_offset >= bs_sectors) {
737 bs_i ++;
738 assert (bs_i < bs_n);
739 bs_offset += bs_sectors;
740 bdrv_get_geometry(bs[bs_i], &bs_sectors);
741 /* printf("changing part: sector_num=%lld, bs_i=%d, "
742 "bs_offset=%lld, bs_sectors=%lld\n",
743 sector_num, bs_i, bs_offset, bs_sectors); */
746 if (n > bs_offset + bs_sectors - sector_num)
747 n = bs_offset + bs_sectors - sector_num;
749 if (strcmp(drv->format_name, "host_device")) {
750 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
751 n, &n1)) {
752 sector_num += n1;
753 continue;
755 /* The next 'n1' sectors are allocated in the input image. Copy
756 only those as they may be followed by unallocated sectors. */
757 n = n1;
758 } else {
759 n1 = n;
762 if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
763 error("error while reading");
764 /* NOTE: at the same time we convert, we do not write zero
765 sectors to have a chance to compress the image. Ideally, we
766 should add a specific call to have the info to go faster */
767 buf1 = buf;
768 while (n > 0) {
769 /* If the output image is being created as a copy on write image,
770 copy all sectors even the ones containing only NUL bytes,
771 because they may differ from the sectors in the base image.
773 If the output is to a host device, we also write out
774 sectors that are entirely 0, since whatever data was
775 already there is garbage, not 0s. */
776 if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg ||
777 is_allocated_sectors(buf1, n, &n1)) {
778 if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
779 error("error while writing");
781 sector_num += n1;
782 n -= n1;
783 buf1 += n1 * 512;
787 bdrv_delete(out_bs);
788 for (bs_i = 0; bs_i < bs_n; bs_i++)
789 bdrv_delete(bs[bs_i]);
790 free(bs);
791 return 0;
794 #ifdef _WIN32
795 static int64_t get_allocated_file_size(const char *filename)
797 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
798 get_compressed_t get_compressed;
799 struct _stati64 st;
801 /* WinNT support GetCompressedFileSize to determine allocate size */
802 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
803 if (get_compressed) {
804 DWORD high, low;
805 low = get_compressed(filename, &high);
806 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
807 return (((int64_t) high) << 32) + low;
810 if (_stati64(filename, &st) < 0)
811 return -1;
812 return st.st_size;
814 #else
815 static int64_t get_allocated_file_size(const char *filename)
817 struct stat st;
818 if (stat(filename, &st) < 0)
819 return -1;
820 return (int64_t)st.st_blocks * 512;
822 #endif
824 static void dump_snapshots(BlockDriverState *bs)
826 QEMUSnapshotInfo *sn_tab, *sn;
827 int nb_sns, i;
828 char buf[256];
830 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
831 if (nb_sns <= 0)
832 return;
833 printf("Snapshot list:\n");
834 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
835 for(i = 0; i < nb_sns; i++) {
836 sn = &sn_tab[i];
837 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
839 qemu_free(sn_tab);
842 static int img_info(int argc, char **argv)
844 int c;
845 const char *filename, *fmt;
846 BlockDriver *drv;
847 BlockDriverState *bs;
848 char fmt_name[128], size_buf[128], dsize_buf[128];
849 uint64_t total_sectors;
850 int64_t allocated_size;
851 char backing_filename[1024];
852 char backing_filename2[1024];
853 BlockDriverInfo bdi;
855 fmt = NULL;
856 for(;;) {
857 c = getopt(argc, argv, "f:h");
858 if (c == -1)
859 break;
860 switch(c) {
861 case 'h':
862 help();
863 break;
864 case 'f':
865 fmt = optarg;
866 break;
869 if (optind >= argc)
870 help();
871 filename = argv[optind++];
873 bs = bdrv_new("");
874 if (!bs)
875 error("Not enough memory");
876 if (fmt) {
877 drv = bdrv_find_format(fmt);
878 if (!drv)
879 error("Unknown file format '%s'", fmt);
880 } else {
881 drv = NULL;
883 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
884 error("Could not open '%s'", filename);
886 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
887 bdrv_get_geometry(bs, &total_sectors);
888 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
889 allocated_size = get_allocated_file_size(filename);
890 if (allocated_size < 0)
891 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
892 else
893 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
894 allocated_size);
895 printf("image: %s\n"
896 "file format: %s\n"
897 "virtual size: %s (%" PRId64 " bytes)\n"
898 "disk size: %s\n",
899 filename, fmt_name, size_buf,
900 (total_sectors * 512),
901 dsize_buf);
902 if (bdrv_is_encrypted(bs))
903 printf("encrypted: yes\n");
904 if (bdrv_get_info(bs, &bdi) >= 0) {
905 if (bdi.cluster_size != 0)
906 printf("cluster_size: %d\n", bdi.cluster_size);
908 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
909 if (backing_filename[0] != '\0') {
910 path_combine(backing_filename2, sizeof(backing_filename2),
911 filename, backing_filename);
912 printf("backing file: %s (actual path: %s)\n",
913 backing_filename,
914 backing_filename2);
916 dump_snapshots(bs);
917 bdrv_delete(bs);
918 return 0;
921 #define SNAPSHOT_LIST 1
922 #define SNAPSHOT_CREATE 2
923 #define SNAPSHOT_APPLY 3
924 #define SNAPSHOT_DELETE 4
926 static int img_snapshot(int argc, char **argv)
928 BlockDriverState *bs;
929 QEMUSnapshotInfo sn;
930 char *filename, *snapshot_name = NULL;
931 int c, ret;
932 int action = 0;
933 qemu_timeval tv;
935 /* Parse commandline parameters */
936 for(;;) {
937 c = getopt(argc, argv, "la:c:d:h");
938 if (c == -1)
939 break;
940 switch(c) {
941 case 'h':
942 help();
943 return 0;
944 case 'l':
945 if (action) {
946 help();
947 return 0;
949 action = SNAPSHOT_LIST;
950 break;
951 case 'a':
952 if (action) {
953 help();
954 return 0;
956 action = SNAPSHOT_APPLY;
957 snapshot_name = optarg;
958 break;
959 case 'c':
960 if (action) {
961 help();
962 return 0;
964 action = SNAPSHOT_CREATE;
965 snapshot_name = optarg;
966 break;
967 case 'd':
968 if (action) {
969 help();
970 return 0;
972 action = SNAPSHOT_DELETE;
973 snapshot_name = optarg;
974 break;
978 if (optind >= argc)
979 help();
980 filename = argv[optind++];
982 /* Open the image */
983 bs = bdrv_new("");
984 if (!bs)
985 error("Not enough memory");
987 if (bdrv_open2(bs, filename, 0, NULL) < 0) {
988 error("Could not open '%s'", filename);
991 /* Perform the requested action */
992 switch(action) {
993 case SNAPSHOT_LIST:
994 dump_snapshots(bs);
995 break;
997 case SNAPSHOT_CREATE:
998 memset(&sn, 0, sizeof(sn));
999 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1001 qemu_gettimeofday(&tv);
1002 sn.date_sec = tv.tv_sec;
1003 sn.date_nsec = tv.tv_usec * 1000;
1005 ret = bdrv_snapshot_create(bs, &sn);
1006 if (ret)
1007 error("Could not create snapshot '%s': %d (%s)",
1008 snapshot_name, ret, strerror(-ret));
1009 break;
1011 case SNAPSHOT_APPLY:
1012 ret = bdrv_snapshot_goto(bs, snapshot_name);
1013 if (ret)
1014 error("Could not apply snapshot '%s': %d (%s)",
1015 snapshot_name, ret, strerror(-ret));
1016 break;
1018 case SNAPSHOT_DELETE:
1019 ret = bdrv_snapshot_delete(bs, snapshot_name);
1020 if (ret)
1021 error("Could not delete snapshot '%s': %d (%s)",
1022 snapshot_name, ret, strerror(-ret));
1023 break;
1026 /* Cleanup */
1027 bdrv_delete(bs);
1029 return 0;
1032 static const img_cmd_t img_cmds[] = {
1033 #define DEF(option, callback, arg_string) \
1034 { option, callback },
1035 #include "qemu-img-cmds.h"
1036 #undef DEF
1037 #undef GEN_DOCS
1038 { NULL, NULL, },
1041 int main(int argc, char **argv)
1043 const img_cmd_t *cmd;
1044 const char *cmdname;
1046 bdrv_init();
1047 if (argc < 2)
1048 help();
1049 cmdname = argv[1];
1050 argc--; argv++;
1052 /* find the command */
1053 for(cmd = img_cmds; cmd->name != NULL; cmd++) {
1054 if (!strcmp(cmdname, cmd->name)) {
1055 return cmd->handler(argc, argv);
1059 /* not found */
1060 help();
1061 return 0;