]> git.proxmox.com Git - qemu.git/blob - qemu-img.c
Fail if detecting an unknown option
[qemu.git] / qemu-img.c
1 /*
2 * QEMU disk image utility
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
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 "qemu-common.h"
25 #include "qemu-option.h"
26 #include "osdep.h"
27 #include "sysemu.h"
28 #include "block_int.h"
29 #include <stdio.h>
30
31 #ifdef _WIN32
32 #include <windows.h>
33 #endif
34
35 typedef struct img_cmd_t {
36 const char *name;
37 int (*handler)(int argc, char **argv);
38 } img_cmd_t;
39
40 /* Default to cache=writeback as data integrity is not important for qemu-tcg. */
41 #define BDRV_O_FLAGS BDRV_O_CACHE_WB
42
43 static void GCC_FMT_ATTR(1, 2) error(const char *fmt, ...)
44 {
45 va_list ap;
46 va_start(ap, fmt);
47 fprintf(stderr, "qemu-img: ");
48 vfprintf(stderr, fmt, ap);
49 fprintf(stderr, "\n");
50 va_end(ap);
51 }
52
53 static void format_print(void *opaque, const char *name)
54 {
55 printf(" %s", name);
56 }
57
58 /* Please keep in synch with qemu-img.texi */
59 static void help(void)
60 {
61 const char *help_msg =
62 "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
63 "usage: qemu-img command [command options]\n"
64 "QEMU disk image utility\n"
65 "\n"
66 "Command syntax:\n"
67 #define DEF(option, callback, arg_string) \
68 " " arg_string "\n"
69 #include "qemu-img-cmds.h"
70 #undef DEF
71 #undef GEN_DOCS
72 "\n"
73 "Command parameters:\n"
74 " 'filename' is a disk image filename\n"
75 " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
76 " 'size' is the disk image size in bytes. Optional suffixes\n"
77 " 'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
78 " and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
79 " 'output_filename' is the destination disk image filename\n"
80 " 'output_fmt' is the destination format\n"
81 " 'options' is a comma separated list of format specific options in a\n"
82 " name=value format. Use -o ? for an overview of the options supported by the\n"
83 " used format\n"
84 " '-c' indicates that target image must be compressed (qcow format only)\n"
85 " '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
86 " match exactly. The image doesn't need a working backing file before\n"
87 " rebasing in this case (useful for renaming the backing file)\n"
88 " '-h' with or without a command shows this help and lists the supported formats\n"
89 "\n"
90 "Parameters to snapshot subcommand:\n"
91 " 'snapshot' is the name of the snapshot to create, apply or delete\n"
92 " '-a' applies a snapshot (revert disk to saved state)\n"
93 " '-c' creates a snapshot\n"
94 " '-d' deletes a snapshot\n"
95 " '-l' lists all snapshots in the given image\n";
96
97 printf("%s\nSupported formats:", help_msg);
98 bdrv_iterate_format(format_print, NULL);
99 printf("\n");
100 exit(1);
101 }
102
103 #if defined(WIN32)
104 /* XXX: put correct support for win32 */
105 static int read_password(char *buf, int buf_size)
106 {
107 int c, i;
108 printf("Password: ");
109 fflush(stdout);
110 i = 0;
111 for(;;) {
112 c = getchar();
113 if (c == '\n')
114 break;
115 if (i < (buf_size - 1))
116 buf[i++] = c;
117 }
118 buf[i] = '\0';
119 return 0;
120 }
121
122 #else
123
124 #include <termios.h>
125
126 static struct termios oldtty;
127
128 static void term_exit(void)
129 {
130 tcsetattr (0, TCSANOW, &oldtty);
131 }
132
133 static void term_init(void)
134 {
135 struct termios tty;
136
137 tcgetattr (0, &tty);
138 oldtty = tty;
139
140 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
141 |INLCR|IGNCR|ICRNL|IXON);
142 tty.c_oflag |= OPOST;
143 tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
144 tty.c_cflag &= ~(CSIZE|PARENB);
145 tty.c_cflag |= CS8;
146 tty.c_cc[VMIN] = 1;
147 tty.c_cc[VTIME] = 0;
148
149 tcsetattr (0, TCSANOW, &tty);
150
151 atexit(term_exit);
152 }
153
154 static int read_password(char *buf, int buf_size)
155 {
156 uint8_t ch;
157 int i, ret;
158
159 printf("password: ");
160 fflush(stdout);
161 term_init();
162 i = 0;
163 for(;;) {
164 ret = read(0, &ch, 1);
165 if (ret == -1) {
166 if (errno == EAGAIN || errno == EINTR) {
167 continue;
168 } else {
169 ret = -1;
170 break;
171 }
172 } else if (ret == 0) {
173 ret = -1;
174 break;
175 } else {
176 if (ch == '\r') {
177 ret = 0;
178 break;
179 }
180 if (i < (buf_size - 1))
181 buf[i++] = ch;
182 }
183 }
184 term_exit();
185 buf[i] = '\0';
186 printf("\n");
187 return ret;
188 }
189 #endif
190
191 static int print_block_option_help(const char *filename, const char *fmt)
192 {
193 BlockDriver *drv, *proto_drv;
194 QEMUOptionParameter *create_options = NULL;
195
196 /* Find driver and parse its options */
197 drv = bdrv_find_format(fmt);
198 if (!drv) {
199 error("Unknown file format '%s'", fmt);
200 return 1;
201 }
202
203 proto_drv = bdrv_find_protocol(filename);
204 if (!proto_drv) {
205 error("Unknown protocol '%s'", filename);
206 return 1;
207 }
208
209 create_options = append_option_parameters(create_options,
210 drv->create_options);
211 create_options = append_option_parameters(create_options,
212 proto_drv->create_options);
213 print_option_help(create_options);
214 free_option_parameters(create_options);
215 return 0;
216 }
217
218 static BlockDriverState *bdrv_new_open(const char *filename,
219 const char *fmt,
220 int flags)
221 {
222 BlockDriverState *bs;
223 BlockDriver *drv;
224 char password[256];
225
226 bs = bdrv_new("");
227 if (!bs) {
228 error("Not enough memory");
229 goto fail;
230 }
231 if (fmt) {
232 drv = bdrv_find_format(fmt);
233 if (!drv) {
234 error("Unknown file format '%s'", fmt);
235 goto fail;
236 }
237 } else {
238 drv = NULL;
239 }
240 if (bdrv_open(bs, filename, flags, drv) < 0) {
241 error("Could not open '%s'", filename);
242 goto fail;
243 }
244 if (bdrv_is_encrypted(bs)) {
245 printf("Disk image '%s' is encrypted.\n", filename);
246 if (read_password(password, sizeof(password)) < 0) {
247 error("No password given");
248 goto fail;
249 }
250 if (bdrv_set_key(bs, password) < 0) {
251 error("invalid password");
252 goto fail;
253 }
254 }
255 return bs;
256 fail:
257 if (bs) {
258 bdrv_delete(bs);
259 }
260 return NULL;
261 }
262
263 static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
264 int flags, const char *base_filename, const char *base_fmt)
265 {
266 if (flags & BLOCK_FLAG_ENCRYPT) {
267 if (set_option_parameter(list, BLOCK_OPT_ENCRYPT, "on")) {
268 error("Encryption not supported for file format '%s'", fmt);
269 return -1;
270 }
271 }
272 if (flags & BLOCK_FLAG_COMPAT6) {
273 if (set_option_parameter(list, BLOCK_OPT_COMPAT6, "on")) {
274 error("VMDK version 6 not supported for file format '%s'", fmt);
275 return -1;
276 }
277 }
278
279 if (base_filename) {
280 if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
281 error("Backing file not supported for file format '%s'", fmt);
282 return -1;
283 }
284 }
285 if (base_fmt) {
286 if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
287 error("Backing file format not supported for file format '%s'", fmt);
288 return -1;
289 }
290 }
291 return 0;
292 }
293
294 static int img_create(int argc, char **argv)
295 {
296 int c, ret = 0, flags;
297 const char *fmt = "raw";
298 const char *base_fmt = NULL;
299 const char *filename;
300 const char *base_filename = NULL;
301 BlockDriver *drv, *proto_drv;
302 QEMUOptionParameter *param = NULL, *create_options = NULL;
303 char *options = NULL;
304
305 flags = 0;
306 for(;;) {
307 c = getopt(argc, argv, "F:b:f:he6o:");
308 if (c == -1) {
309 break;
310 }
311 switch(c) {
312 case '?':
313 case 'h':
314 help();
315 break;
316 case 'F':
317 base_fmt = optarg;
318 break;
319 case 'b':
320 base_filename = optarg;
321 break;
322 case 'f':
323 fmt = optarg;
324 break;
325 case 'e':
326 flags |= BLOCK_FLAG_ENCRYPT;
327 break;
328 case '6':
329 flags |= BLOCK_FLAG_COMPAT6;
330 break;
331 case 'o':
332 options = optarg;
333 break;
334 }
335 }
336
337 /* Get the filename */
338 if (optind >= argc) {
339 help();
340 }
341 filename = argv[optind++];
342
343 if (options && !strcmp(options, "?")) {
344 ret = print_block_option_help(filename, fmt);
345 goto out;
346 }
347
348 /* Find driver and parse its options */
349 drv = bdrv_find_format(fmt);
350 if (!drv) {
351 error("Unknown file format '%s'", fmt);
352 return 1;
353 }
354
355 proto_drv = bdrv_find_protocol(filename);
356 if (!proto_drv) {
357 error("Unknown protocol '%s'", filename);
358 return 1;
359 }
360
361 create_options = append_option_parameters(create_options,
362 drv->create_options);
363 create_options = append_option_parameters(create_options,
364 proto_drv->create_options);
365
366 /* Create parameter list with default values */
367 param = parse_option_parameters("", create_options, param);
368 set_option_parameter_int(param, BLOCK_OPT_SIZE, -1);
369
370 /* Parse -o options */
371 if (options) {
372 param = parse_option_parameters(options, create_options, param);
373 if (param == NULL) {
374 error("Invalid options for file format '%s'.", fmt);
375 ret = -1;
376 goto out;
377 }
378 }
379
380 /* Add size to parameters */
381 if (optind < argc) {
382 set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
383 }
384
385 /* Add old-style options to parameters */
386 ret = add_old_style_options(fmt, param, flags, base_filename, base_fmt);
387 if (ret < 0) {
388 goto out;
389 }
390
391 // The size for the image must always be specified, with one exception:
392 // If we are using a backing file, we can obtain the size from there
393 if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
394
395 QEMUOptionParameter *backing_file =
396 get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
397 QEMUOptionParameter *backing_fmt =
398 get_option_parameter(param, BLOCK_OPT_BACKING_FMT);
399
400 if (backing_file && backing_file->value.s) {
401 BlockDriverState *bs;
402 uint64_t size;
403 const char *fmt = NULL;
404 char buf[32];
405
406 if (backing_fmt && backing_fmt->value.s) {
407 if (bdrv_find_format(backing_fmt->value.s)) {
408 fmt = backing_fmt->value.s;
409 } else {
410 error("Unknown backing file format '%s'",
411 backing_fmt->value.s);
412 ret = -1;
413 goto out;
414 }
415 }
416
417 bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS);
418 if (!bs) {
419 ret = -1;
420 goto out;
421 }
422 bdrv_get_geometry(bs, &size);
423 size *= 512;
424 bdrv_delete(bs);
425
426 snprintf(buf, sizeof(buf), "%" PRId64, size);
427 set_option_parameter(param, BLOCK_OPT_SIZE, buf);
428 } else {
429 error("Image creation needs a size parameter");
430 ret = -1;
431 goto out;
432 }
433 }
434
435 printf("Formatting '%s', fmt=%s ", filename, fmt);
436 print_option_parameters(param);
437 puts("");
438
439 ret = bdrv_create(drv, filename, param);
440 free_option_parameters(create_options);
441 free_option_parameters(param);
442
443 if (ret < 0) {
444 if (ret == -ENOTSUP) {
445 error("Formatting or formatting option not supported for file format '%s'", fmt);
446 } else if (ret == -EFBIG) {
447 error("The image size is too large for file format '%s'", fmt);
448 } else {
449 error("%s: error while creating %s: %s", filename, fmt, strerror(-ret));
450 }
451 }
452 out:
453 if (ret) {
454 return 1;
455 }
456 return 0;
457 }
458
459 /*
460 * Checks an image for consistency. Exit codes:
461 *
462 * 0 - Check completed, image is good
463 * 1 - Check not completed because of internal errors
464 * 2 - Check completed, image is corrupted
465 * 3 - Check completed, image has leaked clusters, but is good otherwise
466 */
467 static int img_check(int argc, char **argv)
468 {
469 int c, ret;
470 const char *filename, *fmt;
471 BlockDriverState *bs;
472 BdrvCheckResult result;
473
474 fmt = NULL;
475 for(;;) {
476 c = getopt(argc, argv, "f:h");
477 if (c == -1) {
478 break;
479 }
480 switch(c) {
481 case '?':
482 case 'h':
483 help();
484 break;
485 case 'f':
486 fmt = optarg;
487 break;
488 }
489 }
490 if (optind >= argc) {
491 help();
492 }
493 filename = argv[optind++];
494
495 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS);
496 if (!bs) {
497 return 1;
498 }
499 ret = bdrv_check(bs, &result);
500
501 if (ret == -ENOTSUP) {
502 error("This image format does not support checks");
503 bdrv_delete(bs);
504 return 1;
505 }
506
507 if (!(result.corruptions || result.leaks || result.check_errors)) {
508 printf("No errors were found on the image.\n");
509 } else {
510 if (result.corruptions) {
511 printf("\n%d errors were found on the image.\n"
512 "Data may be corrupted, or further writes to the image "
513 "may corrupt it.\n",
514 result.corruptions);
515 }
516
517 if (result.leaks) {
518 printf("\n%d leaked clusters were found on the image.\n"
519 "This means waste of disk space, but no harm to data.\n",
520 result.leaks);
521 }
522
523 if (result.check_errors) {
524 printf("\n%d internal errors have occurred during the check.\n",
525 result.check_errors);
526 }
527 }
528
529 bdrv_delete(bs);
530
531 if (ret < 0 || result.check_errors) {
532 printf("\nAn error has occurred during the check: %s\n"
533 "The check is not complete and may have missed error.\n",
534 strerror(-ret));
535 return 1;
536 }
537
538 if (result.corruptions) {
539 return 2;
540 } else if (result.leaks) {
541 return 3;
542 } else {
543 return 0;
544 }
545 }
546
547 static int img_commit(int argc, char **argv)
548 {
549 int c, ret;
550 const char *filename, *fmt;
551 BlockDriverState *bs;
552
553 fmt = NULL;
554 for(;;) {
555 c = getopt(argc, argv, "f:h");
556 if (c == -1) {
557 break;
558 }
559 switch(c) {
560 case '?':
561 case 'h':
562 help();
563 break;
564 case 'f':
565 fmt = optarg;
566 break;
567 }
568 }
569 if (optind >= argc) {
570 help();
571 }
572 filename = argv[optind++];
573
574 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
575 if (!bs) {
576 return 1;
577 }
578 ret = bdrv_commit(bs);
579 switch(ret) {
580 case 0:
581 printf("Image committed.\n");
582 break;
583 case -ENOENT:
584 error("No disk inserted");
585 break;
586 case -EACCES:
587 error("Image is read-only");
588 break;
589 case -ENOTSUP:
590 error("Image is already committed");
591 break;
592 default:
593 error("Error while committing image");
594 break;
595 }
596
597 bdrv_delete(bs);
598 if (ret) {
599 return 1;
600 }
601 return 0;
602 }
603
604 static int is_not_zero(const uint8_t *sector, int len)
605 {
606 int i;
607 len >>= 2;
608 for(i = 0;i < len; i++) {
609 if (((uint32_t *)sector)[i] != 0)
610 return 1;
611 }
612 return 0;
613 }
614
615 /*
616 * Returns true iff the first sector pointed to by 'buf' contains at least
617 * a non-NUL byte.
618 *
619 * 'pnum' is set to the number of sectors (including and immediately following
620 * the first one) that are known to be in the same allocated/unallocated state.
621 */
622 static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
623 {
624 int v, i;
625
626 if (n <= 0) {
627 *pnum = 0;
628 return 0;
629 }
630 v = is_not_zero(buf, 512);
631 for(i = 1; i < n; i++) {
632 buf += 512;
633 if (v != is_not_zero(buf, 512))
634 break;
635 }
636 *pnum = i;
637 return v;
638 }
639
640 /*
641 * Compares two buffers sector by sector. Returns 0 if the first sector of both
642 * buffers matches, non-zero otherwise.
643 *
644 * pnum is set to the number of sectors (including and immediately following
645 * the first one) that are known to have the same comparison result
646 */
647 static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
648 int *pnum)
649 {
650 int res, i;
651
652 if (n <= 0) {
653 *pnum = 0;
654 return 0;
655 }
656
657 res = !!memcmp(buf1, buf2, 512);
658 for(i = 1; i < n; i++) {
659 buf1 += 512;
660 buf2 += 512;
661
662 if (!!memcmp(buf1, buf2, 512) != res) {
663 break;
664 }
665 }
666
667 *pnum = i;
668 return res;
669 }
670
671 #define IO_BUF_SIZE (2 * 1024 * 1024)
672
673 static int img_convert(int argc, char **argv)
674 {
675 int c, ret = 0, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
676 const char *fmt, *out_fmt, *out_baseimg, *out_filename;
677 BlockDriver *drv, *proto_drv;
678 BlockDriverState **bs = NULL, *out_bs = NULL;
679 int64_t total_sectors, nb_sectors, sector_num, bs_offset;
680 uint64_t bs_sectors;
681 uint8_t * buf = NULL;
682 const uint8_t *buf1;
683 BlockDriverInfo bdi;
684 QEMUOptionParameter *param = NULL, *create_options = NULL;
685 QEMUOptionParameter *out_baseimg_param;
686 char *options = NULL;
687 const char *snapshot_name = NULL;
688
689 fmt = NULL;
690 out_fmt = "raw";
691 out_baseimg = NULL;
692 flags = 0;
693 for(;;) {
694 c = getopt(argc, argv, "f:O:B:s:hce6o:");
695 if (c == -1) {
696 break;
697 }
698 switch(c) {
699 case '?':
700 case 'h':
701 help();
702 break;
703 case 'f':
704 fmt = optarg;
705 break;
706 case 'O':
707 out_fmt = optarg;
708 break;
709 case 'B':
710 out_baseimg = optarg;
711 break;
712 case 'c':
713 flags |= BLOCK_FLAG_COMPRESS;
714 break;
715 case 'e':
716 flags |= BLOCK_FLAG_ENCRYPT;
717 break;
718 case '6':
719 flags |= BLOCK_FLAG_COMPAT6;
720 break;
721 case 'o':
722 options = optarg;
723 break;
724 case 's':
725 snapshot_name = optarg;
726 break;
727 }
728 }
729
730 bs_n = argc - optind - 1;
731 if (bs_n < 1) {
732 help();
733 }
734
735 out_filename = argv[argc - 1];
736
737 if (options && !strcmp(options, "?")) {
738 ret = print_block_option_help(out_filename, out_fmt);
739 goto out;
740 }
741
742 if (bs_n > 1 && out_baseimg) {
743 error("-B makes no sense when concatenating multiple input images");
744 ret = -1;
745 goto out;
746 }
747
748 bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *));
749
750 total_sectors = 0;
751 for (bs_i = 0; bs_i < bs_n; bs_i++) {
752 bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
753 if (!bs[bs_i]) {
754 error("Could not open '%s'", argv[optind + bs_i]);
755 ret = -1;
756 goto out;
757 }
758 bdrv_get_geometry(bs[bs_i], &bs_sectors);
759 total_sectors += bs_sectors;
760 }
761
762 if (snapshot_name != NULL) {
763 if (bs_n > 1) {
764 error("No support for concatenating multiple snapshot\n");
765 ret = -1;
766 goto out;
767 }
768 if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
769 error("Failed to load snapshot\n");
770 ret = -1;
771 goto out;
772 }
773 }
774
775 /* Find driver and parse its options */
776 drv = bdrv_find_format(out_fmt);
777 if (!drv) {
778 error("Unknown file format '%s'", out_fmt);
779 ret = -1;
780 goto out;
781 }
782
783 proto_drv = bdrv_find_protocol(out_filename);
784 if (!proto_drv) {
785 error("Unknown protocol '%s'", out_filename);
786 ret = -1;
787 goto out;
788 }
789
790 create_options = append_option_parameters(create_options,
791 drv->create_options);
792 create_options = append_option_parameters(create_options,
793 proto_drv->create_options);
794
795 if (options) {
796 param = parse_option_parameters(options, create_options, param);
797 if (param == NULL) {
798 error("Invalid options for file format '%s'.", out_fmt);
799 ret = -1;
800 goto out;
801 }
802 } else {
803 param = parse_option_parameters("", create_options, param);
804 }
805
806 set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
807 ret = add_old_style_options(out_fmt, param, flags, out_baseimg, NULL);
808 if (ret < 0) {
809 goto out;
810 }
811
812 /* Get backing file name if -o backing_file was used */
813 out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
814 if (out_baseimg_param) {
815 out_baseimg = out_baseimg_param->value.s;
816 }
817
818 /* Check if compression is supported */
819 if (flags & BLOCK_FLAG_COMPRESS) {
820 QEMUOptionParameter *encryption =
821 get_option_parameter(param, BLOCK_OPT_ENCRYPT);
822
823 if (!drv->bdrv_write_compressed) {
824 error("Compression not supported for this file format");
825 ret = -1;
826 goto out;
827 }
828
829 if (encryption && encryption->value.n) {
830 error("Compression and encryption not supported at the same time");
831 ret = -1;
832 goto out;
833 }
834 }
835
836 /* Create the new image */
837 ret = bdrv_create(drv, out_filename, param);
838 if (ret < 0) {
839 if (ret == -ENOTSUP) {
840 error("Formatting not supported for file format '%s'", out_fmt);
841 } else if (ret == -EFBIG) {
842 error("The image size is too large for file format '%s'", out_fmt);
843 } else {
844 error("%s: error while converting %s: %s", out_filename, out_fmt, strerror(-ret));
845 }
846 goto out;
847 }
848
849 out_bs = bdrv_new_open(out_filename, out_fmt,
850 BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
851 if (!out_bs) {
852 ret = -1;
853 goto out;
854 }
855
856 bs_i = 0;
857 bs_offset = 0;
858 bdrv_get_geometry(bs[0], &bs_sectors);
859 buf = qemu_malloc(IO_BUF_SIZE);
860
861 if (flags & BLOCK_FLAG_COMPRESS) {
862 ret = bdrv_get_info(out_bs, &bdi);
863 if (ret < 0) {
864 error("could not get block driver info");
865 goto out;
866 }
867 cluster_size = bdi.cluster_size;
868 if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
869 error("invalid cluster size");
870 ret = -1;
871 goto out;
872 }
873 cluster_sectors = cluster_size >> 9;
874 sector_num = 0;
875 for(;;) {
876 int64_t bs_num;
877 int remainder;
878 uint8_t *buf2;
879
880 nb_sectors = total_sectors - sector_num;
881 if (nb_sectors <= 0)
882 break;
883 if (nb_sectors >= cluster_sectors)
884 n = cluster_sectors;
885 else
886 n = nb_sectors;
887
888 bs_num = sector_num - bs_offset;
889 assert (bs_num >= 0);
890 remainder = n;
891 buf2 = buf;
892 while (remainder > 0) {
893 int nlow;
894 while (bs_num == bs_sectors) {
895 bs_i++;
896 assert (bs_i < bs_n);
897 bs_offset += bs_sectors;
898 bdrv_get_geometry(bs[bs_i], &bs_sectors);
899 bs_num = 0;
900 /* printf("changing part: sector_num=%" PRId64 ", "
901 "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
902 "\n", sector_num, bs_i, bs_offset, bs_sectors); */
903 }
904 assert (bs_num < bs_sectors);
905
906 nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
907
908 ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
909 if (ret < 0) {
910 error("error while reading");
911 goto out;
912 }
913
914 buf2 += nlow * 512;
915 bs_num += nlow;
916
917 remainder -= nlow;
918 }
919 assert (remainder == 0);
920
921 if (n < cluster_sectors) {
922 memset(buf + n * 512, 0, cluster_size - n * 512);
923 }
924 if (is_not_zero(buf, cluster_size)) {
925 ret = bdrv_write_compressed(out_bs, sector_num, buf,
926 cluster_sectors);
927 if (ret != 0) {
928 error("error while compressing sector %" PRId64,
929 sector_num);
930 goto out;
931 }
932 }
933 sector_num += n;
934 }
935 /* signal EOF to align */
936 bdrv_write_compressed(out_bs, 0, NULL, 0);
937 } else {
938 int has_zero_init = bdrv_has_zero_init(out_bs);
939
940 sector_num = 0; // total number of sectors converted so far
941 for(;;) {
942 nb_sectors = total_sectors - sector_num;
943 if (nb_sectors <= 0) {
944 break;
945 }
946 if (nb_sectors >= (IO_BUF_SIZE / 512)) {
947 n = (IO_BUF_SIZE / 512);
948 } else {
949 n = nb_sectors;
950 }
951
952 while (sector_num - bs_offset >= bs_sectors) {
953 bs_i ++;
954 assert (bs_i < bs_n);
955 bs_offset += bs_sectors;
956 bdrv_get_geometry(bs[bs_i], &bs_sectors);
957 /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
958 "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
959 sector_num, bs_i, bs_offset, bs_sectors); */
960 }
961
962 if (n > bs_offset + bs_sectors - sector_num) {
963 n = bs_offset + bs_sectors - sector_num;
964 }
965
966 if (has_zero_init) {
967 /* If the output image is being created as a copy on write image,
968 assume that sectors which are unallocated in the input image
969 are present in both the output's and input's base images (no
970 need to copy them). */
971 if (out_baseimg) {
972 if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
973 n, &n1)) {
974 sector_num += n1;
975 continue;
976 }
977 /* The next 'n1' sectors are allocated in the input image. Copy
978 only those as they may be followed by unallocated sectors. */
979 n = n1;
980 }
981 } else {
982 n1 = n;
983 }
984
985 ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
986 if (ret < 0) {
987 error("error while reading");
988 goto out;
989 }
990 /* NOTE: at the same time we convert, we do not write zero
991 sectors to have a chance to compress the image. Ideally, we
992 should add a specific call to have the info to go faster */
993 buf1 = buf;
994 while (n > 0) {
995 /* If the output image is being created as a copy on write image,
996 copy all sectors even the ones containing only NUL bytes,
997 because they may differ from the sectors in the base image.
998
999 If the output is to a host device, we also write out
1000 sectors that are entirely 0, since whatever data was
1001 already there is garbage, not 0s. */
1002 if (!has_zero_init || out_baseimg ||
1003 is_allocated_sectors(buf1, n, &n1)) {
1004 ret = bdrv_write(out_bs, sector_num, buf1, n1);
1005 if (ret < 0) {
1006 error("error while writing");
1007 goto out;
1008 }
1009 }
1010 sector_num += n1;
1011 n -= n1;
1012 buf1 += n1 * 512;
1013 }
1014 }
1015 }
1016 out:
1017 free_option_parameters(create_options);
1018 free_option_parameters(param);
1019 qemu_free(buf);
1020 if (out_bs) {
1021 bdrv_delete(out_bs);
1022 }
1023 if (bs) {
1024 for (bs_i = 0; bs_i < bs_n; bs_i++) {
1025 if (bs[bs_i]) {
1026 bdrv_delete(bs[bs_i]);
1027 }
1028 }
1029 qemu_free(bs);
1030 }
1031 if (ret) {
1032 return 1;
1033 }
1034 return 0;
1035 }
1036
1037 #ifdef _WIN32
1038 static int64_t get_allocated_file_size(const char *filename)
1039 {
1040 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
1041 get_compressed_t get_compressed;
1042 struct _stati64 st;
1043
1044 /* WinNT support GetCompressedFileSize to determine allocate size */
1045 get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
1046 if (get_compressed) {
1047 DWORD high, low;
1048 low = get_compressed(filename, &high);
1049 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
1050 return (((int64_t) high) << 32) + low;
1051 }
1052
1053 if (_stati64(filename, &st) < 0)
1054 return -1;
1055 return st.st_size;
1056 }
1057 #else
1058 static int64_t get_allocated_file_size(const char *filename)
1059 {
1060 struct stat st;
1061 if (stat(filename, &st) < 0)
1062 return -1;
1063 return (int64_t)st.st_blocks * 512;
1064 }
1065 #endif
1066
1067 static void dump_snapshots(BlockDriverState *bs)
1068 {
1069 QEMUSnapshotInfo *sn_tab, *sn;
1070 int nb_sns, i;
1071 char buf[256];
1072
1073 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1074 if (nb_sns <= 0)
1075 return;
1076 printf("Snapshot list:\n");
1077 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
1078 for(i = 0; i < nb_sns; i++) {
1079 sn = &sn_tab[i];
1080 printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
1081 }
1082 qemu_free(sn_tab);
1083 }
1084
1085 static int img_info(int argc, char **argv)
1086 {
1087 int c;
1088 const char *filename, *fmt;
1089 BlockDriverState *bs;
1090 char fmt_name[128], size_buf[128], dsize_buf[128];
1091 uint64_t total_sectors;
1092 int64_t allocated_size;
1093 char backing_filename[1024];
1094 char backing_filename2[1024];
1095 BlockDriverInfo bdi;
1096
1097 fmt = NULL;
1098 for(;;) {
1099 c = getopt(argc, argv, "f:h");
1100 if (c == -1) {
1101 break;
1102 }
1103 switch(c) {
1104 case '?':
1105 case 'h':
1106 help();
1107 break;
1108 case 'f':
1109 fmt = optarg;
1110 break;
1111 }
1112 }
1113 if (optind >= argc) {
1114 help();
1115 }
1116 filename = argv[optind++];
1117
1118 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
1119 if (!bs) {
1120 return 1;
1121 }
1122 bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
1123 bdrv_get_geometry(bs, &total_sectors);
1124 get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
1125 allocated_size = get_allocated_file_size(filename);
1126 if (allocated_size < 0) {
1127 snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
1128 } else {
1129 get_human_readable_size(dsize_buf, sizeof(dsize_buf),
1130 allocated_size);
1131 }
1132 printf("image: %s\n"
1133 "file format: %s\n"
1134 "virtual size: %s (%" PRId64 " bytes)\n"
1135 "disk size: %s\n",
1136 filename, fmt_name, size_buf,
1137 (total_sectors * 512),
1138 dsize_buf);
1139 if (bdrv_is_encrypted(bs)) {
1140 printf("encrypted: yes\n");
1141 }
1142 if (bdrv_get_info(bs, &bdi) >= 0) {
1143 if (bdi.cluster_size != 0) {
1144 printf("cluster_size: %d\n", bdi.cluster_size);
1145 }
1146 }
1147 bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
1148 if (backing_filename[0] != '\0') {
1149 path_combine(backing_filename2, sizeof(backing_filename2),
1150 filename, backing_filename);
1151 printf("backing file: %s (actual path: %s)\n",
1152 backing_filename,
1153 backing_filename2);
1154 }
1155 dump_snapshots(bs);
1156 bdrv_delete(bs);
1157 return 0;
1158 }
1159
1160 #define SNAPSHOT_LIST 1
1161 #define SNAPSHOT_CREATE 2
1162 #define SNAPSHOT_APPLY 3
1163 #define SNAPSHOT_DELETE 4
1164
1165 static int img_snapshot(int argc, char **argv)
1166 {
1167 BlockDriverState *bs;
1168 QEMUSnapshotInfo sn;
1169 char *filename, *snapshot_name = NULL;
1170 int c, ret = 0, bdrv_oflags;
1171 int action = 0;
1172 qemu_timeval tv;
1173
1174 bdrv_oflags = BDRV_O_RDWR;
1175 /* Parse commandline parameters */
1176 for(;;) {
1177 c = getopt(argc, argv, "la:c:d:h");
1178 if (c == -1) {
1179 break;
1180 }
1181 switch(c) {
1182 case '?':
1183 case 'h':
1184 help();
1185 return 0;
1186 case 'l':
1187 if (action) {
1188 help();
1189 return 0;
1190 }
1191 action = SNAPSHOT_LIST;
1192 bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
1193 break;
1194 case 'a':
1195 if (action) {
1196 help();
1197 return 0;
1198 }
1199 action = SNAPSHOT_APPLY;
1200 snapshot_name = optarg;
1201 break;
1202 case 'c':
1203 if (action) {
1204 help();
1205 return 0;
1206 }
1207 action = SNAPSHOT_CREATE;
1208 snapshot_name = optarg;
1209 break;
1210 case 'd':
1211 if (action) {
1212 help();
1213 return 0;
1214 }
1215 action = SNAPSHOT_DELETE;
1216 snapshot_name = optarg;
1217 break;
1218 }
1219 }
1220
1221 if (optind >= argc) {
1222 help();
1223 }
1224 filename = argv[optind++];
1225
1226 /* Open the image */
1227 bs = bdrv_new_open(filename, NULL, bdrv_oflags);
1228 if (!bs) {
1229 return 1;
1230 }
1231
1232 /* Perform the requested action */
1233 switch(action) {
1234 case SNAPSHOT_LIST:
1235 dump_snapshots(bs);
1236 break;
1237
1238 case SNAPSHOT_CREATE:
1239 memset(&sn, 0, sizeof(sn));
1240 pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1241
1242 qemu_gettimeofday(&tv);
1243 sn.date_sec = tv.tv_sec;
1244 sn.date_nsec = tv.tv_usec * 1000;
1245
1246 ret = bdrv_snapshot_create(bs, &sn);
1247 if (ret) {
1248 error("Could not create snapshot '%s': %d (%s)",
1249 snapshot_name, ret, strerror(-ret));
1250 }
1251 break;
1252
1253 case SNAPSHOT_APPLY:
1254 ret = bdrv_snapshot_goto(bs, snapshot_name);
1255 if (ret) {
1256 error("Could not apply snapshot '%s': %d (%s)",
1257 snapshot_name, ret, strerror(-ret));
1258 }
1259 break;
1260
1261 case SNAPSHOT_DELETE:
1262 ret = bdrv_snapshot_delete(bs, snapshot_name);
1263 if (ret) {
1264 error("Could not delete snapshot '%s': %d (%s)",
1265 snapshot_name, ret, strerror(-ret));
1266 }
1267 break;
1268 }
1269
1270 /* Cleanup */
1271 bdrv_delete(bs);
1272 if (ret) {
1273 return 1;
1274 }
1275 return 0;
1276 }
1277
1278 static int img_rebase(int argc, char **argv)
1279 {
1280 BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
1281 BlockDriver *old_backing_drv, *new_backing_drv;
1282 char *filename;
1283 const char *fmt, *out_basefmt, *out_baseimg;
1284 int c, flags, ret;
1285 int unsafe = 0;
1286
1287 /* Parse commandline parameters */
1288 fmt = NULL;
1289 out_baseimg = NULL;
1290 out_basefmt = NULL;
1291
1292 for(;;) {
1293 c = getopt(argc, argv, "uhf:F:b:");
1294 if (c == -1) {
1295 break;
1296 }
1297 switch(c) {
1298 case '?':
1299 case 'h':
1300 help();
1301 return 0;
1302 case 'f':
1303 fmt = optarg;
1304 break;
1305 case 'F':
1306 out_basefmt = optarg;
1307 break;
1308 case 'b':
1309 out_baseimg = optarg;
1310 break;
1311 case 'u':
1312 unsafe = 1;
1313 break;
1314 }
1315 }
1316
1317 if ((optind >= argc) || !out_baseimg) {
1318 help();
1319 }
1320 filename = argv[optind++];
1321
1322 /*
1323 * Open the images.
1324 *
1325 * Ignore the old backing file for unsafe rebase in case we want to correct
1326 * the reference to a renamed or moved backing file.
1327 */
1328 flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
1329 bs = bdrv_new_open(filename, fmt, flags);
1330 if (!bs) {
1331 return 1;
1332 }
1333
1334 /* Find the right drivers for the backing files */
1335 old_backing_drv = NULL;
1336 new_backing_drv = NULL;
1337
1338 if (!unsafe && bs->backing_format[0] != '\0') {
1339 old_backing_drv = bdrv_find_format(bs->backing_format);
1340 if (old_backing_drv == NULL) {
1341 error("Invalid format name: '%s'", bs->backing_format);
1342 ret = -1;
1343 goto out;
1344 }
1345 }
1346
1347 if (out_basefmt != NULL) {
1348 new_backing_drv = bdrv_find_format(out_basefmt);
1349 if (new_backing_drv == NULL) {
1350 error("Invalid format name: '%s'", out_basefmt);
1351 ret = -1;
1352 goto out;
1353 }
1354 }
1355
1356 /* For safe rebasing we need to compare old and new backing file */
1357 if (unsafe) {
1358 /* Make the compiler happy */
1359 bs_old_backing = NULL;
1360 bs_new_backing = NULL;
1361 } else {
1362 char backing_name[1024];
1363
1364 bs_old_backing = bdrv_new("old_backing");
1365 bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
1366 ret = bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,
1367 old_backing_drv);
1368 if (ret) {
1369 error("Could not open old backing file '%s'", backing_name);
1370 goto out;
1371 }
1372
1373 bs_new_backing = bdrv_new("new_backing");
1374 ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS,
1375 new_backing_drv);
1376 if (ret) {
1377 error("Could not open new backing file '%s'", out_baseimg);
1378 goto out;
1379 }
1380 }
1381
1382 /*
1383 * Check each unallocated cluster in the COW file. If it is unallocated,
1384 * accesses go to the backing file. We must therefore compare this cluster
1385 * in the old and new backing file, and if they differ we need to copy it
1386 * from the old backing file into the COW file.
1387 *
1388 * If qemu-img crashes during this step, no harm is done. The content of
1389 * the image is the same as the original one at any time.
1390 */
1391 if (!unsafe) {
1392 uint64_t num_sectors;
1393 uint64_t sector;
1394 int n;
1395 uint8_t * buf_old;
1396 uint8_t * buf_new;
1397
1398 buf_old = qemu_malloc(IO_BUF_SIZE);
1399 buf_new = qemu_malloc(IO_BUF_SIZE);
1400
1401 bdrv_get_geometry(bs, &num_sectors);
1402
1403 for (sector = 0; sector < num_sectors; sector += n) {
1404
1405 /* How many sectors can we handle with the next read? */
1406 if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
1407 n = (IO_BUF_SIZE / 512);
1408 } else {
1409 n = num_sectors - sector;
1410 }
1411
1412 /* If the cluster is allocated, we don't need to take action */
1413 ret = bdrv_is_allocated(bs, sector, n, &n);
1414 if (ret) {
1415 continue;
1416 }
1417
1418 /* Read old and new backing file */
1419 ret = bdrv_read(bs_old_backing, sector, buf_old, n);
1420 if (ret < 0) {
1421 error("error while reading from old backing file");
1422 goto out;
1423 }
1424 ret = bdrv_read(bs_new_backing, sector, buf_new, n);
1425 if (ret < 0) {
1426 error("error while reading from new backing file");
1427 goto out;
1428 }
1429
1430 /* If they differ, we need to write to the COW file */
1431 uint64_t written = 0;
1432
1433 while (written < n) {
1434 int pnum;
1435
1436 if (compare_sectors(buf_old + written * 512,
1437 buf_new + written * 512, n - written, &pnum))
1438 {
1439 ret = bdrv_write(bs, sector + written,
1440 buf_old + written * 512, pnum);
1441 if (ret < 0) {
1442 error("Error while writing to COW image: %s",
1443 strerror(-ret));
1444 goto out;
1445 }
1446 }
1447
1448 written += pnum;
1449 }
1450 }
1451
1452 qemu_free(buf_old);
1453 qemu_free(buf_new);
1454 }
1455
1456 /*
1457 * Change the backing file. All clusters that are different from the old
1458 * backing file are overwritten in the COW file now, so the visible content
1459 * doesn't change when we switch the backing file.
1460 */
1461 ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
1462 if (ret == -ENOSPC) {
1463 error("Could not change the backing file to '%s': No space left in "
1464 "the file header", out_baseimg);
1465 } else if (ret < 0) {
1466 error("Could not change the backing file to '%s': %s",
1467 out_baseimg, strerror(-ret));
1468 }
1469
1470 /*
1471 * TODO At this point it is possible to check if any clusters that are
1472 * allocated in the COW file are the same in the backing file. If so, they
1473 * could be dropped from the COW file. Don't do this before switching the
1474 * backing file, in case of a crash this would lead to corruption.
1475 */
1476 out:
1477 /* Cleanup */
1478 if (!unsafe) {
1479 bdrv_delete(bs_old_backing);
1480 bdrv_delete(bs_new_backing);
1481 }
1482
1483 bdrv_delete(bs);
1484 if (ret) {
1485 return 1;
1486 }
1487 return 0;
1488 }
1489
1490 static int img_resize(int argc, char **argv)
1491 {
1492 int c, ret, relative;
1493 const char *filename, *fmt, *size;
1494 int64_t n, total_size;
1495 BlockDriverState *bs;
1496 QEMUOptionParameter *param;
1497 QEMUOptionParameter resize_options[] = {
1498 {
1499 .name = BLOCK_OPT_SIZE,
1500 .type = OPT_SIZE,
1501 .help = "Virtual disk size"
1502 },
1503 { NULL }
1504 };
1505
1506 fmt = NULL;
1507 for(;;) {
1508 c = getopt(argc, argv, "f:h");
1509 if (c == -1) {
1510 break;
1511 }
1512 switch(c) {
1513 case '?':
1514 case 'h':
1515 help();
1516 break;
1517 case 'f':
1518 fmt = optarg;
1519 break;
1520 }
1521 }
1522 if (optind + 1 >= argc) {
1523 help();
1524 }
1525 filename = argv[optind++];
1526 size = argv[optind++];
1527
1528 /* Choose grow, shrink, or absolute resize mode */
1529 switch (size[0]) {
1530 case '+':
1531 relative = 1;
1532 size++;
1533 break;
1534 case '-':
1535 relative = -1;
1536 size++;
1537 break;
1538 default:
1539 relative = 0;
1540 break;
1541 }
1542
1543 /* Parse size */
1544 param = parse_option_parameters("", resize_options, NULL);
1545 if (set_option_parameter(param, BLOCK_OPT_SIZE, size)) {
1546 /* Error message already printed when size parsing fails */
1547 exit(1);
1548 }
1549 n = get_option_parameter(param, BLOCK_OPT_SIZE)->value.n;
1550 free_option_parameters(param);
1551
1552 bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
1553 if (!bs) {
1554 return 1;
1555 }
1556
1557 if (relative) {
1558 total_size = bdrv_getlength(bs) + n * relative;
1559 } else {
1560 total_size = n;
1561 }
1562 if (total_size <= 0) {
1563 error("New image size must be positive");
1564 ret = -1;
1565 goto out;
1566 }
1567
1568 ret = bdrv_truncate(bs, total_size);
1569 switch (ret) {
1570 case 0:
1571 printf("Image resized.\n");
1572 break;
1573 case -ENOTSUP:
1574 error("This image format does not support resize");
1575 break;
1576 case -EACCES:
1577 error("Image is read-only");
1578 break;
1579 default:
1580 error("Error resizing image (%d)", -ret);
1581 break;
1582 }
1583 out:
1584 bdrv_delete(bs);
1585 if (ret) {
1586 return 1;
1587 }
1588 return 0;
1589 }
1590
1591 static const img_cmd_t img_cmds[] = {
1592 #define DEF(option, callback, arg_string) \
1593 { option, callback },
1594 #include "qemu-img-cmds.h"
1595 #undef DEF
1596 #undef GEN_DOCS
1597 { NULL, NULL, },
1598 };
1599
1600 int main(int argc, char **argv)
1601 {
1602 const img_cmd_t *cmd;
1603 const char *cmdname;
1604
1605 bdrv_init();
1606 if (argc < 2)
1607 help();
1608 cmdname = argv[1];
1609 argc--; argv++;
1610
1611 /* find the command */
1612 for(cmd = img_cmds; cmd->name != NULL; cmd++) {
1613 if (!strcmp(cmdname, cmd->name)) {
1614 return cmd->handler(argc, argv);
1615 }
1616 }
1617
1618 /* not found */
1619 help();
1620 return 0;
1621 }