]> git.proxmox.com Git - qemu.git/blame - qemu-img.c
target-alpha: lower parent irq when irq is lowered.
[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"
f7b4a940 25#include "osdep.h"
ec36ba14 26#include "block_int.h"
926c2d23 27#include <assert.h>
9230eaf6 28#include <stdio.h>
ea2384d3 29
e8445331
FB
30#ifdef _WIN32
31#include <windows.h>
32#endif
33
137519ce
AJ
34/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
35#define BRDV_O_FLAGS BDRV_O_CACHE_WB
36
a5e50b26 37static void QEMU_NORETURN error(const char *fmt, ...)
ea2384d3
FB
38{
39 va_list ap;
40 va_start(ap, fmt);
57d1a2b6 41 fprintf(stderr, "qemu-img: ");
ea2384d3
FB
42 vfprintf(stderr, fmt, ap);
43 fprintf(stderr, "\n");
44 exit(1);
45 va_end(ap);
46}
47
48static void format_print(void *opaque, const char *name)
49{
50 printf(" %s", name);
51}
52
d2c639d6 53/* Please keep in synch with qemu-img.texi */
3f379ab1 54static void help(void)
ea2384d3 55{
68d0f70e 56 printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
57d1a2b6 57 "usage: qemu-img command [command options]\n"
ea2384d3
FB
58 "QEMU disk image utility\n"
59 "\n"
60 "Command syntax:\n"
9230eaf6 61 " create [-e] [-6] [-F fmt] [-b base_image] [-f fmt] filename [size]\n"
ea2384d3 62 " commit [-f fmt] filename\n"
f58c7b35 63 " convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
ea2384d3 64 " info [-f fmt] filename\n"
d2c639d6 65 " snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename\n"
ea2384d3
FB
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"
f58c7b35
TS
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"
ea2384d3 75 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
d2c639d6 76 " 'size' is the disk image size in kilobytes. Optional suffixes\n"
2fbc4095
AJ
77 " 'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
78 " supported any 'k' or 'K' is ignored\n"
ea2384d3
FB
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"
ec36ba14 83 " '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
d2c639d6 84 " '-h' with or without a command shows this help and lists the supported formats\n"
f7b4a940 85 "\n"
d2c639d6
BS
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"
ea2384d3 92 );
d2c639d6 93 printf("\nSupported formats:");
ea2384d3
FB
94 bdrv_iterate_format(format_print, NULL);
95 printf("\n");
96 exit(1);
97}
98
ea2384d3
FB
99#if defined(WIN32)
100/* XXX: put correct support for win32 */
101static 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
122static struct termios oldtty;
123
124static void term_exit(void)
125{
126 tcsetattr (0, TCSANOW, &oldtty);
127}
128
129static 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;
3b46e624 144
ea2384d3
FB
145 tcsetattr (0, TCSANOW, &tty);
146
147 atexit(term_exit);
148}
149
3f379ab1 150static int read_password(char *buf, int buf_size)
ea2384d3
FB
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
75c23805
FB
187static 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 }
137519ce 204 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
75c23805
FB
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
ea2384d3
FB
217static int img_create(int argc, char **argv)
218{
ec36ba14 219 int c, ret, flags;
ea2384d3 220 const char *fmt = "raw";
9230eaf6 221 const char *base_fmt = NULL;
ea2384d3
FB
222 const char *filename;
223 const char *base_filename = NULL;
96b8f136 224 uint64_t size;
24501489 225 double sizef;
ea2384d3
FB
226 const char *p;
227 BlockDriver *drv;
3b46e624 228
ec36ba14 229 flags = 0;
ea2384d3 230 for(;;) {
9230eaf6 231 c = getopt(argc, argv, "F:b:f:he6");
ea2384d3
FB
232 if (c == -1)
233 break;
234 switch(c) {
235 case 'h':
236 help();
237 break;
9230eaf6
AL
238 case 'F':
239 base_fmt = optarg;
240 break;
ea2384d3
FB
241 case 'b':
242 base_filename = optarg;
243 break;
244 case 'f':
245 fmt = optarg;
246 break;
247 case 'e':
ec36ba14 248 flags |= BLOCK_FLAG_ENCRYPT;
ea2384d3 249 break;
d8871c5a 250 case '6':
ec36ba14 251 flags |= BLOCK_FLAG_COMPAT6;
d8871c5a 252 break;
ea2384d3
FB
253 }
254 }
5fafdf24 255 if (optind >= argc)
ea2384d3
FB
256 help();
257 filename = argv[optind++];
258 size = 0;
75c23805 259 if (base_filename) {
e94f3a60 260 BlockDriverState *bs;
9230eaf6
AL
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);
75c23805
FB
270 bdrv_get_geometry(bs, &size);
271 size *= 512;
272 bdrv_delete(bs);
273 } else {
ea2384d3
FB
274 if (optind >= argc)
275 help();
276 p = argv[optind];
24501489 277 sizef = strtod(p, (char **)&p);
ea2384d3 278 if (*p == 'M') {
24501489 279 size = (uint64_t)(sizef * 1024 * 1024);
ea2384d3 280 } else if (*p == 'G') {
24501489 281 size = (uint64_t)(sizef * 1024 * 1024 * 1024);
ea2384d3 282 } else if (*p == 'k' || *p == 'K' || *p == '\0') {
24501489 283 size = (uint64_t)(sizef * 1024);
ea2384d3
FB
284 } else {
285 help();
286 }
287 }
288 drv = bdrv_find_format(fmt);
289 if (!drv)
290 error("Unknown file format '%s'", fmt);
0cfec834 291 printf("Formatting '%s', fmt=%s",
ea2384d3 292 filename, fmt);
ec36ba14 293 if (flags & BLOCK_FLAG_ENCRYPT)
ea2384d3 294 printf(", encrypted");
ec36ba14
TS
295 if (flags & BLOCK_FLAG_COMPAT6)
296 printf(", compatibility level=6");
75c23805
FB
297 if (base_filename) {
298 printf(", backing_file=%s",
ea2384d3 299 base_filename);
9230eaf6
AL
300 if (base_fmt)
301 printf(", backing_fmt=%s",
302 base_fmt);
75c23805 303 }
96b8f136 304 printf(", size=%" PRIu64 " kB\n", size / 1024);
9230eaf6 305 ret = bdrv_create2(drv, filename, size / 512, base_filename, base_fmt, flags);
ea2384d3
FB
306 if (ret < 0) {
307 if (ret == -ENOTSUP) {
3c56521b 308 error("Formatting or formatting option not supported for file format '%s'", fmt);
ea2384d3
FB
309 } else {
310 error("Error while formatting");
311 }
312 }
313 return 0;
314}
315
316static 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 }
5fafdf24 337 if (optind >= argc)
ea2384d3
FB
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 }
137519ce 351 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
ea2384d3
FB
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
377static 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
f58c7b35
TS
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 */
ea2384d3
FB
395static 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
ea2384d3
FB
413#define IO_BUF_SIZE 65536
414
415static int img_convert(int argc, char **argv)
416{
926c2d23 417 int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
f58c7b35 418 const char *fmt, *out_fmt, *out_baseimg, *out_filename;
ea2384d3 419 BlockDriver *drv;
926c2d23 420 BlockDriverState **bs, *out_bs;
96b8f136
TS
421 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
422 uint64_t bs_sectors;
ea2384d3
FB
423 uint8_t buf[IO_BUF_SIZE];
424 const uint8_t *buf1;
faea38e7 425 BlockDriverInfo bdi;
ea2384d3
FB
426
427 fmt = NULL;
428 out_fmt = "raw";
f58c7b35 429 out_baseimg = NULL;
ec36ba14 430 flags = 0;
ea2384d3 431 for(;;) {
f58c7b35 432 c = getopt(argc, argv, "f:O:B:hce6");
ea2384d3
FB
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;
f58c7b35
TS
445 case 'B':
446 out_baseimg = optarg;
447 break;
ea2384d3 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];
f58c7b35
TS
464
465 if (bs_n > 1 && out_baseimg)
466 error("-B makes no sense when concatenating multiple input images");
926c2d23
AZ
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 }
ea2384d3
FB
480
481 drv = bdrv_find_format(out_fmt);
482 if (!drv)
d34dda5e 483 error("Unknown file format '%s'", out_fmt);
ec36ba14 484 if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2)
ea2384d3 485 error("Compression not supported for this file format");
ec36ba14 486 if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
ea2384d3 487 error("Encryption not supported for this file format");
d8871c5a 488 if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
ec36ba14
TS
489 error("Alternative compatibility level not supported for this file format");
490 if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
ea2384d3 491 error("Compression and encryption not supported at the same time");
926c2d23 492
f58c7b35 493 ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
ea2384d3
FB
494 if (ret < 0) {
495 if (ret == -ENOTSUP) {
93c65b47 496 error("Formatting not supported for file format '%s'", out_fmt);
ea2384d3
FB
497 } else {
498 error("Error while formatting '%s'", out_filename);
499 }
500 }
3b46e624 501
ea2384d3
FB
502 out_bs = bdrv_new_open(out_filename, out_fmt);
503
926c2d23
AZ
504 bs_i = 0;
505 bs_offset = 0;
506 bdrv_get_geometry(bs[0], &bs_sectors);
507
508 if (flags & BLOCK_FLAG_COMPRESS) {
faea38e7
FB
509 if (bdrv_get_info(out_bs, &bdi) < 0)
510 error("could not get block driver info");
511 cluster_size = bdi.cluster_size;
ea2384d3
FB
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(;;) {
926c2d23
AZ
517 int64_t bs_num;
518 int remainder;
519 uint8_t *buf2;
520
ea2384d3
FB
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;
926c2d23
AZ
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
ea2384d3
FB
559 if (n < cluster_sectors)
560 memset(buf + n * 512, 0, cluster_size - n * 512);
561 if (is_not_zero(buf, cluster_size)) {
5fafdf24 562 if (bdrv_write_compressed(out_bs, sector_num, buf,
faea38e7 563 cluster_sectors) != 0)
ec3757de
FB
564 error("error while compressing sector %" PRId64,
565 sector_num);
ea2384d3
FB
566 }
567 sector_num += n;
568 }
faea38e7
FB
569 /* signal EOF to align */
570 bdrv_write_compressed(out_bs, 0, NULL, 0);
ea2384d3 571 } else {
f58c7b35 572 sector_num = 0; // total number of sectors converted so far
ea2384d3
FB
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;
926c2d23
AZ
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
93c65b47
AL
595 if (drv != &bdrv_host_device) {
596 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
597 n, &n1)) {
598 sector_num += n1;
599 continue;
600 }
601 /* The next 'n1' sectors are allocated in the input image. Copy
602 only those as they may be followed by unallocated sectors. */
603 n = n1;
604 } else {
605 n1 = n;
f58c7b35
TS
606 }
607
926c2d23 608 if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0)
ea2384d3
FB
609 error("error while reading");
610 /* NOTE: at the same time we convert, we do not write zero
611 sectors to have a chance to compress the image. Ideally, we
612 should add a specific call to have the info to go faster */
613 buf1 = buf;
614 while (n > 0) {
f58c7b35
TS
615 /* If the output image is being created as a copy on write image,
616 copy all sectors even the ones containing only NUL bytes,
93c65b47
AL
617 because they may differ from the sectors in the base image.
618
619 If the output is to a host device, we also write out
620 sectors that are entirely 0, since whatever data was
621 already there is garbage, not 0s. */
622 if (drv == &bdrv_host_device || out_baseimg ||
623 is_allocated_sectors(buf1, n, &n1)) {
5fafdf24 624 if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
ea2384d3
FB
625 error("error while writing");
626 }
627 sector_num += n1;
628 n -= n1;
629 buf1 += n1 * 512;
630 }
631 }
632 }
633 bdrv_delete(out_bs);
926c2d23
AZ
634 for (bs_i = 0; bs_i < bs_n; bs_i++)
635 bdrv_delete(bs[bs_i]);
636 free(bs);
ea2384d3
FB
637 return 0;
638}
639
57d1a2b6
FB
640#ifdef _WIN32
641static int64_t get_allocated_file_size(const char *filename)
642{
e8445331
FB
643 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
644 get_compressed_t get_compressed;
57d1a2b6 645 struct _stati64 st;
e8445331
FB
646
647 /* WinNT support GetCompressedFileSize to determine allocate size */
648 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
649 if (get_compressed) {
650 DWORD high, low;
651 low = get_compressed(filename, &high);
652 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
653 return (((int64_t) high) << 32) + low;
654 }
655
5fafdf24 656 if (_stati64(filename, &st) < 0)
57d1a2b6
FB
657 return -1;
658 return st.st_size;
659}
660#else
661static int64_t get_allocated_file_size(const char *filename)
662{
663 struct stat st;
5fafdf24 664 if (stat(filename, &st) < 0)
57d1a2b6
FB
665 return -1;
666 return (int64_t)st.st_blocks * 512;
667}
668#endif
669
faea38e7
FB
670static void dump_snapshots(BlockDriverState *bs)
671{
672 QEMUSnapshotInfo *sn_tab, *sn;
673 int nb_sns, i;
674 char buf[256];
675
676 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
677 if (nb_sns <= 0)
678 return;
679 printf("Snapshot list:\n");
680 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
681 for(i = 0; i < nb_sns; i++) {
682 sn = &sn_tab[i];
683 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
684 }
685 qemu_free(sn_tab);
686}
687
ea2384d3
FB
688static int img_info(int argc, char **argv)
689{
690 int c;
691 const char *filename, *fmt;
692 BlockDriver *drv;
693 BlockDriverState *bs;
694 char fmt_name[128], size_buf[128], dsize_buf[128];
96b8f136
TS
695 uint64_t total_sectors;
696 int64_t allocated_size;
93b6b2a3
FB
697 char backing_filename[1024];
698 char backing_filename2[1024];
faea38e7 699 BlockDriverInfo bdi;
ea2384d3
FB
700
701 fmt = NULL;
702 for(;;) {
703 c = getopt(argc, argv, "f:h");
704 if (c == -1)
705 break;
706 switch(c) {
707 case 'h':
708 help();
709 break;
710 case 'f':
711 fmt = optarg;
712 break;
713 }
714 }
5fafdf24 715 if (optind >= argc)
ea2384d3
FB
716 help();
717 filename = argv[optind++];
718
719 bs = bdrv_new("");
720 if (!bs)
721 error("Not enough memory");
722 if (fmt) {
723 drv = bdrv_find_format(fmt);
724 if (!drv)
725 error("Unknown file format '%s'", fmt);
726 } else {
727 drv = NULL;
728 }
137519ce 729 if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
ea2384d3
FB
730 error("Could not open '%s'", filename);
731 }
732 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
733 bdrv_get_geometry(bs, &total_sectors);
734 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
57d1a2b6
FB
735 allocated_size = get_allocated_file_size(filename);
736 if (allocated_size < 0)
a10ea30b 737 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
de167e41 738 else
5fafdf24 739 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
de167e41 740 allocated_size);
ea2384d3
FB
741 printf("image: %s\n"
742 "file format: %s\n"
ec3757de 743 "virtual size: %s (%" PRId64 " bytes)\n"
ea2384d3 744 "disk size: %s\n",
5fafdf24 745 filename, fmt_name, size_buf,
ec3757de 746 (total_sectors * 512),
ea2384d3
FB
747 dsize_buf);
748 if (bdrv_is_encrypted(bs))
749 printf("encrypted: yes\n");
faea38e7 750 if (bdrv_get_info(bs, &bdi) >= 0) {
5fafdf24 751 if (bdi.cluster_size != 0)
faea38e7
FB
752 printf("cluster_size: %d\n", bdi.cluster_size);
753 }
93b6b2a3 754 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
faea38e7 755 if (backing_filename[0] != '\0') {
93b6b2a3
FB
756 path_combine(backing_filename2, sizeof(backing_filename2),
757 filename, backing_filename);
5fafdf24 758 printf("backing file: %s (actual path: %s)\n",
93b6b2a3
FB
759 backing_filename,
760 backing_filename2);
faea38e7
FB
761 }
762 dump_snapshots(bs);
ea2384d3
FB
763 bdrv_delete(bs);
764 return 0;
765}
766
f7b4a940
AL
767#define SNAPSHOT_LIST 1
768#define SNAPSHOT_CREATE 2
769#define SNAPSHOT_APPLY 3
770#define SNAPSHOT_DELETE 4
771
772static void img_snapshot(int argc, char **argv)
773{
774 BlockDriverState *bs;
775 QEMUSnapshotInfo sn;
776 char *filename, *snapshot_name = NULL;
40a4539e 777 int c, ret;
f7b4a940
AL
778 int action = 0;
779 qemu_timeval tv;
780
781 /* Parse commandline parameters */
782 for(;;) {
783 c = getopt(argc, argv, "la:c:d:h");
784 if (c == -1)
785 break;
786 switch(c) {
787 case 'h':
788 help();
789 return;
790 case 'l':
791 if (action) {
792 help();
793 return;
794 }
795 action = SNAPSHOT_LIST;
796 break;
797 case 'a':
798 if (action) {
799 help();
800 return;
801 }
802 action = SNAPSHOT_APPLY;
803 snapshot_name = optarg;
804 break;
805 case 'c':
806 if (action) {
807 help();
808 return;
809 }
810 action = SNAPSHOT_CREATE;
811 snapshot_name = optarg;
812 break;
813 case 'd':
814 if (action) {
815 help();
816 return;
817 }
818 action = SNAPSHOT_DELETE;
819 snapshot_name = optarg;
820 break;
821 }
822 }
823
824 if (optind >= argc)
825 help();
826 filename = argv[optind++];
827
828 /* Open the image */
829 bs = bdrv_new("");
830 if (!bs)
831 error("Not enough memory");
832
833 if (bdrv_open2(bs, filename, 0, NULL) < 0) {
834 error("Could not open '%s'", filename);
835 }
836
837 /* Perform the requested action */
838 switch(action) {
839 case SNAPSHOT_LIST:
840 dump_snapshots(bs);
841 break;
842
843 case SNAPSHOT_CREATE:
844 memset(&sn, 0, sizeof(sn));
845 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
846
847 qemu_gettimeofday(&tv);
848 sn.date_sec = tv.tv_sec;
849 sn.date_nsec = tv.tv_usec * 1000;
850
851 ret = bdrv_snapshot_create(bs, &sn);
852 if (ret)
853 error("Could not create snapshot '%s': %d (%s)",
854 snapshot_name, ret, strerror(-ret));
855 break;
856
857 case SNAPSHOT_APPLY:
858 ret = bdrv_snapshot_goto(bs, snapshot_name);
859 if (ret)
860 error("Could not apply snapshot '%s': %d (%s)",
861 snapshot_name, ret, strerror(-ret));
862 break;
863
864 case SNAPSHOT_DELETE:
865 ret = bdrv_snapshot_delete(bs, snapshot_name);
866 if (ret)
867 error("Could not delete snapshot '%s': %d (%s)",
868 snapshot_name, ret, strerror(-ret));
869 break;
870 }
871
872 /* Cleanup */
873 bdrv_delete(bs);
874}
875
ea2384d3
FB
876int main(int argc, char **argv)
877{
878 const char *cmd;
879
880 bdrv_init();
881 if (argc < 2)
882 help();
883 cmd = argv[1];
8f9b157e 884 argc--; argv++;
ea2384d3
FB
885 if (!strcmp(cmd, "create")) {
886 img_create(argc, argv);
887 } else if (!strcmp(cmd, "commit")) {
888 img_commit(argc, argv);
889 } else if (!strcmp(cmd, "convert")) {
890 img_convert(argc, argv);
891 } else if (!strcmp(cmd, "info")) {
892 img_info(argc, argv);
f7b4a940
AL
893 } else if (!strcmp(cmd, "snapshot")) {
894 img_snapshot(argc, argv);
ea2384d3
FB
895 } else {
896 help();
897 }
898 return 0;
899}