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