]> git.proxmox.com Git - qemu.git/blame - qemu-img.c
More generic boot devices specification, allowing more devices to be specified
[qemu.git] / qemu-img.c
CommitLineData
ea2384d3 1/*
fb43f4dd 2 * QEMU disk image utility
5fafdf24 3 *
84f2e8ef 4 * Copyright (c) 2003-2007 Fabrice Bellard
5fafdf24 5 *
ea2384d3
FB
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 "vl.h"
ec36ba14 25#include "block_int.h"
926c2d23 26#include <assert.h>
ea2384d3 27
e8445331
FB
28#ifdef _WIN32
29#include <windows.h>
30#endif
31
ea2384d3
FB
32void *get_mmap_addr(unsigned long size)
33{
34 return NULL;
35}
36
37void qemu_free(void *ptr)
38{
39 free(ptr);
40}
41
42void *qemu_malloc(size_t size)
43{
44 return malloc(size);
45}
46
47void *qemu_mallocz(size_t size)
48{
49 void *ptr;
50 ptr = qemu_malloc(size);
51 if (!ptr)
52 return NULL;
53 memset(ptr, 0, size);
54 return ptr;
55}
56
57char *qemu_strdup(const char *str)
58{
59 char *ptr;
60 ptr = qemu_malloc(strlen(str) + 1);
61 if (!ptr)
62 return NULL;
63 strcpy(ptr, str);
64 return ptr;
65}
66
ea2384d3
FB
67void term_printf(const char *fmt, ...)
68{
69 va_list ap;
70 va_start(ap, fmt);
71 vprintf(fmt, ap);
72 va_end(ap);
73}
74
fef30743
TS
75void term_print_filename(const char *filename)
76{
77 term_printf(filename);
78}
79
5fafdf24 80void __attribute__((noreturn)) error(const char *fmt, ...)
ea2384d3
FB
81{
82 va_list ap;
83 va_start(ap, fmt);
57d1a2b6 84 fprintf(stderr, "qemu-img: ");
ea2384d3
FB
85 vfprintf(stderr, fmt, ap);
86 fprintf(stderr, "\n");
87 exit(1);
88 va_end(ap);
89}
90
91static void format_print(void *opaque, const char *name)
92{
93 printf(" %s", name);
94}
95
96void help(void)
97{
84f2e8ef 98 printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2007 Fabrice Bellard\n"
57d1a2b6 99 "usage: qemu-img command [command options]\n"
ea2384d3
FB
100 "QEMU disk image utility\n"
101 "\n"
102 "Command syntax:\n"
ec36ba14 103 " create [-e] [-6] [-b base_image] [-f fmt] filename [size]\n"
ea2384d3 104 " commit [-f fmt] filename\n"
926c2d23 105 " convert [-c] [-e] [-6] [-f fmt] filename [filename2 [...]] [-O output_fmt] output_filename\n"
ea2384d3
FB
106 " info [-f fmt] filename\n"
107 "\n"
108 "Command parameters:\n"
109 " 'filename' is a disk image filename\n"
110 " 'base_image' is the read-only disk image which is used as base for a copy on\n"
111 " write image; the copy on write image only stores the modified data\n"
112 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
113 " 'size' is the disk image size in kilobytes. Optional suffixes 'M' (megabyte)\n"
114 " and 'G' (gigabyte) are supported\n"
115 " 'output_filename' is the destination disk image filename\n"
116 " 'output_fmt' is the destination format\n"
117 " '-c' indicates that target image must be compressed (qcow format only)\n"
118 " '-e' indicates that the target image must be encrypted (qcow format only)\n"
ec36ba14 119 " '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
ea2384d3
FB
120 );
121 printf("\nSupported format:");
122 bdrv_iterate_format(format_print, NULL);
123 printf("\n");
124 exit(1);
125}
126
ea2384d3
FB
127#if defined(WIN32)
128/* XXX: put correct support for win32 */
129static int read_password(char *buf, int buf_size)
130{
131 int c, i;
132 printf("Password: ");
133 fflush(stdout);
134 i = 0;
135 for(;;) {
136 c = getchar();
137 if (c == '\n')
138 break;
139 if (i < (buf_size - 1))
140 buf[i++] = c;
141 }
142 buf[i] = '\0';
143 return 0;
144}
145
146#else
147
148#include <termios.h>
149
150static struct termios oldtty;
151
152static void term_exit(void)
153{
154 tcsetattr (0, TCSANOW, &oldtty);
155}
156
157static void term_init(void)
158{
159 struct termios tty;
160
161 tcgetattr (0, &tty);
162 oldtty = tty;
163
164 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
165 |INLCR|IGNCR|ICRNL|IXON);
166 tty.c_oflag |= OPOST;
167 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
168 tty.c_cflag &= ~(CSIZE|PARENB);
169 tty.c_cflag |= CS8;
170 tty.c_cc[VMIN] = 1;
171 tty.c_cc[VTIME] = 0;
3b46e624 172
ea2384d3
FB
173 tcsetattr (0, TCSANOW, &tty);
174
175 atexit(term_exit);
176}
177
178int read_password(char *buf, int buf_size)
179{
180 uint8_t ch;
181 int i, ret;
182
183 printf("password: ");
184 fflush(stdout);
185 term_init();
186 i = 0;
187 for(;;) {
188 ret = read(0, &ch, 1);
189 if (ret == -1) {
190 if (errno == EAGAIN || errno == EINTR) {
191 continue;
192 } else {
193 ret = -1;
194 break;
195 }
196 } else if (ret == 0) {
197 ret = -1;
198 break;
199 } else {
200 if (ch == '\r') {
201 ret = 0;
202 break;
203 }
204 if (i < (buf_size - 1))
205 buf[i++] = ch;
206 }
207 }
208 term_exit();
209 buf[i] = '\0';
210 printf("\n");
211 return ret;
212}
213#endif
214
75c23805
FB
215static BlockDriverState *bdrv_new_open(const char *filename,
216 const char *fmt)
217{
218 BlockDriverState *bs;
219 BlockDriver *drv;
220 char password[256];
221
222 bs = bdrv_new("");
223 if (!bs)
224 error("Not enough memory");
225 if (fmt) {
226 drv = bdrv_find_format(fmt);
227 if (!drv)
228 error("Unknown file format '%s'", fmt);
229 } else {
230 drv = NULL;
231 }
232 if (bdrv_open2(bs, filename, 0, drv) < 0) {
233 error("Could not open '%s'", filename);
234 }
235 if (bdrv_is_encrypted(bs)) {
236 printf("Disk image '%s' is encrypted.\n", filename);
237 if (read_password(password, sizeof(password)) < 0)
238 error("No password given");
239 if (bdrv_set_key(bs, password) < 0)
240 error("invalid password");
241 }
242 return bs;
243}
244
ea2384d3
FB
245static int img_create(int argc, char **argv)
246{
ec36ba14 247 int c, ret, flags;
ea2384d3
FB
248 const char *fmt = "raw";
249 const char *filename;
250 const char *base_filename = NULL;
251 int64_t size;
252 const char *p;
253 BlockDriver *drv;
3b46e624 254
ec36ba14 255 flags = 0;
ea2384d3 256 for(;;) {
ec36ba14 257 c = getopt(argc, argv, "b:f:he6");
ea2384d3
FB
258 if (c == -1)
259 break;
260 switch(c) {
261 case 'h':
262 help();
263 break;
264 case 'b':
265 base_filename = optarg;
266 break;
267 case 'f':
268 fmt = optarg;
269 break;
270 case 'e':
ec36ba14 271 flags |= BLOCK_FLAG_ENCRYPT;
ea2384d3 272 break;
d8871c5a 273 case '6':
ec36ba14 274 flags |= BLOCK_FLAG_COMPAT6;
d8871c5a 275 break;
ea2384d3
FB
276 }
277 }
5fafdf24 278 if (optind >= argc)
ea2384d3
FB
279 help();
280 filename = argv[optind++];
281 size = 0;
75c23805
FB
282 if (base_filename) {
283 BlockDriverState *bs;
284 bs = bdrv_new_open(base_filename, NULL);
285 bdrv_get_geometry(bs, &size);
286 size *= 512;
287 bdrv_delete(bs);
288 } else {
ea2384d3
FB
289 if (optind >= argc)
290 help();
291 p = argv[optind];
292 size = strtoul(p, (char **)&p, 0);
293 if (*p == 'M') {
294 size *= 1024 * 1024;
295 } else if (*p == 'G') {
296 size *= 1024 * 1024 * 1024;
297 } else if (*p == 'k' || *p == 'K' || *p == '\0') {
298 size *= 1024;
299 } else {
300 help();
301 }
302 }
303 drv = bdrv_find_format(fmt);
304 if (!drv)
305 error("Unknown file format '%s'", fmt);
0cfec834 306 printf("Formatting '%s', fmt=%s",
ea2384d3 307 filename, fmt);
ec36ba14 308 if (flags & BLOCK_FLAG_ENCRYPT)
ea2384d3 309 printf(", encrypted");
ec36ba14
TS
310 if (flags & BLOCK_FLAG_COMPAT6)
311 printf(", compatibility level=6");
75c23805
FB
312 if (base_filename) {
313 printf(", backing_file=%s",
ea2384d3 314 base_filename);
75c23805 315 }
ec3757de 316 printf(", size=%" PRId64 " kB\n", (int64_t) (size / 1024));
ec36ba14 317 ret = bdrv_create(drv, filename, size / 512, base_filename, flags);
ea2384d3
FB
318 if (ret < 0) {
319 if (ret == -ENOTSUP) {
3c56521b 320 error("Formatting or formatting option not supported for file format '%s'", fmt);
ea2384d3
FB
321 } else {
322 error("Error while formatting");
323 }
324 }
325 return 0;
326}
327
328static int img_commit(int argc, char **argv)
329{
330 int c, ret;
331 const char *filename, *fmt;
332 BlockDriver *drv;
333 BlockDriverState *bs;
334
335 fmt = NULL;
336 for(;;) {
337 c = getopt(argc, argv, "f:h");
338 if (c == -1)
339 break;
340 switch(c) {
341 case 'h':
342 help();
343 break;
344 case 'f':
345 fmt = optarg;
346 break;
347 }
348 }
5fafdf24 349 if (optind >= argc)
ea2384d3
FB
350 help();
351 filename = argv[optind++];
352
353 bs = bdrv_new("");
354 if (!bs)
355 error("Not enough memory");
356 if (fmt) {
357 drv = bdrv_find_format(fmt);
358 if (!drv)
359 error("Unknown file format '%s'", fmt);
360 } else {
361 drv = NULL;
362 }
363 if (bdrv_open2(bs, filename, 0, drv) < 0) {
364 error("Could not open '%s'", filename);
365 }
366 ret = bdrv_commit(bs);
367 switch(ret) {
368 case 0:
369 printf("Image committed.\n");
370 break;
371 case -ENOENT:
372 error("No disk inserted");
373 break;
374 case -EACCES:
375 error("Image is read-only");
376 break;
377 case -ENOTSUP:
378 error("Image is already committed");
379 break;
380 default:
381 error("Error while committing image");
382 break;
383 }
384
385 bdrv_delete(bs);
386 return 0;
387}
388
389static int is_not_zero(const uint8_t *sector, int len)
390{
391 int i;
392 len >>= 2;
393 for(i = 0;i < len; i++) {
394 if (((uint32_t *)sector)[i] != 0)
395 return 1;
396 }
397 return 0;
398}
399
400static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
401{
402 int v, i;
403
404 if (n <= 0) {
405 *pnum = 0;
406 return 0;
407 }
408 v = is_not_zero(buf, 512);
409 for(i = 1; i < n; i++) {
410 buf += 512;
411 if (v != is_not_zero(buf, 512))
412 break;
413 }
414 *pnum = i;
415 return v;
416}
417
ea2384d3
FB
418#define IO_BUF_SIZE 65536
419
420static int img_convert(int argc, char **argv)
421{
926c2d23
AZ
422 int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
423 const char *fmt, *out_fmt, *out_filename;
ea2384d3 424 BlockDriver *drv;
926c2d23
AZ
425 BlockDriverState **bs, *out_bs;
426 int64_t total_sectors, nb_sectors, sector_num, bs_offset, bs_sectors;
ea2384d3
FB
427 uint8_t buf[IO_BUF_SIZE];
428 const uint8_t *buf1;
faea38e7 429 BlockDriverInfo bdi;
ea2384d3
FB
430
431 fmt = NULL;
432 out_fmt = "raw";
ec36ba14 433 flags = 0;
ea2384d3 434 for(;;) {
ec36ba14 435 c = getopt(argc, argv, "f:O:hce6");
ea2384d3
FB
436 if (c == -1)
437 break;
438 switch(c) {
439 case 'h':
440 help();
441 break;
442 case 'f':
443 fmt = optarg;
444 break;
445 case 'O':
446 out_fmt = optarg;
447 break;
448 case 'c':
ec36ba14 449 flags |= BLOCK_FLAG_COMPRESS;
ea2384d3
FB
450 break;
451 case 'e':
ec36ba14
TS
452 flags |= BLOCK_FLAG_ENCRYPT;
453 break;
454 case '6':
455 flags |= BLOCK_FLAG_COMPAT6;
ea2384d3
FB
456 break;
457 }
458 }
3b46e624 459
926c2d23
AZ
460 bs_n = argc - optind - 1;
461 if (bs_n < 1) help();
462
463 out_filename = argv[argc - 1];
464
465 bs = calloc(bs_n, sizeof(BlockDriverState *));
466 if (!bs)
467 error("Out of memory");
468
469 total_sectors = 0;
470 for (bs_i = 0; bs_i < bs_n; bs_i++) {
471 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
472 if (!bs[bs_i])
473 error("Could not open '%s'", argv[optind + bs_i]);
474 bdrv_get_geometry(bs[bs_i], &bs_sectors);
475 total_sectors += bs_sectors;
476 }
ea2384d3
FB
477
478 drv = bdrv_find_format(out_fmt);
479 if (!drv)
d34dda5e 480 error("Unknown file format '%s'", out_fmt);
ec36ba14 481 if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2)
ea2384d3 482 error("Compression not supported for this file format");
ec36ba14 483 if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
ea2384d3 484 error("Encryption not supported for this file format");
d8871c5a 485 if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
ec36ba14
TS
486 error("Alternative compatibility level not supported for this file format");
487 if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
ea2384d3 488 error("Compression and encryption not supported at the same time");
926c2d23 489
ec36ba14 490 ret = bdrv_create(drv, out_filename, total_sectors, NULL, flags);
ea2384d3
FB
491 if (ret < 0) {
492 if (ret == -ENOTSUP) {
3c56521b 493 error("Formatting not supported for file format '%s'", fmt);
ea2384d3
FB
494 } else {
495 error("Error while formatting '%s'", out_filename);
496 }
497 }
3b46e624 498
ea2384d3
FB
499 out_bs = bdrv_new_open(out_filename, out_fmt);
500
926c2d23
AZ
501 bs_i = 0;
502 bs_offset = 0;
503 bdrv_get_geometry(bs[0], &bs_sectors);
504
505 if (flags & BLOCK_FLAG_COMPRESS) {
faea38e7
FB
506 if (bdrv_get_info(out_bs, &bdi) < 0)
507 error("could not get block driver info");
508 cluster_size = bdi.cluster_size;
ea2384d3
FB
509 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
510 error("invalid cluster size");
511 cluster_sectors = cluster_size >> 9;
512 sector_num = 0;
513 for(;;) {
926c2d23
AZ
514 int64_t bs_num;
515 int remainder;
516 uint8_t *buf2;
517
ea2384d3
FB
518 nb_sectors = total_sectors - sector_num;
519 if (nb_sectors <= 0)
520 break;
521 if (nb_sectors >= cluster_sectors)
522 n = cluster_sectors;
523 else
524 n = nb_sectors;
926c2d23
AZ
525
526 bs_num = sector_num - bs_offset;
527 assert (bs_num >= 0);
528 remainder = n;
529 buf2 = buf;
530 while (remainder > 0) {
531 int nlow;
532 while (bs_num == bs_sectors) {
533 bs_i++;
534 assert (bs_i < bs_n);
535 bs_offset += bs_sectors;
536 bdrv_get_geometry(bs[bs_i], &bs_sectors);
537 bs_num = 0;
538 /* printf("changing part: sector_num=%lld, "
539 "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
540 sector_num, bs_i, bs_offset, bs_sectors); */
541 }
542 assert (bs_num < bs_sectors);
543
544 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
545
546 if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0)
547 error("error while reading");
548
549 buf2 += nlow * 512;
550 bs_num += nlow;
551
552 remainder -= nlow;
553 }
554 assert (remainder == 0);
555
ea2384d3
FB
556 if (n < cluster_sectors)
557 memset(buf + n * 512, 0, cluster_size - n * 512);
558 if (is_not_zero(buf, cluster_size)) {
5fafdf24 559 if (bdrv_write_compressed(out_bs, sector_num, buf,
faea38e7 560 cluster_sectors) != 0)
ec3757de
FB
561 error("error while compressing sector %" PRId64,
562 sector_num);
ea2384d3
FB
563 }
564 sector_num += n;
565 }
faea38e7
FB
566 /* signal EOF to align */
567 bdrv_write_compressed(out_bs, 0, NULL, 0);
ea2384d3
FB
568 } else {
569 sector_num = 0;
570 for(;;) {
571 nb_sectors = total_sectors - sector_num;
572 if (nb_sectors <= 0)
573 break;
574 if (nb_sectors >= (IO_BUF_SIZE / 512))
575 n = (IO_BUF_SIZE / 512);
576 else
577 n = nb_sectors;
926c2d23
AZ
578
579 while (sector_num - bs_offset >= bs_sectors) {
580 bs_i ++;
581 assert (bs_i < bs_n);
582 bs_offset += bs_sectors;
583 bdrv_get_geometry(bs[bs_i], &bs_sectors);
584 /* printf("changing part: sector_num=%lld, bs_i=%d, "
585 "bs_offset=%lld, bs_sectors=%lld\n",
586 sector_num, bs_i, bs_offset, bs_sectors); */
587 }
588
589 if (n > bs_offset + bs_sectors - sector_num)
590 n = bs_offset + bs_sectors - sector_num;
591
592 if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
ea2384d3
FB
593 error("error while reading");
594 /* NOTE: at the same time we convert, we do not write zero
595 sectors to have a chance to compress the image. Ideally, we
596 should add a specific call to have the info to go faster */
597 buf1 = buf;
598 while (n > 0) {
599 if (is_allocated_sectors(buf1, n, &n1)) {
5fafdf24 600 if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
ea2384d3
FB
601 error("error while writing");
602 }
603 sector_num += n1;
604 n -= n1;
605 buf1 += n1 * 512;
606 }
607 }
608 }
609 bdrv_delete(out_bs);
926c2d23
AZ
610 for (bs_i = 0; bs_i < bs_n; bs_i++)
611 bdrv_delete(bs[bs_i]);
612 free(bs);
ea2384d3
FB
613 return 0;
614}
615
57d1a2b6
FB
616#ifdef _WIN32
617static int64_t get_allocated_file_size(const char *filename)
618{
e8445331
FB
619 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
620 get_compressed_t get_compressed;
57d1a2b6 621 struct _stati64 st;
e8445331
FB
622
623 /* WinNT support GetCompressedFileSize to determine allocate size */
624 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
625 if (get_compressed) {
626 DWORD high, low;
627 low = get_compressed(filename, &high);
628 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
629 return (((int64_t) high) << 32) + low;
630 }
631
5fafdf24 632 if (_stati64(filename, &st) < 0)
57d1a2b6
FB
633 return -1;
634 return st.st_size;
635}
636#else
637static int64_t get_allocated_file_size(const char *filename)
638{
639 struct stat st;
5fafdf24 640 if (stat(filename, &st) < 0)
57d1a2b6
FB
641 return -1;
642 return (int64_t)st.st_blocks * 512;
643}
644#endif
645
faea38e7
FB
646static void dump_snapshots(BlockDriverState *bs)
647{
648 QEMUSnapshotInfo *sn_tab, *sn;
649 int nb_sns, i;
650 char buf[256];
651
652 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
653 if (nb_sns <= 0)
654 return;
655 printf("Snapshot list:\n");
656 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
657 for(i = 0; i < nb_sns; i++) {
658 sn = &sn_tab[i];
659 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
660 }
661 qemu_free(sn_tab);
662}
663
ea2384d3
FB
664static int img_info(int argc, char **argv)
665{
666 int c;
667 const char *filename, *fmt;
668 BlockDriver *drv;
669 BlockDriverState *bs;
670 char fmt_name[128], size_buf[128], dsize_buf[128];
57d1a2b6 671 int64_t total_sectors, allocated_size;
93b6b2a3
FB
672 char backing_filename[1024];
673 char backing_filename2[1024];
faea38e7 674 BlockDriverInfo bdi;
ea2384d3
FB
675
676 fmt = NULL;
677 for(;;) {
678 c = getopt(argc, argv, "f:h");
679 if (c == -1)
680 break;
681 switch(c) {
682 case 'h':
683 help();
684 break;
685 case 'f':
686 fmt = optarg;
687 break;
688 }
689 }
5fafdf24 690 if (optind >= argc)
ea2384d3
FB
691 help();
692 filename = argv[optind++];
693
694 bs = bdrv_new("");
695 if (!bs)
696 error("Not enough memory");
697 if (fmt) {
698 drv = bdrv_find_format(fmt);
699 if (!drv)
700 error("Unknown file format '%s'", fmt);
701 } else {
702 drv = NULL;
703 }
704 if (bdrv_open2(bs, filename, 0, drv) < 0) {
705 error("Could not open '%s'", filename);
706 }
707 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
708 bdrv_get_geometry(bs, &total_sectors);
709 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
57d1a2b6
FB
710 allocated_size = get_allocated_file_size(filename);
711 if (allocated_size < 0)
de167e41
FB
712 sprintf(dsize_buf, "unavailable");
713 else
5fafdf24 714 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
de167e41 715 allocated_size);
ea2384d3
FB
716 printf("image: %s\n"
717 "file format: %s\n"
ec3757de 718 "virtual size: %s (%" PRId64 " bytes)\n"
ea2384d3 719 "disk size: %s\n",
5fafdf24 720 filename, fmt_name, size_buf,
ec3757de 721 (total_sectors * 512),
ea2384d3
FB
722 dsize_buf);
723 if (bdrv_is_encrypted(bs))
724 printf("encrypted: yes\n");
faea38e7 725 if (bdrv_get_info(bs, &bdi) >= 0) {
5fafdf24 726 if (bdi.cluster_size != 0)
faea38e7
FB
727 printf("cluster_size: %d\n", bdi.cluster_size);
728 }
93b6b2a3 729 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
faea38e7 730 if (backing_filename[0] != '\0') {
93b6b2a3
FB
731 path_combine(backing_filename2, sizeof(backing_filename2),
732 filename, backing_filename);
5fafdf24 733 printf("backing file: %s (actual path: %s)\n",
93b6b2a3
FB
734 backing_filename,
735 backing_filename2);
faea38e7
FB
736 }
737 dump_snapshots(bs);
ea2384d3
FB
738 bdrv_delete(bs);
739 return 0;
740}
741
742int main(int argc, char **argv)
743{
744 const char *cmd;
745
746 bdrv_init();
747 if (argc < 2)
748 help();
749 cmd = argv[1];
e3888186 750 optind++;
ea2384d3
FB
751 if (!strcmp(cmd, "create")) {
752 img_create(argc, argv);
753 } else if (!strcmp(cmd, "commit")) {
754 img_commit(argc, argv);
755 } else if (!strcmp(cmd, "convert")) {
756 img_convert(argc, argv);
757 } else if (!strcmp(cmd, "info")) {
758 img_info(argc, argv);
759 } else {
760 help();
761 }
762 return 0;
763}