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