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