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