Statistics
| Branch: | Revision:

root / qemu-img.c @ 6643e2f0

History | View | Annotate | Download (41.6 kB)

1 ea2384d3 bellard
/*
2 fb43f4dd bellard
 * QEMU disk image utility
3 5fafdf24 ths
 *
4 68d0f70e bellard
 * Copyright (c) 2003-2008 Fabrice Bellard
5 5fafdf24 ths
 *
6 ea2384d3 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 ea2384d3 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 ea2384d3 bellard
 * in the Software without restriction, including without limitation the rights
9 ea2384d3 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 ea2384d3 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 ea2384d3 bellard
 * furnished to do so, subject to the following conditions:
12 ea2384d3 bellard
 *
13 ea2384d3 bellard
 * The above copyright notice and this permission notice shall be included in
14 ea2384d3 bellard
 * all copies or substantial portions of the Software.
15 ea2384d3 bellard
 *
16 ea2384d3 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 ea2384d3 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 ea2384d3 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 ea2384d3 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 ea2384d3 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 ea2384d3 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 ea2384d3 bellard
 * THE SOFTWARE.
23 ea2384d3 bellard
 */
24 faf07963 pbrook
#include "qemu-common.h"
25 9ea2ea71 Kevin Wolf
#include "qemu-option.h"
26 53f76e58 Kevin Wolf
#include "qemu-error.h"
27 f7b4a940 aliguori
#include "osdep.h"
28 dc786bc9 Jes Sorensen
#include "sysemu.h"
29 ec36ba14 ths
#include "block_int.h"
30 9230eaf6 aliguori
#include <stdio.h>
31 ea2384d3 bellard
32 e8445331 bellard
#ifdef _WIN32
33 e8445331 bellard
#include <windows.h>
34 e8445331 bellard
#endif
35 e8445331 bellard
36 c227f099 Anthony Liguori
typedef struct img_cmd_t {
37 153859be Stuart Brady
    const char *name;
38 153859be Stuart Brady
    int (*handler)(int argc, char **argv);
39 c227f099 Anthony Liguori
} img_cmd_t;
40 153859be Stuart Brady
41 137519ce aurel32
/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
42 adfe078e Stefan Hajnoczi
#define BDRV_O_FLAGS BDRV_O_CACHE_WB
43 137519ce aurel32
44 ea2384d3 bellard
static void format_print(void *opaque, const char *name)
45 ea2384d3 bellard
{
46 ea2384d3 bellard
    printf(" %s", name);
47 ea2384d3 bellard
}
48 ea2384d3 bellard
49 d2c639d6 blueswir1
/* Please keep in synch with qemu-img.texi */
50 3f379ab1 pbrook
static void help(void)
51 ea2384d3 bellard
{
52 e00291c0 Paolo Bonzini
    const char *help_msg =
53 e00291c0 Paolo Bonzini
           "qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
54 3f020d70 malc
           "usage: qemu-img command [command options]\n"
55 3f020d70 malc
           "QEMU disk image utility\n"
56 3f020d70 malc
           "\n"
57 3f020d70 malc
           "Command syntax:\n"
58 153859be Stuart Brady
#define DEF(option, callback, arg_string)        \
59 153859be Stuart Brady
           "  " arg_string "\n"
60 153859be Stuart Brady
#include "qemu-img-cmds.h"
61 153859be Stuart Brady
#undef DEF
62 153859be Stuart Brady
#undef GEN_DOCS
63 3f020d70 malc
           "\n"
64 3f020d70 malc
           "Command parameters:\n"
65 3f020d70 malc
           "  'filename' is a disk image filename\n"
66 3f020d70 malc
           "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
67 3f020d70 malc
           "  'size' is the disk image size in bytes. Optional suffixes\n"
68 3f020d70 malc
           "    'k' or 'K' (kilobyte, 1024), 'M' (megabyte, 1024k), 'G' (gigabyte, 1024M)\n"
69 3f020d70 malc
           "    and T (terabyte, 1024G) are supported. 'b' is ignored.\n"
70 3f020d70 malc
           "  'output_filename' is the destination disk image filename\n"
71 3f020d70 malc
           "  'output_fmt' is the destination format\n"
72 3f020d70 malc
           "  'options' is a comma separated list of format specific options in a\n"
73 3f020d70 malc
           "    name=value format. Use -o ? for an overview of the options supported by the\n"
74 3f020d70 malc
           "    used format\n"
75 3f020d70 malc
           "  '-c' indicates that target image must be compressed (qcow format only)\n"
76 3f020d70 malc
           "  '-u' enables unsafe rebasing. It is assumed that old and new backing file\n"
77 3f020d70 malc
           "       match exactly. The image doesn't need a working backing file before\n"
78 3f020d70 malc
           "       rebasing in this case (useful for renaming the backing file)\n"
79 3f020d70 malc
           "  '-h' with or without a command shows this help and lists the supported formats\n"
80 3f020d70 malc
           "\n"
81 3f020d70 malc
           "Parameters to snapshot subcommand:\n"
82 3f020d70 malc
           "  'snapshot' is the name of the snapshot to create, apply or delete\n"
83 3f020d70 malc
           "  '-a' applies a snapshot (revert disk to saved state)\n"
84 3f020d70 malc
           "  '-c' creates a snapshot\n"
85 3f020d70 malc
           "  '-d' deletes a snapshot\n"
86 e00291c0 Paolo Bonzini
           "  '-l' lists all snapshots in the given image\n";
87 e00291c0 Paolo Bonzini
88 e00291c0 Paolo Bonzini
    printf("%s\nSupported formats:", help_msg);
89 ea2384d3 bellard
    bdrv_iterate_format(format_print, NULL);
90 ea2384d3 bellard
    printf("\n");
91 ea2384d3 bellard
    exit(1);
92 ea2384d3 bellard
}
93 ea2384d3 bellard
94 ea2384d3 bellard
#if defined(WIN32)
95 ea2384d3 bellard
/* XXX: put correct support for win32 */
96 ea2384d3 bellard
static int read_password(char *buf, int buf_size)
97 ea2384d3 bellard
{
98 ea2384d3 bellard
    int c, i;
99 ea2384d3 bellard
    printf("Password: ");
100 ea2384d3 bellard
    fflush(stdout);
101 ea2384d3 bellard
    i = 0;
102 ea2384d3 bellard
    for(;;) {
103 ea2384d3 bellard
        c = getchar();
104 ea2384d3 bellard
        if (c == '\n')
105 ea2384d3 bellard
            break;
106 ea2384d3 bellard
        if (i < (buf_size - 1))
107 ea2384d3 bellard
            buf[i++] = c;
108 ea2384d3 bellard
    }
109 ea2384d3 bellard
    buf[i] = '\0';
110 ea2384d3 bellard
    return 0;
111 ea2384d3 bellard
}
112 ea2384d3 bellard
113 ea2384d3 bellard
#else
114 ea2384d3 bellard
115 ea2384d3 bellard
#include <termios.h>
116 ea2384d3 bellard
117 ea2384d3 bellard
static struct termios oldtty;
118 ea2384d3 bellard
119 ea2384d3 bellard
static void term_exit(void)
120 ea2384d3 bellard
{
121 ea2384d3 bellard
    tcsetattr (0, TCSANOW, &oldtty);
122 ea2384d3 bellard
}
123 ea2384d3 bellard
124 ea2384d3 bellard
static void term_init(void)
125 ea2384d3 bellard
{
126 ea2384d3 bellard
    struct termios tty;
127 ea2384d3 bellard
128 ea2384d3 bellard
    tcgetattr (0, &tty);
129 ea2384d3 bellard
    oldtty = tty;
130 ea2384d3 bellard
131 ea2384d3 bellard
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
132 ea2384d3 bellard
                          |INLCR|IGNCR|ICRNL|IXON);
133 ea2384d3 bellard
    tty.c_oflag |= OPOST;
134 ea2384d3 bellard
    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
135 ea2384d3 bellard
    tty.c_cflag &= ~(CSIZE|PARENB);
136 ea2384d3 bellard
    tty.c_cflag |= CS8;
137 ea2384d3 bellard
    tty.c_cc[VMIN] = 1;
138 ea2384d3 bellard
    tty.c_cc[VTIME] = 0;
139 3b46e624 ths
140 ea2384d3 bellard
    tcsetattr (0, TCSANOW, &tty);
141 ea2384d3 bellard
142 ea2384d3 bellard
    atexit(term_exit);
143 ea2384d3 bellard
}
144 ea2384d3 bellard
145 3f379ab1 pbrook
static int read_password(char *buf, int buf_size)
146 ea2384d3 bellard
{
147 ea2384d3 bellard
    uint8_t ch;
148 ea2384d3 bellard
    int i, ret;
149 ea2384d3 bellard
150 ea2384d3 bellard
    printf("password: ");
151 ea2384d3 bellard
    fflush(stdout);
152 ea2384d3 bellard
    term_init();
153 ea2384d3 bellard
    i = 0;
154 ea2384d3 bellard
    for(;;) {
155 ea2384d3 bellard
        ret = read(0, &ch, 1);
156 ea2384d3 bellard
        if (ret == -1) {
157 ea2384d3 bellard
            if (errno == EAGAIN || errno == EINTR) {
158 ea2384d3 bellard
                continue;
159 ea2384d3 bellard
            } else {
160 ea2384d3 bellard
                ret = -1;
161 ea2384d3 bellard
                break;
162 ea2384d3 bellard
            }
163 ea2384d3 bellard
        } else if (ret == 0) {
164 ea2384d3 bellard
            ret = -1;
165 ea2384d3 bellard
            break;
166 ea2384d3 bellard
        } else {
167 ea2384d3 bellard
            if (ch == '\r') {
168 ea2384d3 bellard
                ret = 0;
169 ea2384d3 bellard
                break;
170 ea2384d3 bellard
            }
171 ea2384d3 bellard
            if (i < (buf_size - 1))
172 ea2384d3 bellard
                buf[i++] = ch;
173 ea2384d3 bellard
        }
174 ea2384d3 bellard
    }
175 ea2384d3 bellard
    term_exit();
176 ea2384d3 bellard
    buf[i] = '\0';
177 ea2384d3 bellard
    printf("\n");
178 ea2384d3 bellard
    return ret;
179 ea2384d3 bellard
}
180 ea2384d3 bellard
#endif
181 ea2384d3 bellard
182 4ac8aacd Jes Sorensen
static int print_block_option_help(const char *filename, const char *fmt)
183 4ac8aacd Jes Sorensen
{
184 4ac8aacd Jes Sorensen
    BlockDriver *drv, *proto_drv;
185 4ac8aacd Jes Sorensen
    QEMUOptionParameter *create_options = NULL;
186 4ac8aacd Jes Sorensen
187 4ac8aacd Jes Sorensen
    /* Find driver and parse its options */
188 4ac8aacd Jes Sorensen
    drv = bdrv_find_format(fmt);
189 4ac8aacd Jes Sorensen
    if (!drv) {
190 15654a6d Jes Sorensen
        error_report("Unknown file format '%s'", fmt);
191 4ac8aacd Jes Sorensen
        return 1;
192 4ac8aacd Jes Sorensen
    }
193 4ac8aacd Jes Sorensen
194 4ac8aacd Jes Sorensen
    proto_drv = bdrv_find_protocol(filename);
195 4ac8aacd Jes Sorensen
    if (!proto_drv) {
196 15654a6d Jes Sorensen
        error_report("Unknown protocol '%s'", filename);
197 4ac8aacd Jes Sorensen
        return 1;
198 4ac8aacd Jes Sorensen
    }
199 4ac8aacd Jes Sorensen
200 4ac8aacd Jes Sorensen
    create_options = append_option_parameters(create_options,
201 4ac8aacd Jes Sorensen
                                              drv->create_options);
202 4ac8aacd Jes Sorensen
    create_options = append_option_parameters(create_options,
203 4ac8aacd Jes Sorensen
                                              proto_drv->create_options);
204 4ac8aacd Jes Sorensen
    print_option_help(create_options);
205 4ac8aacd Jes Sorensen
    free_option_parameters(create_options);
206 4ac8aacd Jes Sorensen
    return 0;
207 4ac8aacd Jes Sorensen
}
208 4ac8aacd Jes Sorensen
209 75c23805 bellard
static BlockDriverState *bdrv_new_open(const char *filename,
210 9bc378c1 Sheng Yang
                                       const char *fmt,
211 f163d073 Stefan Hajnoczi
                                       int flags)
212 75c23805 bellard
{
213 75c23805 bellard
    BlockDriverState *bs;
214 75c23805 bellard
    BlockDriver *drv;
215 75c23805 bellard
    char password[256];
216 75c23805 bellard
217 75c23805 bellard
    bs = bdrv_new("");
218 ad717139 Kevin Wolf
219 75c23805 bellard
    if (fmt) {
220 75c23805 bellard
        drv = bdrv_find_format(fmt);
221 c2abccec MORITA Kazutaka
        if (!drv) {
222 15654a6d Jes Sorensen
            error_report("Unknown file format '%s'", fmt);
223 c2abccec MORITA Kazutaka
            goto fail;
224 c2abccec MORITA Kazutaka
        }
225 75c23805 bellard
    } else {
226 75c23805 bellard
        drv = NULL;
227 75c23805 bellard
    }
228 d6e9098e Kevin Wolf
    if (bdrv_open(bs, filename, flags, drv) < 0) {
229 15654a6d Jes Sorensen
        error_report("Could not open '%s'", filename);
230 c2abccec MORITA Kazutaka
        goto fail;
231 75c23805 bellard
    }
232 75c23805 bellard
    if (bdrv_is_encrypted(bs)) {
233 75c23805 bellard
        printf("Disk image '%s' is encrypted.\n", filename);
234 c2abccec MORITA Kazutaka
        if (read_password(password, sizeof(password)) < 0) {
235 15654a6d Jes Sorensen
            error_report("No password given");
236 c2abccec MORITA Kazutaka
            goto fail;
237 c2abccec MORITA Kazutaka
        }
238 c2abccec MORITA Kazutaka
        if (bdrv_set_key(bs, password) < 0) {
239 15654a6d Jes Sorensen
            error_report("invalid password");
240 c2abccec MORITA Kazutaka
            goto fail;
241 c2abccec MORITA Kazutaka
        }
242 75c23805 bellard
    }
243 75c23805 bellard
    return bs;
244 c2abccec MORITA Kazutaka
fail:
245 c2abccec MORITA Kazutaka
    if (bs) {
246 c2abccec MORITA Kazutaka
        bdrv_delete(bs);
247 c2abccec MORITA Kazutaka
    }
248 c2abccec MORITA Kazutaka
    return NULL;
249 75c23805 bellard
}
250 75c23805 bellard
251 c2abccec MORITA Kazutaka
static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
252 eec77d9e Jes Sorensen
                                 const char *base_filename,
253 eec77d9e Jes Sorensen
                                 const char *base_fmt)
254 efa84d43 Kevin Wolf
{
255 efa84d43 Kevin Wolf
    if (base_filename) {
256 efa84d43 Kevin Wolf
        if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
257 15654a6d Jes Sorensen
            error_report("Backing file not supported for file format '%s'",
258 15654a6d Jes Sorensen
                         fmt);
259 c2abccec MORITA Kazutaka
            return -1;
260 efa84d43 Kevin Wolf
        }
261 efa84d43 Kevin Wolf
    }
262 efa84d43 Kevin Wolf
    if (base_fmt) {
263 efa84d43 Kevin Wolf
        if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
264 15654a6d Jes Sorensen
            error_report("Backing file format not supported for file "
265 15654a6d Jes Sorensen
                         "format '%s'", fmt);
266 c2abccec MORITA Kazutaka
            return -1;
267 efa84d43 Kevin Wolf
        }
268 efa84d43 Kevin Wolf
    }
269 c2abccec MORITA Kazutaka
    return 0;
270 efa84d43 Kevin Wolf
}
271 efa84d43 Kevin Wolf
272 ea2384d3 bellard
static int img_create(int argc, char **argv)
273 ea2384d3 bellard
{
274 eec77d9e Jes Sorensen
    int c, ret = 0;
275 1da7cfbd Jes Sorensen
    uint64_t img_size = -1;
276 ea2384d3 bellard
    const char *fmt = "raw";
277 9230eaf6 aliguori
    const char *base_fmt = NULL;
278 ea2384d3 bellard
    const char *filename;
279 ea2384d3 bellard
    const char *base_filename = NULL;
280 9ea2ea71 Kevin Wolf
    char *options = NULL;
281 3b46e624 ths
282 ea2384d3 bellard
    for(;;) {
283 9ea2ea71 Kevin Wolf
        c = getopt(argc, argv, "F:b:f:he6o:");
284 b8fb60da Jes Sorensen
        if (c == -1) {
285 ea2384d3 bellard
            break;
286 b8fb60da Jes Sorensen
        }
287 ea2384d3 bellard
        switch(c) {
288 ef87394c Jes Sorensen
        case '?':
289 ea2384d3 bellard
        case 'h':
290 ea2384d3 bellard
            help();
291 ea2384d3 bellard
            break;
292 9230eaf6 aliguori
        case 'F':
293 9230eaf6 aliguori
            base_fmt = optarg;
294 9230eaf6 aliguori
            break;
295 ea2384d3 bellard
        case 'b':
296 ea2384d3 bellard
            base_filename = optarg;
297 ea2384d3 bellard
            break;
298 ea2384d3 bellard
        case 'f':
299 ea2384d3 bellard
            fmt = optarg;
300 ea2384d3 bellard
            break;
301 ea2384d3 bellard
        case 'e':
302 15654a6d Jes Sorensen
            error_report("qemu-img: option -e is deprecated, please use \'-o "
303 eec77d9e Jes Sorensen
                  "encryption\' instead!");
304 eec77d9e Jes Sorensen
            return 1;
305 d8871c5a ths
        case '6':
306 15654a6d Jes Sorensen
            error_report("qemu-img: option -6 is deprecated, please use \'-o "
307 eec77d9e Jes Sorensen
                  "compat6\' instead!");
308 eec77d9e Jes Sorensen
            return 1;
309 9ea2ea71 Kevin Wolf
        case 'o':
310 9ea2ea71 Kevin Wolf
            options = optarg;
311 9ea2ea71 Kevin Wolf
            break;
312 ea2384d3 bellard
        }
313 ea2384d3 bellard
    }
314 9230eaf6 aliguori
315 b50cbabc MORITA Kazutaka
    /* Get the filename */
316 b8fb60da Jes Sorensen
    if (optind >= argc) {
317 b50cbabc MORITA Kazutaka
        help();
318 b8fb60da Jes Sorensen
    }
319 b50cbabc MORITA Kazutaka
    filename = argv[optind++];
320 b50cbabc MORITA Kazutaka
321 1da7cfbd Jes Sorensen
    /* Get image size, if specified */
322 1da7cfbd Jes Sorensen
    if (optind < argc) {
323 1da7cfbd Jes Sorensen
        ssize_t sval;
324 1da7cfbd Jes Sorensen
        sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);
325 1da7cfbd Jes Sorensen
        if (sval < 0) {
326 15654a6d Jes Sorensen
            error_report("Invalid image size specified! You may use k, M, G or "
327 1da7cfbd Jes Sorensen
                  "T suffixes for ");
328 15654a6d Jes Sorensen
            error_report("kilobytes, megabytes, gigabytes and terabytes.");
329 1da7cfbd Jes Sorensen
            ret = -1;
330 1da7cfbd Jes Sorensen
            goto out;
331 1da7cfbd Jes Sorensen
        }
332 1da7cfbd Jes Sorensen
        img_size = (uint64_t)sval;
333 1da7cfbd Jes Sorensen
    }
334 1da7cfbd Jes Sorensen
335 4ac8aacd Jes Sorensen
    if (options && !strcmp(options, "?")) {
336 4ac8aacd Jes Sorensen
        ret = print_block_option_help(filename, fmt);
337 4ac8aacd Jes Sorensen
        goto out;
338 4ac8aacd Jes Sorensen
    }
339 4ac8aacd Jes Sorensen
340 f88e1a42 Jes Sorensen
    ret = bdrv_img_create(filename, fmt, base_filename, base_fmt,
341 f88e1a42 Jes Sorensen
                          options, img_size, BDRV_O_FLAGS);
342 c2abccec MORITA Kazutaka
out:
343 c2abccec MORITA Kazutaka
    if (ret) {
344 c2abccec MORITA Kazutaka
        return 1;
345 c2abccec MORITA Kazutaka
    }
346 ea2384d3 bellard
    return 0;
347 ea2384d3 bellard
}
348 ea2384d3 bellard
349 e076f338 Kevin Wolf
/*
350 e076f338 Kevin Wolf
 * Checks an image for consistency. Exit codes:
351 e076f338 Kevin Wolf
 *
352 e076f338 Kevin Wolf
 * 0 - Check completed, image is good
353 e076f338 Kevin Wolf
 * 1 - Check not completed because of internal errors
354 e076f338 Kevin Wolf
 * 2 - Check completed, image is corrupted
355 e076f338 Kevin Wolf
 * 3 - Check completed, image has leaked clusters, but is good otherwise
356 e076f338 Kevin Wolf
 */
357 1585969c aliguori
static int img_check(int argc, char **argv)
358 1585969c aliguori
{
359 1585969c aliguori
    int c, ret;
360 1585969c aliguori
    const char *filename, *fmt;
361 1585969c aliguori
    BlockDriverState *bs;
362 e076f338 Kevin Wolf
    BdrvCheckResult result;
363 1585969c aliguori
364 1585969c aliguori
    fmt = NULL;
365 1585969c aliguori
    for(;;) {
366 1585969c aliguori
        c = getopt(argc, argv, "f:h");
367 b8fb60da Jes Sorensen
        if (c == -1) {
368 1585969c aliguori
            break;
369 b8fb60da Jes Sorensen
        }
370 1585969c aliguori
        switch(c) {
371 ef87394c Jes Sorensen
        case '?':
372 1585969c aliguori
        case 'h':
373 1585969c aliguori
            help();
374 1585969c aliguori
            break;
375 1585969c aliguori
        case 'f':
376 1585969c aliguori
            fmt = optarg;
377 1585969c aliguori
            break;
378 1585969c aliguori
        }
379 1585969c aliguori
    }
380 b8fb60da Jes Sorensen
    if (optind >= argc) {
381 1585969c aliguori
        help();
382 b8fb60da Jes Sorensen
    }
383 1585969c aliguori
    filename = argv[optind++];
384 1585969c aliguori
385 adfe078e Stefan Hajnoczi
    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS);
386 c2abccec MORITA Kazutaka
    if (!bs) {
387 c2abccec MORITA Kazutaka
        return 1;
388 c2abccec MORITA Kazutaka
    }
389 e076f338 Kevin Wolf
    ret = bdrv_check(bs, &result);
390 e076f338 Kevin Wolf
391 e076f338 Kevin Wolf
    if (ret == -ENOTSUP) {
392 15654a6d Jes Sorensen
        error_report("This image format does not support checks");
393 e076f338 Kevin Wolf
        bdrv_delete(bs);
394 e076f338 Kevin Wolf
        return 1;
395 e076f338 Kevin Wolf
    }
396 e076f338 Kevin Wolf
397 e076f338 Kevin Wolf
    if (!(result.corruptions || result.leaks || result.check_errors)) {
398 e076f338 Kevin Wolf
        printf("No errors were found on the image.\n");
399 e076f338 Kevin Wolf
    } else {
400 e076f338 Kevin Wolf
        if (result.corruptions) {
401 e076f338 Kevin Wolf
            printf("\n%d errors were found on the image.\n"
402 e076f338 Kevin Wolf
                "Data may be corrupted, or further writes to the image "
403 e076f338 Kevin Wolf
                "may corrupt it.\n",
404 e076f338 Kevin Wolf
                result.corruptions);
405 e076f338 Kevin Wolf
        }
406 e076f338 Kevin Wolf
407 e076f338 Kevin Wolf
        if (result.leaks) {
408 e076f338 Kevin Wolf
            printf("\n%d leaked clusters were found on the image.\n"
409 e076f338 Kevin Wolf
                "This means waste of disk space, but no harm to data.\n",
410 e076f338 Kevin Wolf
                result.leaks);
411 e076f338 Kevin Wolf
        }
412 e076f338 Kevin Wolf
413 e076f338 Kevin Wolf
        if (result.check_errors) {
414 e076f338 Kevin Wolf
            printf("\n%d internal errors have occurred during the check.\n",
415 e076f338 Kevin Wolf
                result.check_errors);
416 1585969c aliguori
        }
417 1585969c aliguori
    }
418 1585969c aliguori
419 1585969c aliguori
    bdrv_delete(bs);
420 e076f338 Kevin Wolf
421 e076f338 Kevin Wolf
    if (ret < 0 || result.check_errors) {
422 e076f338 Kevin Wolf
        printf("\nAn error has occurred during the check: %s\n"
423 e076f338 Kevin Wolf
            "The check is not complete and may have missed error.\n",
424 e076f338 Kevin Wolf
            strerror(-ret));
425 c2abccec MORITA Kazutaka
        return 1;
426 c2abccec MORITA Kazutaka
    }
427 e076f338 Kevin Wolf
428 e076f338 Kevin Wolf
    if (result.corruptions) {
429 e076f338 Kevin Wolf
        return 2;
430 e076f338 Kevin Wolf
    } else if (result.leaks) {
431 e076f338 Kevin Wolf
        return 3;
432 e076f338 Kevin Wolf
    } else {
433 e076f338 Kevin Wolf
        return 0;
434 e076f338 Kevin Wolf
    }
435 1585969c aliguori
}
436 1585969c aliguori
437 ea2384d3 bellard
static int img_commit(int argc, char **argv)
438 ea2384d3 bellard
{
439 ea2384d3 bellard
    int c, ret;
440 ea2384d3 bellard
    const char *filename, *fmt;
441 ea2384d3 bellard
    BlockDriverState *bs;
442 ea2384d3 bellard
443 ea2384d3 bellard
    fmt = NULL;
444 ea2384d3 bellard
    for(;;) {
445 ea2384d3 bellard
        c = getopt(argc, argv, "f:h");
446 b8fb60da Jes Sorensen
        if (c == -1) {
447 ea2384d3 bellard
            break;
448 b8fb60da Jes Sorensen
        }
449 ea2384d3 bellard
        switch(c) {
450 ef87394c Jes Sorensen
        case '?':
451 ea2384d3 bellard
        case 'h':
452 ea2384d3 bellard
            help();
453 ea2384d3 bellard
            break;
454 ea2384d3 bellard
        case 'f':
455 ea2384d3 bellard
            fmt = optarg;
456 ea2384d3 bellard
            break;
457 ea2384d3 bellard
        }
458 ea2384d3 bellard
    }
459 b8fb60da Jes Sorensen
    if (optind >= argc) {
460 ea2384d3 bellard
        help();
461 b8fb60da Jes Sorensen
    }
462 ea2384d3 bellard
    filename = argv[optind++];
463 ea2384d3 bellard
464 adfe078e Stefan Hajnoczi
    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
465 c2abccec MORITA Kazutaka
    if (!bs) {
466 c2abccec MORITA Kazutaka
        return 1;
467 c2abccec MORITA Kazutaka
    }
468 ea2384d3 bellard
    ret = bdrv_commit(bs);
469 ea2384d3 bellard
    switch(ret) {
470 ea2384d3 bellard
    case 0:
471 ea2384d3 bellard
        printf("Image committed.\n");
472 ea2384d3 bellard
        break;
473 ea2384d3 bellard
    case -ENOENT:
474 15654a6d Jes Sorensen
        error_report("No disk inserted");
475 ea2384d3 bellard
        break;
476 ea2384d3 bellard
    case -EACCES:
477 15654a6d Jes Sorensen
        error_report("Image is read-only");
478 ea2384d3 bellard
        break;
479 ea2384d3 bellard
    case -ENOTSUP:
480 15654a6d Jes Sorensen
        error_report("Image is already committed");
481 ea2384d3 bellard
        break;
482 ea2384d3 bellard
    default:
483 15654a6d Jes Sorensen
        error_report("Error while committing image");
484 ea2384d3 bellard
        break;
485 ea2384d3 bellard
    }
486 ea2384d3 bellard
487 ea2384d3 bellard
    bdrv_delete(bs);
488 c2abccec MORITA Kazutaka
    if (ret) {
489 c2abccec MORITA Kazutaka
        return 1;
490 c2abccec MORITA Kazutaka
    }
491 ea2384d3 bellard
    return 0;
492 ea2384d3 bellard
}
493 ea2384d3 bellard
494 ea2384d3 bellard
static int is_not_zero(const uint8_t *sector, int len)
495 ea2384d3 bellard
{
496 ea2384d3 bellard
    int i;
497 ea2384d3 bellard
    len >>= 2;
498 ea2384d3 bellard
    for(i = 0;i < len; i++) {
499 ea2384d3 bellard
        if (((uint32_t *)sector)[i] != 0)
500 ea2384d3 bellard
            return 1;
501 ea2384d3 bellard
    }
502 ea2384d3 bellard
    return 0;
503 ea2384d3 bellard
}
504 ea2384d3 bellard
505 f58c7b35 ths
/*
506 f58c7b35 ths
 * Returns true iff the first sector pointed to by 'buf' contains at least
507 f58c7b35 ths
 * a non-NUL byte.
508 f58c7b35 ths
 *
509 f58c7b35 ths
 * 'pnum' is set to the number of sectors (including and immediately following
510 f58c7b35 ths
 * the first one) that are known to be in the same allocated/unallocated state.
511 f58c7b35 ths
 */
512 ea2384d3 bellard
static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
513 ea2384d3 bellard
{
514 ea2384d3 bellard
    int v, i;
515 ea2384d3 bellard
516 ea2384d3 bellard
    if (n <= 0) {
517 ea2384d3 bellard
        *pnum = 0;
518 ea2384d3 bellard
        return 0;
519 ea2384d3 bellard
    }
520 ea2384d3 bellard
    v = is_not_zero(buf, 512);
521 ea2384d3 bellard
    for(i = 1; i < n; i++) {
522 ea2384d3 bellard
        buf += 512;
523 ea2384d3 bellard
        if (v != is_not_zero(buf, 512))
524 ea2384d3 bellard
            break;
525 ea2384d3 bellard
    }
526 ea2384d3 bellard
    *pnum = i;
527 ea2384d3 bellard
    return v;
528 ea2384d3 bellard
}
529 ea2384d3 bellard
530 3e85c6fd Kevin Wolf
/*
531 3e85c6fd Kevin Wolf
 * Compares two buffers sector by sector. Returns 0 if the first sector of both
532 3e85c6fd Kevin Wolf
 * buffers matches, non-zero otherwise.
533 3e85c6fd Kevin Wolf
 *
534 3e85c6fd Kevin Wolf
 * pnum is set to the number of sectors (including and immediately following
535 3e85c6fd Kevin Wolf
 * the first one) that are known to have the same comparison result
536 3e85c6fd Kevin Wolf
 */
537 3e85c6fd Kevin Wolf
static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
538 3e85c6fd Kevin Wolf
    int *pnum)
539 3e85c6fd Kevin Wolf
{
540 3e85c6fd Kevin Wolf
    int res, i;
541 3e85c6fd Kevin Wolf
542 3e85c6fd Kevin Wolf
    if (n <= 0) {
543 3e85c6fd Kevin Wolf
        *pnum = 0;
544 3e85c6fd Kevin Wolf
        return 0;
545 3e85c6fd Kevin Wolf
    }
546 3e85c6fd Kevin Wolf
547 3e85c6fd Kevin Wolf
    res = !!memcmp(buf1, buf2, 512);
548 3e85c6fd Kevin Wolf
    for(i = 1; i < n; i++) {
549 3e85c6fd Kevin Wolf
        buf1 += 512;
550 3e85c6fd Kevin Wolf
        buf2 += 512;
551 3e85c6fd Kevin Wolf
552 3e85c6fd Kevin Wolf
        if (!!memcmp(buf1, buf2, 512) != res) {
553 3e85c6fd Kevin Wolf
            break;
554 3e85c6fd Kevin Wolf
        }
555 3e85c6fd Kevin Wolf
    }
556 3e85c6fd Kevin Wolf
557 3e85c6fd Kevin Wolf
    *pnum = i;
558 3e85c6fd Kevin Wolf
    return res;
559 3e85c6fd Kevin Wolf
}
560 3e85c6fd Kevin Wolf
561 80ee15a6 Kevin Wolf
#define IO_BUF_SIZE (2 * 1024 * 1024)
562 ea2384d3 bellard
563 ea2384d3 bellard
static int img_convert(int argc, char **argv)
564 ea2384d3 bellard
{
565 eec77d9e Jes Sorensen
    int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
566 f58c7b35 ths
    const char *fmt, *out_fmt, *out_baseimg, *out_filename;
567 b50cbabc MORITA Kazutaka
    BlockDriver *drv, *proto_drv;
568 c2abccec MORITA Kazutaka
    BlockDriverState **bs = NULL, *out_bs = NULL;
569 96b8f136 ths
    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
570 96b8f136 ths
    uint64_t bs_sectors;
571 c2abccec MORITA Kazutaka
    uint8_t * buf = NULL;
572 ea2384d3 bellard
    const uint8_t *buf1;
573 faea38e7 bellard
    BlockDriverInfo bdi;
574 b50cbabc MORITA Kazutaka
    QEMUOptionParameter *param = NULL, *create_options = NULL;
575 a18953fb Kevin Wolf
    QEMUOptionParameter *out_baseimg_param;
576 efa84d43 Kevin Wolf
    char *options = NULL;
577 51ef6727 edison
    const char *snapshot_name = NULL;
578 ea2384d3 bellard
579 ea2384d3 bellard
    fmt = NULL;
580 ea2384d3 bellard
    out_fmt = "raw";
581 f58c7b35 ths
    out_baseimg = NULL;
582 eec77d9e Jes Sorensen
    compress = 0;
583 ea2384d3 bellard
    for(;;) {
584 51ef6727 edison
        c = getopt(argc, argv, "f:O:B:s:hce6o:");
585 b8fb60da Jes Sorensen
        if (c == -1) {
586 ea2384d3 bellard
            break;
587 b8fb60da Jes Sorensen
        }
588 ea2384d3 bellard
        switch(c) {
589 ef87394c Jes Sorensen
        case '?':
590 ea2384d3 bellard
        case 'h':
591 ea2384d3 bellard
            help();
592 ea2384d3 bellard
            break;
593 ea2384d3 bellard
        case 'f':
594 ea2384d3 bellard
            fmt = optarg;
595 ea2384d3 bellard
            break;
596 ea2384d3 bellard
        case 'O':
597 ea2384d3 bellard
            out_fmt = optarg;
598 ea2384d3 bellard
            break;
599 f58c7b35 ths
        case 'B':
600 f58c7b35 ths
            out_baseimg = optarg;
601 f58c7b35 ths
            break;
602 ea2384d3 bellard
        case 'c':
603 eec77d9e Jes Sorensen
            compress = 1;
604 ea2384d3 bellard
            break;
605 ea2384d3 bellard
        case 'e':
606 15654a6d Jes Sorensen
            error_report("qemu-img: option -e is deprecated, please use \'-o "
607 eec77d9e Jes Sorensen
                  "encryption\' instead!");
608 eec77d9e Jes Sorensen
            return 1;
609 ec36ba14 ths
        case '6':
610 15654a6d Jes Sorensen
            error_report("qemu-img: option -6 is deprecated, please use \'-o "
611 eec77d9e Jes Sorensen
                  "compat6\' instead!");
612 eec77d9e Jes Sorensen
            return 1;
613 efa84d43 Kevin Wolf
        case 'o':
614 efa84d43 Kevin Wolf
            options = optarg;
615 efa84d43 Kevin Wolf
            break;
616 51ef6727 edison
        case 's':
617 51ef6727 edison
            snapshot_name = optarg;
618 51ef6727 edison
            break;
619 ea2384d3 bellard
        }
620 ea2384d3 bellard
    }
621 3b46e624 ths
622 926c2d23 balrog
    bs_n = argc - optind - 1;
623 b8fb60da Jes Sorensen
    if (bs_n < 1) {
624 b8fb60da Jes Sorensen
        help();
625 b8fb60da Jes Sorensen
    }
626 926c2d23 balrog
627 926c2d23 balrog
    out_filename = argv[argc - 1];
628 f58c7b35 ths
629 4ac8aacd Jes Sorensen
    if (options && !strcmp(options, "?")) {
630 4ac8aacd Jes Sorensen
        ret = print_block_option_help(out_filename, out_fmt);
631 4ac8aacd Jes Sorensen
        goto out;
632 4ac8aacd Jes Sorensen
    }
633 4ac8aacd Jes Sorensen
634 c2abccec MORITA Kazutaka
    if (bs_n > 1 && out_baseimg) {
635 15654a6d Jes Sorensen
        error_report("-B makes no sense when concatenating multiple input "
636 15654a6d Jes Sorensen
                     "images");
637 31ca34b8 Jes Sorensen
        ret = -1;
638 31ca34b8 Jes Sorensen
        goto out;
639 c2abccec MORITA Kazutaka
    }
640 926c2d23 balrog
        
641 5bdf61fd Jes Sorensen
    bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *));
642 926c2d23 balrog
643 926c2d23 balrog
    total_sectors = 0;
644 926c2d23 balrog
    for (bs_i = 0; bs_i < bs_n; bs_i++) {
645 adfe078e Stefan Hajnoczi
        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
646 c2abccec MORITA Kazutaka
        if (!bs[bs_i]) {
647 15654a6d Jes Sorensen
            error_report("Could not open '%s'", argv[optind + bs_i]);
648 c2abccec MORITA Kazutaka
            ret = -1;
649 c2abccec MORITA Kazutaka
            goto out;
650 c2abccec MORITA Kazutaka
        }
651 926c2d23 balrog
        bdrv_get_geometry(bs[bs_i], &bs_sectors);
652 926c2d23 balrog
        total_sectors += bs_sectors;
653 926c2d23 balrog
    }
654 ea2384d3 bellard
655 51ef6727 edison
    if (snapshot_name != NULL) {
656 51ef6727 edison
        if (bs_n > 1) {
657 15654a6d Jes Sorensen
            error_report("No support for concatenating multiple snapshot\n");
658 51ef6727 edison
            ret = -1;
659 51ef6727 edison
            goto out;
660 51ef6727 edison
        }
661 51ef6727 edison
        if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
662 15654a6d Jes Sorensen
            error_report("Failed to load snapshot\n");
663 51ef6727 edison
            ret = -1;
664 51ef6727 edison
            goto out;
665 51ef6727 edison
        }
666 51ef6727 edison
    }
667 51ef6727 edison
668 efa84d43 Kevin Wolf
    /* Find driver and parse its options */
669 ea2384d3 bellard
    drv = bdrv_find_format(out_fmt);
670 c2abccec MORITA Kazutaka
    if (!drv) {
671 15654a6d Jes Sorensen
        error_report("Unknown file format '%s'", out_fmt);
672 c2abccec MORITA Kazutaka
        ret = -1;
673 c2abccec MORITA Kazutaka
        goto out;
674 c2abccec MORITA Kazutaka
    }
675 efa84d43 Kevin Wolf
676 b50cbabc MORITA Kazutaka
    proto_drv = bdrv_find_protocol(out_filename);
677 c2abccec MORITA Kazutaka
    if (!proto_drv) {
678 15654a6d Jes Sorensen
        error_report("Unknown protocol '%s'", out_filename);
679 c2abccec MORITA Kazutaka
        ret = -1;
680 c2abccec MORITA Kazutaka
        goto out;
681 c2abccec MORITA Kazutaka
    }
682 b50cbabc MORITA Kazutaka
683 b50cbabc MORITA Kazutaka
    create_options = append_option_parameters(create_options,
684 b50cbabc MORITA Kazutaka
                                              drv->create_options);
685 b50cbabc MORITA Kazutaka
    create_options = append_option_parameters(create_options,
686 b50cbabc MORITA Kazutaka
                                              proto_drv->create_options);
687 db08adf5 Kevin Wolf
688 efa84d43 Kevin Wolf
    if (options) {
689 b50cbabc MORITA Kazutaka
        param = parse_option_parameters(options, create_options, param);
690 efa84d43 Kevin Wolf
        if (param == NULL) {
691 15654a6d Jes Sorensen
            error_report("Invalid options for file format '%s'.", out_fmt);
692 c2abccec MORITA Kazutaka
            ret = -1;
693 c2abccec MORITA Kazutaka
            goto out;
694 efa84d43 Kevin Wolf
        }
695 efa84d43 Kevin Wolf
    } else {
696 b50cbabc MORITA Kazutaka
        param = parse_option_parameters("", create_options, param);
697 efa84d43 Kevin Wolf
    }
698 efa84d43 Kevin Wolf
699 efa84d43 Kevin Wolf
    set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
700 eec77d9e Jes Sorensen
    ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
701 c2abccec MORITA Kazutaka
    if (ret < 0) {
702 c2abccec MORITA Kazutaka
        goto out;
703 c2abccec MORITA Kazutaka
    }
704 efa84d43 Kevin Wolf
705 a18953fb Kevin Wolf
    /* Get backing file name if -o backing_file was used */
706 a18953fb Kevin Wolf
    out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
707 a18953fb Kevin Wolf
    if (out_baseimg_param) {
708 a18953fb Kevin Wolf
        out_baseimg = out_baseimg_param->value.s;
709 a18953fb Kevin Wolf
    }
710 a18953fb Kevin Wolf
711 efa84d43 Kevin Wolf
    /* Check if compression is supported */
712 eec77d9e Jes Sorensen
    if (compress) {
713 efa84d43 Kevin Wolf
        QEMUOptionParameter *encryption =
714 efa84d43 Kevin Wolf
            get_option_parameter(param, BLOCK_OPT_ENCRYPT);
715 efa84d43 Kevin Wolf
716 efa84d43 Kevin Wolf
        if (!drv->bdrv_write_compressed) {
717 15654a6d Jes Sorensen
            error_report("Compression not supported for this file format");
718 c2abccec MORITA Kazutaka
            ret = -1;
719 c2abccec MORITA Kazutaka
            goto out;
720 efa84d43 Kevin Wolf
        }
721 efa84d43 Kevin Wolf
722 efa84d43 Kevin Wolf
        if (encryption && encryption->value.n) {
723 15654a6d Jes Sorensen
            error_report("Compression and encryption not supported at "
724 15654a6d Jes Sorensen
                         "the same time");
725 c2abccec MORITA Kazutaka
            ret = -1;
726 c2abccec MORITA Kazutaka
            goto out;
727 efa84d43 Kevin Wolf
        }
728 efa84d43 Kevin Wolf
    }
729 efa84d43 Kevin Wolf
730 efa84d43 Kevin Wolf
    /* Create the new image */
731 efa84d43 Kevin Wolf
    ret = bdrv_create(drv, out_filename, param);
732 ea2384d3 bellard
    if (ret < 0) {
733 ea2384d3 bellard
        if (ret == -ENOTSUP) {
734 15654a6d Jes Sorensen
            error_report("Formatting not supported for file format '%s'",
735 15654a6d Jes Sorensen
                         out_fmt);
736 6e9ea0c0 aurel32
        } else if (ret == -EFBIG) {
737 15654a6d Jes Sorensen
            error_report("The image size is too large for file format '%s'",
738 15654a6d Jes Sorensen
                         out_fmt);
739 ea2384d3 bellard
        } else {
740 15654a6d Jes Sorensen
            error_report("%s: error while converting %s: %s",
741 15654a6d Jes Sorensen
                         out_filename, out_fmt, strerror(-ret));
742 ea2384d3 bellard
        }
743 c2abccec MORITA Kazutaka
        goto out;
744 ea2384d3 bellard
    }
745 3b46e624 ths
746 1bd8e175 Kevin Wolf
    out_bs = bdrv_new_open(out_filename, out_fmt,
747 1bd8e175 Kevin Wolf
        BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
748 c2abccec MORITA Kazutaka
    if (!out_bs) {
749 c2abccec MORITA Kazutaka
        ret = -1;
750 c2abccec MORITA Kazutaka
        goto out;
751 c2abccec MORITA Kazutaka
    }
752 ea2384d3 bellard
753 926c2d23 balrog
    bs_i = 0;
754 926c2d23 balrog
    bs_offset = 0;
755 926c2d23 balrog
    bdrv_get_geometry(bs[0], &bs_sectors);
756 d6771bfa TeLeMan
    buf = qemu_malloc(IO_BUF_SIZE);
757 926c2d23 balrog
758 eec77d9e Jes Sorensen
    if (compress) {
759 c2abccec MORITA Kazutaka
        ret = bdrv_get_info(out_bs, &bdi);
760 c2abccec MORITA Kazutaka
        if (ret < 0) {
761 15654a6d Jes Sorensen
            error_report("could not get block driver info");
762 c2abccec MORITA Kazutaka
            goto out;
763 c2abccec MORITA Kazutaka
        }
764 faea38e7 bellard
        cluster_size = bdi.cluster_size;
765 c2abccec MORITA Kazutaka
        if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
766 15654a6d Jes Sorensen
            error_report("invalid cluster size");
767 c2abccec MORITA Kazutaka
            ret = -1;
768 c2abccec MORITA Kazutaka
            goto out;
769 c2abccec MORITA Kazutaka
        }
770 ea2384d3 bellard
        cluster_sectors = cluster_size >> 9;
771 ea2384d3 bellard
        sector_num = 0;
772 ea2384d3 bellard
        for(;;) {
773 926c2d23 balrog
            int64_t bs_num;
774 926c2d23 balrog
            int remainder;
775 926c2d23 balrog
            uint8_t *buf2;
776 926c2d23 balrog
777 ea2384d3 bellard
            nb_sectors = total_sectors - sector_num;
778 ea2384d3 bellard
            if (nb_sectors <= 0)
779 ea2384d3 bellard
                break;
780 ea2384d3 bellard
            if (nb_sectors >= cluster_sectors)
781 ea2384d3 bellard
                n = cluster_sectors;
782 ea2384d3 bellard
            else
783 ea2384d3 bellard
                n = nb_sectors;
784 926c2d23 balrog
785 926c2d23 balrog
            bs_num = sector_num - bs_offset;
786 926c2d23 balrog
            assert (bs_num >= 0);
787 926c2d23 balrog
            remainder = n;
788 926c2d23 balrog
            buf2 = buf;
789 926c2d23 balrog
            while (remainder > 0) {
790 926c2d23 balrog
                int nlow;
791 926c2d23 balrog
                while (bs_num == bs_sectors) {
792 926c2d23 balrog
                    bs_i++;
793 926c2d23 balrog
                    assert (bs_i < bs_n);
794 926c2d23 balrog
                    bs_offset += bs_sectors;
795 926c2d23 balrog
                    bdrv_get_geometry(bs[bs_i], &bs_sectors);
796 926c2d23 balrog
                    bs_num = 0;
797 0bfcd599 Blue Swirl
                    /* printf("changing part: sector_num=%" PRId64 ", "
798 0bfcd599 Blue Swirl
                       "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
799 0bfcd599 Blue Swirl
                       "\n", sector_num, bs_i, bs_offset, bs_sectors); */
800 926c2d23 balrog
                }
801 926c2d23 balrog
                assert (bs_num < bs_sectors);
802 926c2d23 balrog
803 926c2d23 balrog
                nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
804 926c2d23 balrog
805 c2abccec MORITA Kazutaka
                ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
806 c2abccec MORITA Kazutaka
                if (ret < 0) {
807 15654a6d Jes Sorensen
                    error_report("error while reading");
808 c2abccec MORITA Kazutaka
                    goto out;
809 c2abccec MORITA Kazutaka
                }
810 926c2d23 balrog
811 926c2d23 balrog
                buf2 += nlow * 512;
812 926c2d23 balrog
                bs_num += nlow;
813 926c2d23 balrog
814 926c2d23 balrog
                remainder -= nlow;
815 926c2d23 balrog
            }
816 926c2d23 balrog
            assert (remainder == 0);
817 926c2d23 balrog
818 b8fb60da Jes Sorensen
            if (n < cluster_sectors) {
819 ea2384d3 bellard
                memset(buf + n * 512, 0, cluster_size - n * 512);
820 b8fb60da Jes Sorensen
            }
821 ea2384d3 bellard
            if (is_not_zero(buf, cluster_size)) {
822 c2abccec MORITA Kazutaka
                ret = bdrv_write_compressed(out_bs, sector_num, buf,
823 c2abccec MORITA Kazutaka
                                            cluster_sectors);
824 c2abccec MORITA Kazutaka
                if (ret != 0) {
825 15654a6d Jes Sorensen
                    error_report("error while compressing sector %" PRId64,
826 ec3757de bellard
                          sector_num);
827 c2abccec MORITA Kazutaka
                    goto out;
828 c2abccec MORITA Kazutaka
                }
829 ea2384d3 bellard
            }
830 ea2384d3 bellard
            sector_num += n;
831 ea2384d3 bellard
        }
832 faea38e7 bellard
        /* signal EOF to align */
833 faea38e7 bellard
        bdrv_write_compressed(out_bs, 0, NULL, 0);
834 ea2384d3 bellard
    } else {
835 f2feebbd Kevin Wolf
        int has_zero_init = bdrv_has_zero_init(out_bs);
836 f2feebbd Kevin Wolf
837 f58c7b35 ths
        sector_num = 0; // total number of sectors converted so far
838 ea2384d3 bellard
        for(;;) {
839 ea2384d3 bellard
            nb_sectors = total_sectors - sector_num;
840 b8fb60da Jes Sorensen
            if (nb_sectors <= 0) {
841 ea2384d3 bellard
                break;
842 b8fb60da Jes Sorensen
            }
843 b8fb60da Jes Sorensen
            if (nb_sectors >= (IO_BUF_SIZE / 512)) {
844 ea2384d3 bellard
                n = (IO_BUF_SIZE / 512);
845 b8fb60da Jes Sorensen
            } else {
846 ea2384d3 bellard
                n = nb_sectors;
847 b8fb60da Jes Sorensen
            }
848 926c2d23 balrog
849 926c2d23 balrog
            while (sector_num - bs_offset >= bs_sectors) {
850 926c2d23 balrog
                bs_i ++;
851 926c2d23 balrog
                assert (bs_i < bs_n);
852 926c2d23 balrog
                bs_offset += bs_sectors;
853 926c2d23 balrog
                bdrv_get_geometry(bs[bs_i], &bs_sectors);
854 0bfcd599 Blue Swirl
                /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
855 0bfcd599 Blue Swirl
                  "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
856 926c2d23 balrog
                   sector_num, bs_i, bs_offset, bs_sectors); */
857 926c2d23 balrog
            }
858 926c2d23 balrog
859 b8fb60da Jes Sorensen
            if (n > bs_offset + bs_sectors - sector_num) {
860 926c2d23 balrog
                n = bs_offset + bs_sectors - sector_num;
861 b8fb60da Jes Sorensen
            }
862 926c2d23 balrog
863 f2feebbd Kevin Wolf
            if (has_zero_init) {
864 d032044f Akkarit Sangpetch
                /* If the output image is being created as a copy on write image,
865 d032044f Akkarit Sangpetch
                   assume that sectors which are unallocated in the input image
866 d032044f Akkarit Sangpetch
                   are present in both the output's and input's base images (no
867 d032044f Akkarit Sangpetch
                   need to copy them). */
868 d032044f Akkarit Sangpetch
                if (out_baseimg) {
869 d032044f Akkarit Sangpetch
                    if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
870 d032044f Akkarit Sangpetch
                                           n, &n1)) {
871 d032044f Akkarit Sangpetch
                        sector_num += n1;
872 d032044f Akkarit Sangpetch
                        continue;
873 d032044f Akkarit Sangpetch
                    }
874 d032044f Akkarit Sangpetch
                    /* The next 'n1' sectors are allocated in the input image. Copy
875 d032044f Akkarit Sangpetch
                       only those as they may be followed by unallocated sectors. */
876 d032044f Akkarit Sangpetch
                    n = n1;
877 93c65b47 aliguori
                }
878 93c65b47 aliguori
            } else {
879 93c65b47 aliguori
                n1 = n;
880 f58c7b35 ths
            }
881 f58c7b35 ths
882 c2abccec MORITA Kazutaka
            ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
883 c2abccec MORITA Kazutaka
            if (ret < 0) {
884 15654a6d Jes Sorensen
                error_report("error while reading");
885 c2abccec MORITA Kazutaka
                goto out;
886 c2abccec MORITA Kazutaka
            }
887 ea2384d3 bellard
            /* NOTE: at the same time we convert, we do not write zero
888 ea2384d3 bellard
               sectors to have a chance to compress the image. Ideally, we
889 ea2384d3 bellard
               should add a specific call to have the info to go faster */
890 ea2384d3 bellard
            buf1 = buf;
891 ea2384d3 bellard
            while (n > 0) {
892 f58c7b35 ths
                /* If the output image is being created as a copy on write image,
893 f58c7b35 ths
                   copy all sectors even the ones containing only NUL bytes,
894 93c65b47 aliguori
                   because they may differ from the sectors in the base image.
895 93c65b47 aliguori

896 93c65b47 aliguori
                   If the output is to a host device, we also write out
897 93c65b47 aliguori
                   sectors that are entirely 0, since whatever data was
898 93c65b47 aliguori
                   already there is garbage, not 0s. */
899 f2feebbd Kevin Wolf
                if (!has_zero_init || out_baseimg ||
900 93c65b47 aliguori
                    is_allocated_sectors(buf1, n, &n1)) {
901 c2abccec MORITA Kazutaka
                    ret = bdrv_write(out_bs, sector_num, buf1, n1);
902 c2abccec MORITA Kazutaka
                    if (ret < 0) {
903 15654a6d Jes Sorensen
                        error_report("error while writing");
904 c2abccec MORITA Kazutaka
                        goto out;
905 c2abccec MORITA Kazutaka
                    }
906 ea2384d3 bellard
                }
907 ea2384d3 bellard
                sector_num += n1;
908 ea2384d3 bellard
                n -= n1;
909 ea2384d3 bellard
                buf1 += n1 * 512;
910 ea2384d3 bellard
            }
911 ea2384d3 bellard
        }
912 ea2384d3 bellard
    }
913 c2abccec MORITA Kazutaka
out:
914 c2abccec MORITA Kazutaka
    free_option_parameters(create_options);
915 c2abccec MORITA Kazutaka
    free_option_parameters(param);
916 d6771bfa TeLeMan
    qemu_free(buf);
917 c2abccec MORITA Kazutaka
    if (out_bs) {
918 c2abccec MORITA Kazutaka
        bdrv_delete(out_bs);
919 c2abccec MORITA Kazutaka
    }
920 31ca34b8 Jes Sorensen
    if (bs) {
921 31ca34b8 Jes Sorensen
        for (bs_i = 0; bs_i < bs_n; bs_i++) {
922 31ca34b8 Jes Sorensen
            if (bs[bs_i]) {
923 31ca34b8 Jes Sorensen
                bdrv_delete(bs[bs_i]);
924 31ca34b8 Jes Sorensen
            }
925 c2abccec MORITA Kazutaka
        }
926 31ca34b8 Jes Sorensen
        qemu_free(bs);
927 c2abccec MORITA Kazutaka
    }
928 c2abccec MORITA Kazutaka
    if (ret) {
929 c2abccec MORITA Kazutaka
        return 1;
930 c2abccec MORITA Kazutaka
    }
931 ea2384d3 bellard
    return 0;
932 ea2384d3 bellard
}
933 ea2384d3 bellard
934 57d1a2b6 bellard
#ifdef _WIN32
935 57d1a2b6 bellard
static int64_t get_allocated_file_size(const char *filename)
936 57d1a2b6 bellard
{
937 e8445331 bellard
    typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
938 e8445331 bellard
    get_compressed_t get_compressed;
939 57d1a2b6 bellard
    struct _stati64 st;
940 e8445331 bellard
941 e8445331 bellard
    /* WinNT support GetCompressedFileSize to determine allocate size */
942 e8445331 bellard
    get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
943 e8445331 bellard
    if (get_compressed) {
944 e8445331 bellard
            DWORD high, low;
945 e8445331 bellard
            low = get_compressed(filename, &high);
946 e8445331 bellard
            if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
947 e8445331 bellard
            return (((int64_t) high) << 32) + low;
948 e8445331 bellard
    }
949 e8445331 bellard
950 5fafdf24 ths
    if (_stati64(filename, &st) < 0)
951 57d1a2b6 bellard
        return -1;
952 57d1a2b6 bellard
    return st.st_size;
953 57d1a2b6 bellard
}
954 57d1a2b6 bellard
#else
955 57d1a2b6 bellard
static int64_t get_allocated_file_size(const char *filename)
956 57d1a2b6 bellard
{
957 57d1a2b6 bellard
    struct stat st;
958 5fafdf24 ths
    if (stat(filename, &st) < 0)
959 57d1a2b6 bellard
        return -1;
960 57d1a2b6 bellard
    return (int64_t)st.st_blocks * 512;
961 57d1a2b6 bellard
}
962 57d1a2b6 bellard
#endif
963 57d1a2b6 bellard
964 faea38e7 bellard
static void dump_snapshots(BlockDriverState *bs)
965 faea38e7 bellard
{
966 faea38e7 bellard
    QEMUSnapshotInfo *sn_tab, *sn;
967 faea38e7 bellard
    int nb_sns, i;
968 faea38e7 bellard
    char buf[256];
969 faea38e7 bellard
970 faea38e7 bellard
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
971 faea38e7 bellard
    if (nb_sns <= 0)
972 faea38e7 bellard
        return;
973 faea38e7 bellard
    printf("Snapshot list:\n");
974 faea38e7 bellard
    printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
975 faea38e7 bellard
    for(i = 0; i < nb_sns; i++) {
976 faea38e7 bellard
        sn = &sn_tab[i];
977 faea38e7 bellard
        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
978 faea38e7 bellard
    }
979 faea38e7 bellard
    qemu_free(sn_tab);
980 faea38e7 bellard
}
981 faea38e7 bellard
982 ea2384d3 bellard
static int img_info(int argc, char **argv)
983 ea2384d3 bellard
{
984 ea2384d3 bellard
    int c;
985 ea2384d3 bellard
    const char *filename, *fmt;
986 ea2384d3 bellard
    BlockDriverState *bs;
987 ea2384d3 bellard
    char fmt_name[128], size_buf[128], dsize_buf[128];
988 96b8f136 ths
    uint64_t total_sectors;
989 96b8f136 ths
    int64_t allocated_size;
990 93b6b2a3 bellard
    char backing_filename[1024];
991 93b6b2a3 bellard
    char backing_filename2[1024];
992 faea38e7 bellard
    BlockDriverInfo bdi;
993 ea2384d3 bellard
994 ea2384d3 bellard
    fmt = NULL;
995 ea2384d3 bellard
    for(;;) {
996 ea2384d3 bellard
        c = getopt(argc, argv, "f:h");
997 b8fb60da Jes Sorensen
        if (c == -1) {
998 ea2384d3 bellard
            break;
999 b8fb60da Jes Sorensen
        }
1000 ea2384d3 bellard
        switch(c) {
1001 ef87394c Jes Sorensen
        case '?':
1002 ea2384d3 bellard
        case 'h':
1003 ea2384d3 bellard
            help();
1004 ea2384d3 bellard
            break;
1005 ea2384d3 bellard
        case 'f':
1006 ea2384d3 bellard
            fmt = optarg;
1007 ea2384d3 bellard
            break;
1008 ea2384d3 bellard
        }
1009 ea2384d3 bellard
    }
1010 b8fb60da Jes Sorensen
    if (optind >= argc) {
1011 ea2384d3 bellard
        help();
1012 b8fb60da Jes Sorensen
    }
1013 ea2384d3 bellard
    filename = argv[optind++];
1014 ea2384d3 bellard
1015 adfe078e Stefan Hajnoczi
    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_NO_BACKING);
1016 c2abccec MORITA Kazutaka
    if (!bs) {
1017 c2abccec MORITA Kazutaka
        return 1;
1018 c2abccec MORITA Kazutaka
    }
1019 ea2384d3 bellard
    bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
1020 ea2384d3 bellard
    bdrv_get_geometry(bs, &total_sectors);
1021 ea2384d3 bellard
    get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
1022 57d1a2b6 bellard
    allocated_size = get_allocated_file_size(filename);
1023 b8fb60da Jes Sorensen
    if (allocated_size < 0) {
1024 a10ea30b blueswir1
        snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
1025 b8fb60da Jes Sorensen
    } else {
1026 5fafdf24 ths
        get_human_readable_size(dsize_buf, sizeof(dsize_buf),
1027 de167e41 bellard
                                allocated_size);
1028 b8fb60da Jes Sorensen
    }
1029 ea2384d3 bellard
    printf("image: %s\n"
1030 ea2384d3 bellard
           "file format: %s\n"
1031 ec3757de bellard
           "virtual size: %s (%" PRId64 " bytes)\n"
1032 ea2384d3 bellard
           "disk size: %s\n",
1033 5fafdf24 ths
           filename, fmt_name, size_buf,
1034 ec3757de bellard
           (total_sectors * 512),
1035 ea2384d3 bellard
           dsize_buf);
1036 b8fb60da Jes Sorensen
    if (bdrv_is_encrypted(bs)) {
1037 ea2384d3 bellard
        printf("encrypted: yes\n");
1038 b8fb60da Jes Sorensen
    }
1039 faea38e7 bellard
    if (bdrv_get_info(bs, &bdi) >= 0) {
1040 b8fb60da Jes Sorensen
        if (bdi.cluster_size != 0) {
1041 faea38e7 bellard
            printf("cluster_size: %d\n", bdi.cluster_size);
1042 b8fb60da Jes Sorensen
        }
1043 faea38e7 bellard
    }
1044 93b6b2a3 bellard
    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
1045 faea38e7 bellard
    if (backing_filename[0] != '\0') {
1046 93b6b2a3 bellard
        path_combine(backing_filename2, sizeof(backing_filename2),
1047 93b6b2a3 bellard
                     filename, backing_filename);
1048 5fafdf24 ths
        printf("backing file: %s (actual path: %s)\n",
1049 93b6b2a3 bellard
               backing_filename,
1050 93b6b2a3 bellard
               backing_filename2);
1051 faea38e7 bellard
    }
1052 faea38e7 bellard
    dump_snapshots(bs);
1053 ea2384d3 bellard
    bdrv_delete(bs);
1054 ea2384d3 bellard
    return 0;
1055 ea2384d3 bellard
}
1056 ea2384d3 bellard
1057 f7b4a940 aliguori
#define SNAPSHOT_LIST   1
1058 f7b4a940 aliguori
#define SNAPSHOT_CREATE 2
1059 f7b4a940 aliguori
#define SNAPSHOT_APPLY  3
1060 f7b4a940 aliguori
#define SNAPSHOT_DELETE 4
1061 f7b4a940 aliguori
1062 153859be Stuart Brady
static int img_snapshot(int argc, char **argv)
1063 f7b4a940 aliguori
{
1064 f7b4a940 aliguori
    BlockDriverState *bs;
1065 f7b4a940 aliguori
    QEMUSnapshotInfo sn;
1066 f7b4a940 aliguori
    char *filename, *snapshot_name = NULL;
1067 c2abccec MORITA Kazutaka
    int c, ret = 0, bdrv_oflags;
1068 f7b4a940 aliguori
    int action = 0;
1069 f7b4a940 aliguori
    qemu_timeval tv;
1070 f7b4a940 aliguori
1071 f5edb014 Naphtali Sprei
    bdrv_oflags = BDRV_O_RDWR;
1072 f7b4a940 aliguori
    /* Parse commandline parameters */
1073 f7b4a940 aliguori
    for(;;) {
1074 f7b4a940 aliguori
        c = getopt(argc, argv, "la:c:d:h");
1075 b8fb60da Jes Sorensen
        if (c == -1) {
1076 f7b4a940 aliguori
            break;
1077 b8fb60da Jes Sorensen
        }
1078 f7b4a940 aliguori
        switch(c) {
1079 ef87394c Jes Sorensen
        case '?':
1080 f7b4a940 aliguori
        case 'h':
1081 f7b4a940 aliguori
            help();
1082 153859be Stuart Brady
            return 0;
1083 f7b4a940 aliguori
        case 'l':
1084 f7b4a940 aliguori
            if (action) {
1085 f7b4a940 aliguori
                help();
1086 153859be Stuart Brady
                return 0;
1087 f7b4a940 aliguori
            }
1088 f7b4a940 aliguori
            action = SNAPSHOT_LIST;
1089 f5edb014 Naphtali Sprei
            bdrv_oflags &= ~BDRV_O_RDWR; /* no need for RW */
1090 f7b4a940 aliguori
            break;
1091 f7b4a940 aliguori
        case 'a':
1092 f7b4a940 aliguori
            if (action) {
1093 f7b4a940 aliguori
                help();
1094 153859be Stuart Brady
                return 0;
1095 f7b4a940 aliguori
            }
1096 f7b4a940 aliguori
            action = SNAPSHOT_APPLY;
1097 f7b4a940 aliguori
            snapshot_name = optarg;
1098 f7b4a940 aliguori
            break;
1099 f7b4a940 aliguori
        case 'c':
1100 f7b4a940 aliguori
            if (action) {
1101 f7b4a940 aliguori
                help();
1102 153859be Stuart Brady
                return 0;
1103 f7b4a940 aliguori
            }
1104 f7b4a940 aliguori
            action = SNAPSHOT_CREATE;
1105 f7b4a940 aliguori
            snapshot_name = optarg;
1106 f7b4a940 aliguori
            break;
1107 f7b4a940 aliguori
        case 'd':
1108 f7b4a940 aliguori
            if (action) {
1109 f7b4a940 aliguori
                help();
1110 153859be Stuart Brady
                return 0;
1111 f7b4a940 aliguori
            }
1112 f7b4a940 aliguori
            action = SNAPSHOT_DELETE;
1113 f7b4a940 aliguori
            snapshot_name = optarg;
1114 f7b4a940 aliguori
            break;
1115 f7b4a940 aliguori
        }
1116 f7b4a940 aliguori
    }
1117 f7b4a940 aliguori
1118 b8fb60da Jes Sorensen
    if (optind >= argc) {
1119 f7b4a940 aliguori
        help();
1120 b8fb60da Jes Sorensen
    }
1121 f7b4a940 aliguori
    filename = argv[optind++];
1122 f7b4a940 aliguori
1123 f7b4a940 aliguori
    /* Open the image */
1124 f163d073 Stefan Hajnoczi
    bs = bdrv_new_open(filename, NULL, bdrv_oflags);
1125 c2abccec MORITA Kazutaka
    if (!bs) {
1126 c2abccec MORITA Kazutaka
        return 1;
1127 c2abccec MORITA Kazutaka
    }
1128 f7b4a940 aliguori
1129 f7b4a940 aliguori
    /* Perform the requested action */
1130 f7b4a940 aliguori
    switch(action) {
1131 f7b4a940 aliguori
    case SNAPSHOT_LIST:
1132 f7b4a940 aliguori
        dump_snapshots(bs);
1133 f7b4a940 aliguori
        break;
1134 f7b4a940 aliguori
1135 f7b4a940 aliguori
    case SNAPSHOT_CREATE:
1136 f7b4a940 aliguori
        memset(&sn, 0, sizeof(sn));
1137 f7b4a940 aliguori
        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1138 f7b4a940 aliguori
1139 f7b4a940 aliguori
        qemu_gettimeofday(&tv);
1140 f7b4a940 aliguori
        sn.date_sec = tv.tv_sec;
1141 f7b4a940 aliguori
        sn.date_nsec = tv.tv_usec * 1000;
1142 f7b4a940 aliguori
1143 f7b4a940 aliguori
        ret = bdrv_snapshot_create(bs, &sn);
1144 b8fb60da Jes Sorensen
        if (ret) {
1145 15654a6d Jes Sorensen
            error_report("Could not create snapshot '%s': %d (%s)",
1146 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
1147 b8fb60da Jes Sorensen
        }
1148 f7b4a940 aliguori
        break;
1149 f7b4a940 aliguori
1150 f7b4a940 aliguori
    case SNAPSHOT_APPLY:
1151 f7b4a940 aliguori
        ret = bdrv_snapshot_goto(bs, snapshot_name);
1152 b8fb60da Jes Sorensen
        if (ret) {
1153 15654a6d Jes Sorensen
            error_report("Could not apply snapshot '%s': %d (%s)",
1154 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
1155 b8fb60da Jes Sorensen
        }
1156 f7b4a940 aliguori
        break;
1157 f7b4a940 aliguori
1158 f7b4a940 aliguori
    case SNAPSHOT_DELETE:
1159 f7b4a940 aliguori
        ret = bdrv_snapshot_delete(bs, snapshot_name);
1160 b8fb60da Jes Sorensen
        if (ret) {
1161 15654a6d Jes Sorensen
            error_report("Could not delete snapshot '%s': %d (%s)",
1162 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
1163 b8fb60da Jes Sorensen
        }
1164 f7b4a940 aliguori
        break;
1165 f7b4a940 aliguori
    }
1166 f7b4a940 aliguori
1167 f7b4a940 aliguori
    /* Cleanup */
1168 f7b4a940 aliguori
    bdrv_delete(bs);
1169 c2abccec MORITA Kazutaka
    if (ret) {
1170 c2abccec MORITA Kazutaka
        return 1;
1171 c2abccec MORITA Kazutaka
    }
1172 153859be Stuart Brady
    return 0;
1173 f7b4a940 aliguori
}
1174 f7b4a940 aliguori
1175 3e85c6fd Kevin Wolf
static int img_rebase(int argc, char **argv)
1176 3e85c6fd Kevin Wolf
{
1177 c2abccec MORITA Kazutaka
    BlockDriverState *bs, *bs_old_backing = NULL, *bs_new_backing = NULL;
1178 f163d073 Stefan Hajnoczi
    BlockDriver *old_backing_drv, *new_backing_drv;
1179 3e85c6fd Kevin Wolf
    char *filename;
1180 e53dbee0 Kevin Wolf
    const char *fmt, *out_basefmt, *out_baseimg;
1181 3e85c6fd Kevin Wolf
    int c, flags, ret;
1182 3e85c6fd Kevin Wolf
    int unsafe = 0;
1183 3e85c6fd Kevin Wolf
1184 3e85c6fd Kevin Wolf
    /* Parse commandline parameters */
1185 e53dbee0 Kevin Wolf
    fmt = NULL;
1186 3e85c6fd Kevin Wolf
    out_baseimg = NULL;
1187 3e85c6fd Kevin Wolf
    out_basefmt = NULL;
1188 3e85c6fd Kevin Wolf
1189 3e85c6fd Kevin Wolf
    for(;;) {
1190 e53dbee0 Kevin Wolf
        c = getopt(argc, argv, "uhf:F:b:");
1191 b8fb60da Jes Sorensen
        if (c == -1) {
1192 3e85c6fd Kevin Wolf
            break;
1193 b8fb60da Jes Sorensen
        }
1194 3e85c6fd Kevin Wolf
        switch(c) {
1195 ef87394c Jes Sorensen
        case '?':
1196 3e85c6fd Kevin Wolf
        case 'h':
1197 3e85c6fd Kevin Wolf
            help();
1198 3e85c6fd Kevin Wolf
            return 0;
1199 e53dbee0 Kevin Wolf
        case 'f':
1200 e53dbee0 Kevin Wolf
            fmt = optarg;
1201 e53dbee0 Kevin Wolf
            break;
1202 3e85c6fd Kevin Wolf
        case 'F':
1203 3e85c6fd Kevin Wolf
            out_basefmt = optarg;
1204 3e85c6fd Kevin Wolf
            break;
1205 3e85c6fd Kevin Wolf
        case 'b':
1206 3e85c6fd Kevin Wolf
            out_baseimg = optarg;
1207 3e85c6fd Kevin Wolf
            break;
1208 3e85c6fd Kevin Wolf
        case 'u':
1209 3e85c6fd Kevin Wolf
            unsafe = 1;
1210 3e85c6fd Kevin Wolf
            break;
1211 3e85c6fd Kevin Wolf
        }
1212 3e85c6fd Kevin Wolf
    }
1213 3e85c6fd Kevin Wolf
1214 b8fb60da Jes Sorensen
    if ((optind >= argc) || !out_baseimg) {
1215 3e85c6fd Kevin Wolf
        help();
1216 b8fb60da Jes Sorensen
    }
1217 3e85c6fd Kevin Wolf
    filename = argv[optind++];
1218 3e85c6fd Kevin Wolf
1219 3e85c6fd Kevin Wolf
    /*
1220 3e85c6fd Kevin Wolf
     * Open the images.
1221 3e85c6fd Kevin Wolf
     *
1222 3e85c6fd Kevin Wolf
     * Ignore the old backing file for unsafe rebase in case we want to correct
1223 3e85c6fd Kevin Wolf
     * the reference to a renamed or moved backing file.
1224 3e85c6fd Kevin Wolf
     */
1225 adfe078e Stefan Hajnoczi
    flags = BDRV_O_FLAGS | BDRV_O_RDWR | (unsafe ? BDRV_O_NO_BACKING : 0);
1226 f163d073 Stefan Hajnoczi
    bs = bdrv_new_open(filename, fmt, flags);
1227 c2abccec MORITA Kazutaka
    if (!bs) {
1228 c2abccec MORITA Kazutaka
        return 1;
1229 c2abccec MORITA Kazutaka
    }
1230 3e85c6fd Kevin Wolf
1231 3e85c6fd Kevin Wolf
    /* Find the right drivers for the backing files */
1232 3e85c6fd Kevin Wolf
    old_backing_drv = NULL;
1233 3e85c6fd Kevin Wolf
    new_backing_drv = NULL;
1234 3e85c6fd Kevin Wolf
1235 3e85c6fd Kevin Wolf
    if (!unsafe && bs->backing_format[0] != '\0') {
1236 3e85c6fd Kevin Wolf
        old_backing_drv = bdrv_find_format(bs->backing_format);
1237 3e85c6fd Kevin Wolf
        if (old_backing_drv == NULL) {
1238 15654a6d Jes Sorensen
            error_report("Invalid format name: '%s'", bs->backing_format);
1239 c2abccec MORITA Kazutaka
            ret = -1;
1240 c2abccec MORITA Kazutaka
            goto out;
1241 3e85c6fd Kevin Wolf
        }
1242 3e85c6fd Kevin Wolf
    }
1243 3e85c6fd Kevin Wolf
1244 3e85c6fd Kevin Wolf
    if (out_basefmt != NULL) {
1245 3e85c6fd Kevin Wolf
        new_backing_drv = bdrv_find_format(out_basefmt);
1246 3e85c6fd Kevin Wolf
        if (new_backing_drv == NULL) {
1247 15654a6d Jes Sorensen
            error_report("Invalid format name: '%s'", out_basefmt);
1248 c2abccec MORITA Kazutaka
            ret = -1;
1249 c2abccec MORITA Kazutaka
            goto out;
1250 3e85c6fd Kevin Wolf
        }
1251 3e85c6fd Kevin Wolf
    }
1252 3e85c6fd Kevin Wolf
1253 3e85c6fd Kevin Wolf
    /* For safe rebasing we need to compare old and new backing file */
1254 3e85c6fd Kevin Wolf
    if (unsafe) {
1255 3e85c6fd Kevin Wolf
        /* Make the compiler happy */
1256 3e85c6fd Kevin Wolf
        bs_old_backing = NULL;
1257 3e85c6fd Kevin Wolf
        bs_new_backing = NULL;
1258 3e85c6fd Kevin Wolf
    } else {
1259 3e85c6fd Kevin Wolf
        char backing_name[1024];
1260 3e85c6fd Kevin Wolf
1261 3e85c6fd Kevin Wolf
        bs_old_backing = bdrv_new("old_backing");
1262 3e85c6fd Kevin Wolf
        bdrv_get_backing_filename(bs, backing_name, sizeof(backing_name));
1263 c2abccec MORITA Kazutaka
        ret = bdrv_open(bs_old_backing, backing_name, BDRV_O_FLAGS,
1264 c2abccec MORITA Kazutaka
                        old_backing_drv);
1265 c2abccec MORITA Kazutaka
        if (ret) {
1266 15654a6d Jes Sorensen
            error_report("Could not open old backing file '%s'", backing_name);
1267 c2abccec MORITA Kazutaka
            goto out;
1268 3e85c6fd Kevin Wolf
        }
1269 3e85c6fd Kevin Wolf
1270 3e85c6fd Kevin Wolf
        bs_new_backing = bdrv_new("new_backing");
1271 cdbae851 Kevin Wolf
        ret = bdrv_open(bs_new_backing, out_baseimg, BDRV_O_FLAGS,
1272 c2abccec MORITA Kazutaka
                        new_backing_drv);
1273 c2abccec MORITA Kazutaka
        if (ret) {
1274 15654a6d Jes Sorensen
            error_report("Could not open new backing file '%s'", out_baseimg);
1275 c2abccec MORITA Kazutaka
            goto out;
1276 3e85c6fd Kevin Wolf
        }
1277 3e85c6fd Kevin Wolf
    }
1278 3e85c6fd Kevin Wolf
1279 3e85c6fd Kevin Wolf
    /*
1280 3e85c6fd Kevin Wolf
     * Check each unallocated cluster in the COW file. If it is unallocated,
1281 3e85c6fd Kevin Wolf
     * accesses go to the backing file. We must therefore compare this cluster
1282 3e85c6fd Kevin Wolf
     * in the old and new backing file, and if they differ we need to copy it
1283 3e85c6fd Kevin Wolf
     * from the old backing file into the COW file.
1284 3e85c6fd Kevin Wolf
     *
1285 3e85c6fd Kevin Wolf
     * If qemu-img crashes during this step, no harm is done. The content of
1286 3e85c6fd Kevin Wolf
     * the image is the same as the original one at any time.
1287 3e85c6fd Kevin Wolf
     */
1288 3e85c6fd Kevin Wolf
    if (!unsafe) {
1289 3e85c6fd Kevin Wolf
        uint64_t num_sectors;
1290 3e85c6fd Kevin Wolf
        uint64_t sector;
1291 cc60e327 Kevin Wolf
        int n;
1292 d6771bfa TeLeMan
        uint8_t * buf_old;
1293 d6771bfa TeLeMan
        uint8_t * buf_new;
1294 d6771bfa TeLeMan
1295 d6771bfa TeLeMan
        buf_old = qemu_malloc(IO_BUF_SIZE);
1296 d6771bfa TeLeMan
        buf_new = qemu_malloc(IO_BUF_SIZE);
1297 3e85c6fd Kevin Wolf
1298 3e85c6fd Kevin Wolf
        bdrv_get_geometry(bs, &num_sectors);
1299 3e85c6fd Kevin Wolf
1300 3e85c6fd Kevin Wolf
        for (sector = 0; sector < num_sectors; sector += n) {
1301 3e85c6fd Kevin Wolf
1302 3e85c6fd Kevin Wolf
            /* How many sectors can we handle with the next read? */
1303 3e85c6fd Kevin Wolf
            if (sector + (IO_BUF_SIZE / 512) <= num_sectors) {
1304 3e85c6fd Kevin Wolf
                n = (IO_BUF_SIZE / 512);
1305 3e85c6fd Kevin Wolf
            } else {
1306 3e85c6fd Kevin Wolf
                n = num_sectors - sector;
1307 3e85c6fd Kevin Wolf
            }
1308 3e85c6fd Kevin Wolf
1309 3e85c6fd Kevin Wolf
            /* If the cluster is allocated, we don't need to take action */
1310 cc60e327 Kevin Wolf
            ret = bdrv_is_allocated(bs, sector, n, &n);
1311 cc60e327 Kevin Wolf
            if (ret) {
1312 3e85c6fd Kevin Wolf
                continue;
1313 3e85c6fd Kevin Wolf
            }
1314 3e85c6fd Kevin Wolf
1315 3e85c6fd Kevin Wolf
            /* Read old and new backing file */
1316 c2abccec MORITA Kazutaka
            ret = bdrv_read(bs_old_backing, sector, buf_old, n);
1317 c2abccec MORITA Kazutaka
            if (ret < 0) {
1318 15654a6d Jes Sorensen
                error_report("error while reading from old backing file");
1319 c2abccec MORITA Kazutaka
                goto out;
1320 3e85c6fd Kevin Wolf
            }
1321 c2abccec MORITA Kazutaka
            ret = bdrv_read(bs_new_backing, sector, buf_new, n);
1322 c2abccec MORITA Kazutaka
            if (ret < 0) {
1323 15654a6d Jes Sorensen
                error_report("error while reading from new backing file");
1324 c2abccec MORITA Kazutaka
                goto out;
1325 3e85c6fd Kevin Wolf
            }
1326 3e85c6fd Kevin Wolf
1327 3e85c6fd Kevin Wolf
            /* If they differ, we need to write to the COW file */
1328 3e85c6fd Kevin Wolf
            uint64_t written = 0;
1329 3e85c6fd Kevin Wolf
1330 3e85c6fd Kevin Wolf
            while (written < n) {
1331 3e85c6fd Kevin Wolf
                int pnum;
1332 3e85c6fd Kevin Wolf
1333 3e85c6fd Kevin Wolf
                if (compare_sectors(buf_old + written * 512,
1334 60b1bd4f Kevin Wolf
                    buf_new + written * 512, n - written, &pnum))
1335 3e85c6fd Kevin Wolf
                {
1336 3e85c6fd Kevin Wolf
                    ret = bdrv_write(bs, sector + written,
1337 3e85c6fd Kevin Wolf
                        buf_old + written * 512, pnum);
1338 3e85c6fd Kevin Wolf
                    if (ret < 0) {
1339 15654a6d Jes Sorensen
                        error_report("Error while writing to COW image: %s",
1340 3e85c6fd Kevin Wolf
                            strerror(-ret));
1341 c2abccec MORITA Kazutaka
                        goto out;
1342 3e85c6fd Kevin Wolf
                    }
1343 3e85c6fd Kevin Wolf
                }
1344 3e85c6fd Kevin Wolf
1345 3e85c6fd Kevin Wolf
                written += pnum;
1346 3e85c6fd Kevin Wolf
            }
1347 3e85c6fd Kevin Wolf
        }
1348 d6771bfa TeLeMan
1349 d6771bfa TeLeMan
        qemu_free(buf_old);
1350 d6771bfa TeLeMan
        qemu_free(buf_new);
1351 3e85c6fd Kevin Wolf
    }
1352 3e85c6fd Kevin Wolf
1353 3e85c6fd Kevin Wolf
    /*
1354 3e85c6fd Kevin Wolf
     * Change the backing file. All clusters that are different from the old
1355 3e85c6fd Kevin Wolf
     * backing file are overwritten in the COW file now, so the visible content
1356 3e85c6fd Kevin Wolf
     * doesn't change when we switch the backing file.
1357 3e85c6fd Kevin Wolf
     */
1358 3e85c6fd Kevin Wolf
    ret = bdrv_change_backing_file(bs, out_baseimg, out_basefmt);
1359 3e85c6fd Kevin Wolf
    if (ret == -ENOSPC) {
1360 15654a6d Jes Sorensen
        error_report("Could not change the backing file to '%s': No "
1361 15654a6d Jes Sorensen
                     "space left in the file header", out_baseimg);
1362 3e85c6fd Kevin Wolf
    } else if (ret < 0) {
1363 15654a6d Jes Sorensen
        error_report("Could not change the backing file to '%s': %s",
1364 3e85c6fd Kevin Wolf
            out_baseimg, strerror(-ret));
1365 3e85c6fd Kevin Wolf
    }
1366 3e85c6fd Kevin Wolf
1367 3e85c6fd Kevin Wolf
    /*
1368 3e85c6fd Kevin Wolf
     * TODO At this point it is possible to check if any clusters that are
1369 3e85c6fd Kevin Wolf
     * allocated in the COW file are the same in the backing file. If so, they
1370 3e85c6fd Kevin Wolf
     * could be dropped from the COW file. Don't do this before switching the
1371 3e85c6fd Kevin Wolf
     * backing file, in case of a crash this would lead to corruption.
1372 3e85c6fd Kevin Wolf
     */
1373 c2abccec MORITA Kazutaka
out:
1374 3e85c6fd Kevin Wolf
    /* Cleanup */
1375 3e85c6fd Kevin Wolf
    if (!unsafe) {
1376 3e85c6fd Kevin Wolf
        bdrv_delete(bs_old_backing);
1377 3e85c6fd Kevin Wolf
        bdrv_delete(bs_new_backing);
1378 3e85c6fd Kevin Wolf
    }
1379 3e85c6fd Kevin Wolf
1380 3e85c6fd Kevin Wolf
    bdrv_delete(bs);
1381 c2abccec MORITA Kazutaka
    if (ret) {
1382 c2abccec MORITA Kazutaka
        return 1;
1383 c2abccec MORITA Kazutaka
    }
1384 3e85c6fd Kevin Wolf
    return 0;
1385 3e85c6fd Kevin Wolf
}
1386 3e85c6fd Kevin Wolf
1387 ae6b0ed6 Stefan Hajnoczi
static int img_resize(int argc, char **argv)
1388 ae6b0ed6 Stefan Hajnoczi
{
1389 ae6b0ed6 Stefan Hajnoczi
    int c, ret, relative;
1390 ae6b0ed6 Stefan Hajnoczi
    const char *filename, *fmt, *size;
1391 ae6b0ed6 Stefan Hajnoczi
    int64_t n, total_size;
1392 2a81998a Jes Sorensen
    BlockDriverState *bs = NULL;
1393 ae6b0ed6 Stefan Hajnoczi
    QEMUOptionParameter *param;
1394 ae6b0ed6 Stefan Hajnoczi
    QEMUOptionParameter resize_options[] = {
1395 ae6b0ed6 Stefan Hajnoczi
        {
1396 ae6b0ed6 Stefan Hajnoczi
            .name = BLOCK_OPT_SIZE,
1397 ae6b0ed6 Stefan Hajnoczi
            .type = OPT_SIZE,
1398 ae6b0ed6 Stefan Hajnoczi
            .help = "Virtual disk size"
1399 ae6b0ed6 Stefan Hajnoczi
        },
1400 ae6b0ed6 Stefan Hajnoczi
        { NULL }
1401 ae6b0ed6 Stefan Hajnoczi
    };
1402 ae6b0ed6 Stefan Hajnoczi
1403 ae6b0ed6 Stefan Hajnoczi
    fmt = NULL;
1404 ae6b0ed6 Stefan Hajnoczi
    for(;;) {
1405 ae6b0ed6 Stefan Hajnoczi
        c = getopt(argc, argv, "f:h");
1406 ae6b0ed6 Stefan Hajnoczi
        if (c == -1) {
1407 ae6b0ed6 Stefan Hajnoczi
            break;
1408 ae6b0ed6 Stefan Hajnoczi
        }
1409 ae6b0ed6 Stefan Hajnoczi
        switch(c) {
1410 ef87394c Jes Sorensen
        case '?':
1411 ae6b0ed6 Stefan Hajnoczi
        case 'h':
1412 ae6b0ed6 Stefan Hajnoczi
            help();
1413 ae6b0ed6 Stefan Hajnoczi
            break;
1414 ae6b0ed6 Stefan Hajnoczi
        case 'f':
1415 ae6b0ed6 Stefan Hajnoczi
            fmt = optarg;
1416 ae6b0ed6 Stefan Hajnoczi
            break;
1417 ae6b0ed6 Stefan Hajnoczi
        }
1418 ae6b0ed6 Stefan Hajnoczi
    }
1419 ae6b0ed6 Stefan Hajnoczi
    if (optind + 1 >= argc) {
1420 ae6b0ed6 Stefan Hajnoczi
        help();
1421 ae6b0ed6 Stefan Hajnoczi
    }
1422 ae6b0ed6 Stefan Hajnoczi
    filename = argv[optind++];
1423 ae6b0ed6 Stefan Hajnoczi
    size = argv[optind++];
1424 ae6b0ed6 Stefan Hajnoczi
1425 ae6b0ed6 Stefan Hajnoczi
    /* Choose grow, shrink, or absolute resize mode */
1426 ae6b0ed6 Stefan Hajnoczi
    switch (size[0]) {
1427 ae6b0ed6 Stefan Hajnoczi
    case '+':
1428 ae6b0ed6 Stefan Hajnoczi
        relative = 1;
1429 ae6b0ed6 Stefan Hajnoczi
        size++;
1430 ae6b0ed6 Stefan Hajnoczi
        break;
1431 ae6b0ed6 Stefan Hajnoczi
    case '-':
1432 ae6b0ed6 Stefan Hajnoczi
        relative = -1;
1433 ae6b0ed6 Stefan Hajnoczi
        size++;
1434 ae6b0ed6 Stefan Hajnoczi
        break;
1435 ae6b0ed6 Stefan Hajnoczi
    default:
1436 ae6b0ed6 Stefan Hajnoczi
        relative = 0;
1437 ae6b0ed6 Stefan Hajnoczi
        break;
1438 ae6b0ed6 Stefan Hajnoczi
    }
1439 ae6b0ed6 Stefan Hajnoczi
1440 ae6b0ed6 Stefan Hajnoczi
    /* Parse size */
1441 ae6b0ed6 Stefan Hajnoczi
    param = parse_option_parameters("", resize_options, NULL);
1442 ae6b0ed6 Stefan Hajnoczi
    if (set_option_parameter(param, BLOCK_OPT_SIZE, size)) {
1443 ae6b0ed6 Stefan Hajnoczi
        /* Error message already printed when size parsing fails */
1444 2a81998a Jes Sorensen
        ret = -1;
1445 2a81998a Jes Sorensen
        goto out;
1446 ae6b0ed6 Stefan Hajnoczi
    }
1447 ae6b0ed6 Stefan Hajnoczi
    n = get_option_parameter(param, BLOCK_OPT_SIZE)->value.n;
1448 ae6b0ed6 Stefan Hajnoczi
    free_option_parameters(param);
1449 ae6b0ed6 Stefan Hajnoczi
1450 ae6b0ed6 Stefan Hajnoczi
    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
1451 c2abccec MORITA Kazutaka
    if (!bs) {
1452 2a81998a Jes Sorensen
        ret = -1;
1453 2a81998a Jes Sorensen
        goto out;
1454 c2abccec MORITA Kazutaka
    }
1455 ae6b0ed6 Stefan Hajnoczi
1456 ae6b0ed6 Stefan Hajnoczi
    if (relative) {
1457 ae6b0ed6 Stefan Hajnoczi
        total_size = bdrv_getlength(bs) + n * relative;
1458 ae6b0ed6 Stefan Hajnoczi
    } else {
1459 ae6b0ed6 Stefan Hajnoczi
        total_size = n;
1460 ae6b0ed6 Stefan Hajnoczi
    }
1461 ae6b0ed6 Stefan Hajnoczi
    if (total_size <= 0) {
1462 15654a6d Jes Sorensen
        error_report("New image size must be positive");
1463 c2abccec MORITA Kazutaka
        ret = -1;
1464 c2abccec MORITA Kazutaka
        goto out;
1465 ae6b0ed6 Stefan Hajnoczi
    }
1466 ae6b0ed6 Stefan Hajnoczi
1467 ae6b0ed6 Stefan Hajnoczi
    ret = bdrv_truncate(bs, total_size);
1468 ae6b0ed6 Stefan Hajnoczi
    switch (ret) {
1469 ae6b0ed6 Stefan Hajnoczi
    case 0:
1470 ae6b0ed6 Stefan Hajnoczi
        printf("Image resized.\n");
1471 ae6b0ed6 Stefan Hajnoczi
        break;
1472 ae6b0ed6 Stefan Hajnoczi
    case -ENOTSUP:
1473 15654a6d Jes Sorensen
        error_report("This image format does not support resize");
1474 ae6b0ed6 Stefan Hajnoczi
        break;
1475 ae6b0ed6 Stefan Hajnoczi
    case -EACCES:
1476 15654a6d Jes Sorensen
        error_report("Image is read-only");
1477 ae6b0ed6 Stefan Hajnoczi
        break;
1478 ae6b0ed6 Stefan Hajnoczi
    default:
1479 15654a6d Jes Sorensen
        error_report("Error resizing image (%d)", -ret);
1480 ae6b0ed6 Stefan Hajnoczi
        break;
1481 ae6b0ed6 Stefan Hajnoczi
    }
1482 c2abccec MORITA Kazutaka
out:
1483 2a81998a Jes Sorensen
    if (bs) {
1484 2a81998a Jes Sorensen
        bdrv_delete(bs);
1485 2a81998a Jes Sorensen
    }
1486 c2abccec MORITA Kazutaka
    if (ret) {
1487 c2abccec MORITA Kazutaka
        return 1;
1488 c2abccec MORITA Kazutaka
    }
1489 ae6b0ed6 Stefan Hajnoczi
    return 0;
1490 ae6b0ed6 Stefan Hajnoczi
}
1491 ae6b0ed6 Stefan Hajnoczi
1492 c227f099 Anthony Liguori
static const img_cmd_t img_cmds[] = {
1493 153859be Stuart Brady
#define DEF(option, callback, arg_string)        \
1494 153859be Stuart Brady
    { option, callback },
1495 153859be Stuart Brady
#include "qemu-img-cmds.h"
1496 153859be Stuart Brady
#undef DEF
1497 153859be Stuart Brady
#undef GEN_DOCS
1498 153859be Stuart Brady
    { NULL, NULL, },
1499 153859be Stuart Brady
};
1500 153859be Stuart Brady
1501 ea2384d3 bellard
int main(int argc, char **argv)
1502 ea2384d3 bellard
{
1503 c227f099 Anthony Liguori
    const img_cmd_t *cmd;
1504 153859be Stuart Brady
    const char *cmdname;
1505 ea2384d3 bellard
1506 53f76e58 Kevin Wolf
    error_set_progname(argv[0]);
1507 53f76e58 Kevin Wolf
1508 ea2384d3 bellard
    bdrv_init();
1509 ea2384d3 bellard
    if (argc < 2)
1510 ea2384d3 bellard
        help();
1511 153859be Stuart Brady
    cmdname = argv[1];
1512 8f9b157e aurel32
    argc--; argv++;
1513 153859be Stuart Brady
1514 153859be Stuart Brady
    /* find the command */
1515 153859be Stuart Brady
    for(cmd = img_cmds; cmd->name != NULL; cmd++) {
1516 153859be Stuart Brady
        if (!strcmp(cmdname, cmd->name)) {
1517 153859be Stuart Brady
            return cmd->handler(argc, argv);
1518 153859be Stuart Brady
        }
1519 ea2384d3 bellard
    }
1520 153859be Stuart Brady
1521 153859be Stuart Brady
    /* not found */
1522 153859be Stuart Brady
    help();
1523 ea2384d3 bellard
    return 0;
1524 ea2384d3 bellard
}