Statistics
| Branch: | Revision:

root / qemu-img.c @ 6b331efb

History | View | Annotate | Download (41.7 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 b9eaf9ec Kevin Wolf
    int ret;
217 75c23805 bellard
218 b9eaf9ec Kevin Wolf
    bs = bdrv_new("image");
219 ad717139 Kevin Wolf
220 75c23805 bellard
    if (fmt) {
221 75c23805 bellard
        drv = bdrv_find_format(fmt);
222 c2abccec MORITA Kazutaka
        if (!drv) {
223 15654a6d Jes Sorensen
            error_report("Unknown file format '%s'", fmt);
224 c2abccec MORITA Kazutaka
            goto fail;
225 c2abccec MORITA Kazutaka
        }
226 75c23805 bellard
    } else {
227 75c23805 bellard
        drv = NULL;
228 75c23805 bellard
    }
229 b9eaf9ec Kevin Wolf
230 b9eaf9ec Kevin Wolf
    ret = bdrv_open(bs, filename, flags, drv);
231 b9eaf9ec Kevin Wolf
    if (ret < 0) {
232 b9eaf9ec Kevin Wolf
        error_report("Could not open '%s': %s", filename, strerror(-ret));
233 c2abccec MORITA Kazutaka
        goto fail;
234 75c23805 bellard
    }
235 b9eaf9ec Kevin Wolf
236 75c23805 bellard
    if (bdrv_is_encrypted(bs)) {
237 75c23805 bellard
        printf("Disk image '%s' is encrypted.\n", filename);
238 c2abccec MORITA Kazutaka
        if (read_password(password, sizeof(password)) < 0) {
239 15654a6d Jes Sorensen
            error_report("No password given");
240 c2abccec MORITA Kazutaka
            goto fail;
241 c2abccec MORITA Kazutaka
        }
242 c2abccec MORITA Kazutaka
        if (bdrv_set_key(bs, password) < 0) {
243 15654a6d Jes Sorensen
            error_report("invalid password");
244 c2abccec MORITA Kazutaka
            goto fail;
245 c2abccec MORITA Kazutaka
        }
246 75c23805 bellard
    }
247 75c23805 bellard
    return bs;
248 c2abccec MORITA Kazutaka
fail:
249 c2abccec MORITA Kazutaka
    if (bs) {
250 c2abccec MORITA Kazutaka
        bdrv_delete(bs);
251 c2abccec MORITA Kazutaka
    }
252 c2abccec MORITA Kazutaka
    return NULL;
253 75c23805 bellard
}
254 75c23805 bellard
255 c2abccec MORITA Kazutaka
static int add_old_style_options(const char *fmt, QEMUOptionParameter *list,
256 eec77d9e Jes Sorensen
                                 const char *base_filename,
257 eec77d9e Jes Sorensen
                                 const char *base_fmt)
258 efa84d43 Kevin Wolf
{
259 efa84d43 Kevin Wolf
    if (base_filename) {
260 efa84d43 Kevin Wolf
        if (set_option_parameter(list, BLOCK_OPT_BACKING_FILE, base_filename)) {
261 15654a6d Jes Sorensen
            error_report("Backing file not supported for file format '%s'",
262 15654a6d Jes Sorensen
                         fmt);
263 c2abccec MORITA Kazutaka
            return -1;
264 efa84d43 Kevin Wolf
        }
265 efa84d43 Kevin Wolf
    }
266 efa84d43 Kevin Wolf
    if (base_fmt) {
267 efa84d43 Kevin Wolf
        if (set_option_parameter(list, BLOCK_OPT_BACKING_FMT, base_fmt)) {
268 15654a6d Jes Sorensen
            error_report("Backing file format not supported for file "
269 15654a6d Jes Sorensen
                         "format '%s'", fmt);
270 c2abccec MORITA Kazutaka
            return -1;
271 efa84d43 Kevin Wolf
        }
272 efa84d43 Kevin Wolf
    }
273 c2abccec MORITA Kazutaka
    return 0;
274 efa84d43 Kevin Wolf
}
275 efa84d43 Kevin Wolf
276 ea2384d3 bellard
static int img_create(int argc, char **argv)
277 ea2384d3 bellard
{
278 eec77d9e Jes Sorensen
    int c, ret = 0;
279 1da7cfbd Jes Sorensen
    uint64_t img_size = -1;
280 ea2384d3 bellard
    const char *fmt = "raw";
281 9230eaf6 aliguori
    const char *base_fmt = NULL;
282 ea2384d3 bellard
    const char *filename;
283 ea2384d3 bellard
    const char *base_filename = NULL;
284 9ea2ea71 Kevin Wolf
    char *options = NULL;
285 3b46e624 ths
286 ea2384d3 bellard
    for(;;) {
287 9ea2ea71 Kevin Wolf
        c = getopt(argc, argv, "F:b:f:he6o:");
288 b8fb60da Jes Sorensen
        if (c == -1) {
289 ea2384d3 bellard
            break;
290 b8fb60da Jes Sorensen
        }
291 ea2384d3 bellard
        switch(c) {
292 ef87394c Jes Sorensen
        case '?':
293 ea2384d3 bellard
        case 'h':
294 ea2384d3 bellard
            help();
295 ea2384d3 bellard
            break;
296 9230eaf6 aliguori
        case 'F':
297 9230eaf6 aliguori
            base_fmt = optarg;
298 9230eaf6 aliguori
            break;
299 ea2384d3 bellard
        case 'b':
300 ea2384d3 bellard
            base_filename = optarg;
301 ea2384d3 bellard
            break;
302 ea2384d3 bellard
        case 'f':
303 ea2384d3 bellard
            fmt = optarg;
304 ea2384d3 bellard
            break;
305 ea2384d3 bellard
        case 'e':
306 15654a6d Jes Sorensen
            error_report("qemu-img: option -e is deprecated, please use \'-o "
307 eec77d9e Jes Sorensen
                  "encryption\' instead!");
308 eec77d9e Jes Sorensen
            return 1;
309 d8871c5a ths
        case '6':
310 15654a6d Jes Sorensen
            error_report("qemu-img: option -6 is deprecated, please use \'-o "
311 eec77d9e Jes Sorensen
                  "compat6\' instead!");
312 eec77d9e Jes Sorensen
            return 1;
313 9ea2ea71 Kevin Wolf
        case 'o':
314 9ea2ea71 Kevin Wolf
            options = optarg;
315 9ea2ea71 Kevin Wolf
            break;
316 ea2384d3 bellard
        }
317 ea2384d3 bellard
    }
318 9230eaf6 aliguori
319 b50cbabc MORITA Kazutaka
    /* Get the filename */
320 b8fb60da Jes Sorensen
    if (optind >= argc) {
321 b50cbabc MORITA Kazutaka
        help();
322 b8fb60da Jes Sorensen
    }
323 b50cbabc MORITA Kazutaka
    filename = argv[optind++];
324 b50cbabc MORITA Kazutaka
325 1da7cfbd Jes Sorensen
    /* Get image size, if specified */
326 1da7cfbd Jes Sorensen
    if (optind < argc) {
327 70b4f4bb Jes Sorensen
        int64_t sval;
328 1da7cfbd Jes Sorensen
        sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);
329 1da7cfbd Jes Sorensen
        if (sval < 0) {
330 15654a6d Jes Sorensen
            error_report("Invalid image size specified! You may use k, M, G or "
331 1da7cfbd Jes Sorensen
                  "T suffixes for ");
332 15654a6d Jes Sorensen
            error_report("kilobytes, megabytes, gigabytes and terabytes.");
333 1da7cfbd Jes Sorensen
            ret = -1;
334 1da7cfbd Jes Sorensen
            goto out;
335 1da7cfbd Jes Sorensen
        }
336 1da7cfbd Jes Sorensen
        img_size = (uint64_t)sval;
337 1da7cfbd Jes Sorensen
    }
338 1da7cfbd Jes Sorensen
339 4ac8aacd Jes Sorensen
    if (options && !strcmp(options, "?")) {
340 4ac8aacd Jes Sorensen
        ret = print_block_option_help(filename, fmt);
341 4ac8aacd Jes Sorensen
        goto out;
342 4ac8aacd Jes Sorensen
    }
343 4ac8aacd Jes Sorensen
344 f88e1a42 Jes Sorensen
    ret = bdrv_img_create(filename, fmt, base_filename, base_fmt,
345 f88e1a42 Jes Sorensen
                          options, img_size, BDRV_O_FLAGS);
346 c2abccec MORITA Kazutaka
out:
347 c2abccec MORITA Kazutaka
    if (ret) {
348 c2abccec MORITA Kazutaka
        return 1;
349 c2abccec MORITA Kazutaka
    }
350 ea2384d3 bellard
    return 0;
351 ea2384d3 bellard
}
352 ea2384d3 bellard
353 e076f338 Kevin Wolf
/*
354 e076f338 Kevin Wolf
 * Checks an image for consistency. Exit codes:
355 e076f338 Kevin Wolf
 *
356 e076f338 Kevin Wolf
 * 0 - Check completed, image is good
357 e076f338 Kevin Wolf
 * 1 - Check not completed because of internal errors
358 e076f338 Kevin Wolf
 * 2 - Check completed, image is corrupted
359 e076f338 Kevin Wolf
 * 3 - Check completed, image has leaked clusters, but is good otherwise
360 e076f338 Kevin Wolf
 */
361 1585969c aliguori
static int img_check(int argc, char **argv)
362 1585969c aliguori
{
363 1585969c aliguori
    int c, ret;
364 1585969c aliguori
    const char *filename, *fmt;
365 1585969c aliguori
    BlockDriverState *bs;
366 e076f338 Kevin Wolf
    BdrvCheckResult result;
367 1585969c aliguori
368 1585969c aliguori
    fmt = NULL;
369 1585969c aliguori
    for(;;) {
370 1585969c aliguori
        c = getopt(argc, argv, "f:h");
371 b8fb60da Jes Sorensen
        if (c == -1) {
372 1585969c aliguori
            break;
373 b8fb60da Jes Sorensen
        }
374 1585969c aliguori
        switch(c) {
375 ef87394c Jes Sorensen
        case '?':
376 1585969c aliguori
        case 'h':
377 1585969c aliguori
            help();
378 1585969c aliguori
            break;
379 1585969c aliguori
        case 'f':
380 1585969c aliguori
            fmt = optarg;
381 1585969c aliguori
            break;
382 1585969c aliguori
        }
383 1585969c aliguori
    }
384 b8fb60da Jes Sorensen
    if (optind >= argc) {
385 1585969c aliguori
        help();
386 b8fb60da Jes Sorensen
    }
387 1585969c aliguori
    filename = argv[optind++];
388 1585969c aliguori
389 adfe078e Stefan Hajnoczi
    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS);
390 c2abccec MORITA Kazutaka
    if (!bs) {
391 c2abccec MORITA Kazutaka
        return 1;
392 c2abccec MORITA Kazutaka
    }
393 e076f338 Kevin Wolf
    ret = bdrv_check(bs, &result);
394 e076f338 Kevin Wolf
395 e076f338 Kevin Wolf
    if (ret == -ENOTSUP) {
396 15654a6d Jes Sorensen
        error_report("This image format does not support checks");
397 e076f338 Kevin Wolf
        bdrv_delete(bs);
398 e076f338 Kevin Wolf
        return 1;
399 e076f338 Kevin Wolf
    }
400 e076f338 Kevin Wolf
401 e076f338 Kevin Wolf
    if (!(result.corruptions || result.leaks || result.check_errors)) {
402 e076f338 Kevin Wolf
        printf("No errors were found on the image.\n");
403 e076f338 Kevin Wolf
    } else {
404 e076f338 Kevin Wolf
        if (result.corruptions) {
405 e076f338 Kevin Wolf
            printf("\n%d errors were found on the image.\n"
406 e076f338 Kevin Wolf
                "Data may be corrupted, or further writes to the image "
407 e076f338 Kevin Wolf
                "may corrupt it.\n",
408 e076f338 Kevin Wolf
                result.corruptions);
409 e076f338 Kevin Wolf
        }
410 e076f338 Kevin Wolf
411 e076f338 Kevin Wolf
        if (result.leaks) {
412 e076f338 Kevin Wolf
            printf("\n%d leaked clusters were found on the image.\n"
413 e076f338 Kevin Wolf
                "This means waste of disk space, but no harm to data.\n",
414 e076f338 Kevin Wolf
                result.leaks);
415 e076f338 Kevin Wolf
        }
416 e076f338 Kevin Wolf
417 e076f338 Kevin Wolf
        if (result.check_errors) {
418 e076f338 Kevin Wolf
            printf("\n%d internal errors have occurred during the check.\n",
419 e076f338 Kevin Wolf
                result.check_errors);
420 1585969c aliguori
        }
421 1585969c aliguori
    }
422 1585969c aliguori
423 1585969c aliguori
    bdrv_delete(bs);
424 e076f338 Kevin Wolf
425 e076f338 Kevin Wolf
    if (ret < 0 || result.check_errors) {
426 e076f338 Kevin Wolf
        printf("\nAn error has occurred during the check: %s\n"
427 e076f338 Kevin Wolf
            "The check is not complete and may have missed error.\n",
428 e076f338 Kevin Wolf
            strerror(-ret));
429 c2abccec MORITA Kazutaka
        return 1;
430 c2abccec MORITA Kazutaka
    }
431 e076f338 Kevin Wolf
432 e076f338 Kevin Wolf
    if (result.corruptions) {
433 e076f338 Kevin Wolf
        return 2;
434 e076f338 Kevin Wolf
    } else if (result.leaks) {
435 e076f338 Kevin Wolf
        return 3;
436 e076f338 Kevin Wolf
    } else {
437 e076f338 Kevin Wolf
        return 0;
438 e076f338 Kevin Wolf
    }
439 1585969c aliguori
}
440 1585969c aliguori
441 ea2384d3 bellard
static int img_commit(int argc, char **argv)
442 ea2384d3 bellard
{
443 ea2384d3 bellard
    int c, ret;
444 ea2384d3 bellard
    const char *filename, *fmt;
445 ea2384d3 bellard
    BlockDriverState *bs;
446 ea2384d3 bellard
447 ea2384d3 bellard
    fmt = NULL;
448 ea2384d3 bellard
    for(;;) {
449 ea2384d3 bellard
        c = getopt(argc, argv, "f:h");
450 b8fb60da Jes Sorensen
        if (c == -1) {
451 ea2384d3 bellard
            break;
452 b8fb60da Jes Sorensen
        }
453 ea2384d3 bellard
        switch(c) {
454 ef87394c Jes Sorensen
        case '?':
455 ea2384d3 bellard
        case 'h':
456 ea2384d3 bellard
            help();
457 ea2384d3 bellard
            break;
458 ea2384d3 bellard
        case 'f':
459 ea2384d3 bellard
            fmt = optarg;
460 ea2384d3 bellard
            break;
461 ea2384d3 bellard
        }
462 ea2384d3 bellard
    }
463 b8fb60da Jes Sorensen
    if (optind >= argc) {
464 ea2384d3 bellard
        help();
465 b8fb60da Jes Sorensen
    }
466 ea2384d3 bellard
    filename = argv[optind++];
467 ea2384d3 bellard
468 adfe078e Stefan Hajnoczi
    bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR);
469 c2abccec MORITA Kazutaka
    if (!bs) {
470 c2abccec MORITA Kazutaka
        return 1;
471 c2abccec MORITA Kazutaka
    }
472 ea2384d3 bellard
    ret = bdrv_commit(bs);
473 ea2384d3 bellard
    switch(ret) {
474 ea2384d3 bellard
    case 0:
475 ea2384d3 bellard
        printf("Image committed.\n");
476 ea2384d3 bellard
        break;
477 ea2384d3 bellard
    case -ENOENT:
478 15654a6d Jes Sorensen
        error_report("No disk inserted");
479 ea2384d3 bellard
        break;
480 ea2384d3 bellard
    case -EACCES:
481 15654a6d Jes Sorensen
        error_report("Image is read-only");
482 ea2384d3 bellard
        break;
483 ea2384d3 bellard
    case -ENOTSUP:
484 15654a6d Jes Sorensen
        error_report("Image is already committed");
485 ea2384d3 bellard
        break;
486 ea2384d3 bellard
    default:
487 15654a6d Jes Sorensen
        error_report("Error while committing image");
488 ea2384d3 bellard
        break;
489 ea2384d3 bellard
    }
490 ea2384d3 bellard
491 ea2384d3 bellard
    bdrv_delete(bs);
492 c2abccec MORITA Kazutaka
    if (ret) {
493 c2abccec MORITA Kazutaka
        return 1;
494 c2abccec MORITA Kazutaka
    }
495 ea2384d3 bellard
    return 0;
496 ea2384d3 bellard
}
497 ea2384d3 bellard
498 ea2384d3 bellard
static int is_not_zero(const uint8_t *sector, int len)
499 ea2384d3 bellard
{
500 ea2384d3 bellard
    int i;
501 ea2384d3 bellard
    len >>= 2;
502 ea2384d3 bellard
    for(i = 0;i < len; i++) {
503 ea2384d3 bellard
        if (((uint32_t *)sector)[i] != 0)
504 ea2384d3 bellard
            return 1;
505 ea2384d3 bellard
    }
506 ea2384d3 bellard
    return 0;
507 ea2384d3 bellard
}
508 ea2384d3 bellard
509 f58c7b35 ths
/*
510 f58c7b35 ths
 * Returns true iff the first sector pointed to by 'buf' contains at least
511 f58c7b35 ths
 * a non-NUL byte.
512 f58c7b35 ths
 *
513 f58c7b35 ths
 * 'pnum' is set to the number of sectors (including and immediately following
514 f58c7b35 ths
 * the first one) that are known to be in the same allocated/unallocated state.
515 f58c7b35 ths
 */
516 ea2384d3 bellard
static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
517 ea2384d3 bellard
{
518 ea2384d3 bellard
    int v, i;
519 ea2384d3 bellard
520 ea2384d3 bellard
    if (n <= 0) {
521 ea2384d3 bellard
        *pnum = 0;
522 ea2384d3 bellard
        return 0;
523 ea2384d3 bellard
    }
524 ea2384d3 bellard
    v = is_not_zero(buf, 512);
525 ea2384d3 bellard
    for(i = 1; i < n; i++) {
526 ea2384d3 bellard
        buf += 512;
527 ea2384d3 bellard
        if (v != is_not_zero(buf, 512))
528 ea2384d3 bellard
            break;
529 ea2384d3 bellard
    }
530 ea2384d3 bellard
    *pnum = i;
531 ea2384d3 bellard
    return v;
532 ea2384d3 bellard
}
533 ea2384d3 bellard
534 3e85c6fd Kevin Wolf
/*
535 3e85c6fd Kevin Wolf
 * Compares two buffers sector by sector. Returns 0 if the first sector of both
536 3e85c6fd Kevin Wolf
 * buffers matches, non-zero otherwise.
537 3e85c6fd Kevin Wolf
 *
538 3e85c6fd Kevin Wolf
 * pnum is set to the number of sectors (including and immediately following
539 3e85c6fd Kevin Wolf
 * the first one) that are known to have the same comparison result
540 3e85c6fd Kevin Wolf
 */
541 3e85c6fd Kevin Wolf
static int compare_sectors(const uint8_t *buf1, const uint8_t *buf2, int n,
542 3e85c6fd Kevin Wolf
    int *pnum)
543 3e85c6fd Kevin Wolf
{
544 3e85c6fd Kevin Wolf
    int res, i;
545 3e85c6fd Kevin Wolf
546 3e85c6fd Kevin Wolf
    if (n <= 0) {
547 3e85c6fd Kevin Wolf
        *pnum = 0;
548 3e85c6fd Kevin Wolf
        return 0;
549 3e85c6fd Kevin Wolf
    }
550 3e85c6fd Kevin Wolf
551 3e85c6fd Kevin Wolf
    res = !!memcmp(buf1, buf2, 512);
552 3e85c6fd Kevin Wolf
    for(i = 1; i < n; i++) {
553 3e85c6fd Kevin Wolf
        buf1 += 512;
554 3e85c6fd Kevin Wolf
        buf2 += 512;
555 3e85c6fd Kevin Wolf
556 3e85c6fd Kevin Wolf
        if (!!memcmp(buf1, buf2, 512) != res) {
557 3e85c6fd Kevin Wolf
            break;
558 3e85c6fd Kevin Wolf
        }
559 3e85c6fd Kevin Wolf
    }
560 3e85c6fd Kevin Wolf
561 3e85c6fd Kevin Wolf
    *pnum = i;
562 3e85c6fd Kevin Wolf
    return res;
563 3e85c6fd Kevin Wolf
}
564 3e85c6fd Kevin Wolf
565 80ee15a6 Kevin Wolf
#define IO_BUF_SIZE (2 * 1024 * 1024)
566 ea2384d3 bellard
567 ea2384d3 bellard
static int img_convert(int argc, char **argv)
568 ea2384d3 bellard
{
569 eec77d9e Jes Sorensen
    int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors;
570 f58c7b35 ths
    const char *fmt, *out_fmt, *out_baseimg, *out_filename;
571 b50cbabc MORITA Kazutaka
    BlockDriver *drv, *proto_drv;
572 c2abccec MORITA Kazutaka
    BlockDriverState **bs = NULL, *out_bs = NULL;
573 96b8f136 ths
    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
574 96b8f136 ths
    uint64_t bs_sectors;
575 c2abccec MORITA Kazutaka
    uint8_t * buf = NULL;
576 ea2384d3 bellard
    const uint8_t *buf1;
577 faea38e7 bellard
    BlockDriverInfo bdi;
578 b50cbabc MORITA Kazutaka
    QEMUOptionParameter *param = NULL, *create_options = NULL;
579 a18953fb Kevin Wolf
    QEMUOptionParameter *out_baseimg_param;
580 efa84d43 Kevin Wolf
    char *options = NULL;
581 51ef6727 edison
    const char *snapshot_name = NULL;
582 ea2384d3 bellard
583 ea2384d3 bellard
    fmt = NULL;
584 ea2384d3 bellard
    out_fmt = "raw";
585 f58c7b35 ths
    out_baseimg = NULL;
586 eec77d9e Jes Sorensen
    compress = 0;
587 ea2384d3 bellard
    for(;;) {
588 51ef6727 edison
        c = getopt(argc, argv, "f:O:B:s:hce6o:");
589 b8fb60da Jes Sorensen
        if (c == -1) {
590 ea2384d3 bellard
            break;
591 b8fb60da Jes Sorensen
        }
592 ea2384d3 bellard
        switch(c) {
593 ef87394c Jes Sorensen
        case '?':
594 ea2384d3 bellard
        case 'h':
595 ea2384d3 bellard
            help();
596 ea2384d3 bellard
            break;
597 ea2384d3 bellard
        case 'f':
598 ea2384d3 bellard
            fmt = optarg;
599 ea2384d3 bellard
            break;
600 ea2384d3 bellard
        case 'O':
601 ea2384d3 bellard
            out_fmt = optarg;
602 ea2384d3 bellard
            break;
603 f58c7b35 ths
        case 'B':
604 f58c7b35 ths
            out_baseimg = optarg;
605 f58c7b35 ths
            break;
606 ea2384d3 bellard
        case 'c':
607 eec77d9e Jes Sorensen
            compress = 1;
608 ea2384d3 bellard
            break;
609 ea2384d3 bellard
        case 'e':
610 15654a6d Jes Sorensen
            error_report("qemu-img: option -e is deprecated, please use \'-o "
611 eec77d9e Jes Sorensen
                  "encryption\' instead!");
612 eec77d9e Jes Sorensen
            return 1;
613 ec36ba14 ths
        case '6':
614 15654a6d Jes Sorensen
            error_report("qemu-img: option -6 is deprecated, please use \'-o "
615 eec77d9e Jes Sorensen
                  "compat6\' instead!");
616 eec77d9e Jes Sorensen
            return 1;
617 efa84d43 Kevin Wolf
        case 'o':
618 efa84d43 Kevin Wolf
            options = optarg;
619 efa84d43 Kevin Wolf
            break;
620 51ef6727 edison
        case 's':
621 51ef6727 edison
            snapshot_name = optarg;
622 51ef6727 edison
            break;
623 ea2384d3 bellard
        }
624 ea2384d3 bellard
    }
625 3b46e624 ths
626 926c2d23 balrog
    bs_n = argc - optind - 1;
627 b8fb60da Jes Sorensen
    if (bs_n < 1) {
628 b8fb60da Jes Sorensen
        help();
629 b8fb60da Jes Sorensen
    }
630 926c2d23 balrog
631 926c2d23 balrog
    out_filename = argv[argc - 1];
632 f58c7b35 ths
633 4ac8aacd Jes Sorensen
    if (options && !strcmp(options, "?")) {
634 4ac8aacd Jes Sorensen
        ret = print_block_option_help(out_filename, out_fmt);
635 4ac8aacd Jes Sorensen
        goto out;
636 4ac8aacd Jes Sorensen
    }
637 4ac8aacd Jes Sorensen
638 c2abccec MORITA Kazutaka
    if (bs_n > 1 && out_baseimg) {
639 15654a6d Jes Sorensen
        error_report("-B makes no sense when concatenating multiple input "
640 15654a6d Jes Sorensen
                     "images");
641 31ca34b8 Jes Sorensen
        ret = -1;
642 31ca34b8 Jes Sorensen
        goto out;
643 c2abccec MORITA Kazutaka
    }
644 926c2d23 balrog
        
645 5bdf61fd Jes Sorensen
    bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *));
646 926c2d23 balrog
647 926c2d23 balrog
    total_sectors = 0;
648 926c2d23 balrog
    for (bs_i = 0; bs_i < bs_n; bs_i++) {
649 adfe078e Stefan Hajnoczi
        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS);
650 c2abccec MORITA Kazutaka
        if (!bs[bs_i]) {
651 15654a6d Jes Sorensen
            error_report("Could not open '%s'", argv[optind + bs_i]);
652 c2abccec MORITA Kazutaka
            ret = -1;
653 c2abccec MORITA Kazutaka
            goto out;
654 c2abccec MORITA Kazutaka
        }
655 926c2d23 balrog
        bdrv_get_geometry(bs[bs_i], &bs_sectors);
656 926c2d23 balrog
        total_sectors += bs_sectors;
657 926c2d23 balrog
    }
658 ea2384d3 bellard
659 51ef6727 edison
    if (snapshot_name != NULL) {
660 51ef6727 edison
        if (bs_n > 1) {
661 15654a6d Jes Sorensen
            error_report("No support for concatenating multiple snapshot\n");
662 51ef6727 edison
            ret = -1;
663 51ef6727 edison
            goto out;
664 51ef6727 edison
        }
665 51ef6727 edison
        if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) {
666 15654a6d Jes Sorensen
            error_report("Failed to load snapshot\n");
667 51ef6727 edison
            ret = -1;
668 51ef6727 edison
            goto out;
669 51ef6727 edison
        }
670 51ef6727 edison
    }
671 51ef6727 edison
672 efa84d43 Kevin Wolf
    /* Find driver and parse its options */
673 ea2384d3 bellard
    drv = bdrv_find_format(out_fmt);
674 c2abccec MORITA Kazutaka
    if (!drv) {
675 15654a6d Jes Sorensen
        error_report("Unknown file format '%s'", out_fmt);
676 c2abccec MORITA Kazutaka
        ret = -1;
677 c2abccec MORITA Kazutaka
        goto out;
678 c2abccec MORITA Kazutaka
    }
679 efa84d43 Kevin Wolf
680 b50cbabc MORITA Kazutaka
    proto_drv = bdrv_find_protocol(out_filename);
681 c2abccec MORITA Kazutaka
    if (!proto_drv) {
682 15654a6d Jes Sorensen
        error_report("Unknown protocol '%s'", out_filename);
683 c2abccec MORITA Kazutaka
        ret = -1;
684 c2abccec MORITA Kazutaka
        goto out;
685 c2abccec MORITA Kazutaka
    }
686 b50cbabc MORITA Kazutaka
687 b50cbabc MORITA Kazutaka
    create_options = append_option_parameters(create_options,
688 b50cbabc MORITA Kazutaka
                                              drv->create_options);
689 b50cbabc MORITA Kazutaka
    create_options = append_option_parameters(create_options,
690 b50cbabc MORITA Kazutaka
                                              proto_drv->create_options);
691 db08adf5 Kevin Wolf
692 efa84d43 Kevin Wolf
    if (options) {
693 b50cbabc MORITA Kazutaka
        param = parse_option_parameters(options, create_options, param);
694 efa84d43 Kevin Wolf
        if (param == NULL) {
695 15654a6d Jes Sorensen
            error_report("Invalid options for file format '%s'.", out_fmt);
696 c2abccec MORITA Kazutaka
            ret = -1;
697 c2abccec MORITA Kazutaka
            goto out;
698 efa84d43 Kevin Wolf
        }
699 efa84d43 Kevin Wolf
    } else {
700 b50cbabc MORITA Kazutaka
        param = parse_option_parameters("", create_options, param);
701 efa84d43 Kevin Wolf
    }
702 efa84d43 Kevin Wolf
703 efa84d43 Kevin Wolf
    set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
704 eec77d9e Jes Sorensen
    ret = add_old_style_options(out_fmt, param, out_baseimg, NULL);
705 c2abccec MORITA Kazutaka
    if (ret < 0) {
706 c2abccec MORITA Kazutaka
        goto out;
707 c2abccec MORITA Kazutaka
    }
708 efa84d43 Kevin Wolf
709 a18953fb Kevin Wolf
    /* Get backing file name if -o backing_file was used */
710 a18953fb Kevin Wolf
    out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE);
711 a18953fb Kevin Wolf
    if (out_baseimg_param) {
712 a18953fb Kevin Wolf
        out_baseimg = out_baseimg_param->value.s;
713 a18953fb Kevin Wolf
    }
714 a18953fb Kevin Wolf
715 efa84d43 Kevin Wolf
    /* Check if compression is supported */
716 eec77d9e Jes Sorensen
    if (compress) {
717 efa84d43 Kevin Wolf
        QEMUOptionParameter *encryption =
718 efa84d43 Kevin Wolf
            get_option_parameter(param, BLOCK_OPT_ENCRYPT);
719 efa84d43 Kevin Wolf
720 efa84d43 Kevin Wolf
        if (!drv->bdrv_write_compressed) {
721 15654a6d Jes Sorensen
            error_report("Compression not supported for this file format");
722 c2abccec MORITA Kazutaka
            ret = -1;
723 c2abccec MORITA Kazutaka
            goto out;
724 efa84d43 Kevin Wolf
        }
725 efa84d43 Kevin Wolf
726 efa84d43 Kevin Wolf
        if (encryption && encryption->value.n) {
727 15654a6d Jes Sorensen
            error_report("Compression and encryption not supported at "
728 15654a6d Jes Sorensen
                         "the same time");
729 c2abccec MORITA Kazutaka
            ret = -1;
730 c2abccec MORITA Kazutaka
            goto out;
731 efa84d43 Kevin Wolf
        }
732 efa84d43 Kevin Wolf
    }
733 efa84d43 Kevin Wolf
734 efa84d43 Kevin Wolf
    /* Create the new image */
735 efa84d43 Kevin Wolf
    ret = bdrv_create(drv, out_filename, param);
736 ea2384d3 bellard
    if (ret < 0) {
737 ea2384d3 bellard
        if (ret == -ENOTSUP) {
738 15654a6d Jes Sorensen
            error_report("Formatting not supported for file format '%s'",
739 15654a6d Jes Sorensen
                         out_fmt);
740 6e9ea0c0 aurel32
        } else if (ret == -EFBIG) {
741 15654a6d Jes Sorensen
            error_report("The image size is too large for file format '%s'",
742 15654a6d Jes Sorensen
                         out_fmt);
743 ea2384d3 bellard
        } else {
744 15654a6d Jes Sorensen
            error_report("%s: error while converting %s: %s",
745 15654a6d Jes Sorensen
                         out_filename, out_fmt, strerror(-ret));
746 ea2384d3 bellard
        }
747 c2abccec MORITA Kazutaka
        goto out;
748 ea2384d3 bellard
    }
749 3b46e624 ths
750 1bd8e175 Kevin Wolf
    out_bs = bdrv_new_open(out_filename, out_fmt,
751 1bd8e175 Kevin Wolf
        BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH);
752 c2abccec MORITA Kazutaka
    if (!out_bs) {
753 c2abccec MORITA Kazutaka
        ret = -1;
754 c2abccec MORITA Kazutaka
        goto out;
755 c2abccec MORITA Kazutaka
    }
756 ea2384d3 bellard
757 926c2d23 balrog
    bs_i = 0;
758 926c2d23 balrog
    bs_offset = 0;
759 926c2d23 balrog
    bdrv_get_geometry(bs[0], &bs_sectors);
760 d6771bfa TeLeMan
    buf = qemu_malloc(IO_BUF_SIZE);
761 926c2d23 balrog
762 eec77d9e Jes Sorensen
    if (compress) {
763 c2abccec MORITA Kazutaka
        ret = bdrv_get_info(out_bs, &bdi);
764 c2abccec MORITA Kazutaka
        if (ret < 0) {
765 15654a6d Jes Sorensen
            error_report("could not get block driver info");
766 c2abccec MORITA Kazutaka
            goto out;
767 c2abccec MORITA Kazutaka
        }
768 faea38e7 bellard
        cluster_size = bdi.cluster_size;
769 c2abccec MORITA Kazutaka
        if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) {
770 15654a6d Jes Sorensen
            error_report("invalid cluster size");
771 c2abccec MORITA Kazutaka
            ret = -1;
772 c2abccec MORITA Kazutaka
            goto out;
773 c2abccec MORITA Kazutaka
        }
774 ea2384d3 bellard
        cluster_sectors = cluster_size >> 9;
775 ea2384d3 bellard
        sector_num = 0;
776 ea2384d3 bellard
        for(;;) {
777 926c2d23 balrog
            int64_t bs_num;
778 926c2d23 balrog
            int remainder;
779 926c2d23 balrog
            uint8_t *buf2;
780 926c2d23 balrog
781 ea2384d3 bellard
            nb_sectors = total_sectors - sector_num;
782 ea2384d3 bellard
            if (nb_sectors <= 0)
783 ea2384d3 bellard
                break;
784 ea2384d3 bellard
            if (nb_sectors >= cluster_sectors)
785 ea2384d3 bellard
                n = cluster_sectors;
786 ea2384d3 bellard
            else
787 ea2384d3 bellard
                n = nb_sectors;
788 926c2d23 balrog
789 926c2d23 balrog
            bs_num = sector_num - bs_offset;
790 926c2d23 balrog
            assert (bs_num >= 0);
791 926c2d23 balrog
            remainder = n;
792 926c2d23 balrog
            buf2 = buf;
793 926c2d23 balrog
            while (remainder > 0) {
794 926c2d23 balrog
                int nlow;
795 926c2d23 balrog
                while (bs_num == bs_sectors) {
796 926c2d23 balrog
                    bs_i++;
797 926c2d23 balrog
                    assert (bs_i < bs_n);
798 926c2d23 balrog
                    bs_offset += bs_sectors;
799 926c2d23 balrog
                    bdrv_get_geometry(bs[bs_i], &bs_sectors);
800 926c2d23 balrog
                    bs_num = 0;
801 0bfcd599 Blue Swirl
                    /* printf("changing part: sector_num=%" PRId64 ", "
802 0bfcd599 Blue Swirl
                       "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
803 0bfcd599 Blue Swirl
                       "\n", sector_num, bs_i, bs_offset, bs_sectors); */
804 926c2d23 balrog
                }
805 926c2d23 balrog
                assert (bs_num < bs_sectors);
806 926c2d23 balrog
807 926c2d23 balrog
                nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
808 926c2d23 balrog
809 c2abccec MORITA Kazutaka
                ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow);
810 c2abccec MORITA Kazutaka
                if (ret < 0) {
811 15654a6d Jes Sorensen
                    error_report("error while reading");
812 c2abccec MORITA Kazutaka
                    goto out;
813 c2abccec MORITA Kazutaka
                }
814 926c2d23 balrog
815 926c2d23 balrog
                buf2 += nlow * 512;
816 926c2d23 balrog
                bs_num += nlow;
817 926c2d23 balrog
818 926c2d23 balrog
                remainder -= nlow;
819 926c2d23 balrog
            }
820 926c2d23 balrog
            assert (remainder == 0);
821 926c2d23 balrog
822 b8fb60da Jes Sorensen
            if (n < cluster_sectors) {
823 ea2384d3 bellard
                memset(buf + n * 512, 0, cluster_size - n * 512);
824 b8fb60da Jes Sorensen
            }
825 ea2384d3 bellard
            if (is_not_zero(buf, cluster_size)) {
826 c2abccec MORITA Kazutaka
                ret = bdrv_write_compressed(out_bs, sector_num, buf,
827 c2abccec MORITA Kazutaka
                                            cluster_sectors);
828 c2abccec MORITA Kazutaka
                if (ret != 0) {
829 15654a6d Jes Sorensen
                    error_report("error while compressing sector %" PRId64,
830 ec3757de bellard
                          sector_num);
831 c2abccec MORITA Kazutaka
                    goto out;
832 c2abccec MORITA Kazutaka
                }
833 ea2384d3 bellard
            }
834 ea2384d3 bellard
            sector_num += n;
835 ea2384d3 bellard
        }
836 faea38e7 bellard
        /* signal EOF to align */
837 faea38e7 bellard
        bdrv_write_compressed(out_bs, 0, NULL, 0);
838 ea2384d3 bellard
    } else {
839 f2feebbd Kevin Wolf
        int has_zero_init = bdrv_has_zero_init(out_bs);
840 f2feebbd Kevin Wolf
841 f58c7b35 ths
        sector_num = 0; // total number of sectors converted so far
842 ea2384d3 bellard
        for(;;) {
843 ea2384d3 bellard
            nb_sectors = total_sectors - sector_num;
844 b8fb60da Jes Sorensen
            if (nb_sectors <= 0) {
845 ea2384d3 bellard
                break;
846 b8fb60da Jes Sorensen
            }
847 b8fb60da Jes Sorensen
            if (nb_sectors >= (IO_BUF_SIZE / 512)) {
848 ea2384d3 bellard
                n = (IO_BUF_SIZE / 512);
849 b8fb60da Jes Sorensen
            } else {
850 ea2384d3 bellard
                n = nb_sectors;
851 b8fb60da Jes Sorensen
            }
852 926c2d23 balrog
853 926c2d23 balrog
            while (sector_num - bs_offset >= bs_sectors) {
854 926c2d23 balrog
                bs_i ++;
855 926c2d23 balrog
                assert (bs_i < bs_n);
856 926c2d23 balrog
                bs_offset += bs_sectors;
857 926c2d23 balrog
                bdrv_get_geometry(bs[bs_i], &bs_sectors);
858 0bfcd599 Blue Swirl
                /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
859 0bfcd599 Blue Swirl
                  "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
860 926c2d23 balrog
                   sector_num, bs_i, bs_offset, bs_sectors); */
861 926c2d23 balrog
            }
862 926c2d23 balrog
863 b8fb60da Jes Sorensen
            if (n > bs_offset + bs_sectors - sector_num) {
864 926c2d23 balrog
                n = bs_offset + bs_sectors - sector_num;
865 b8fb60da Jes Sorensen
            }
866 926c2d23 balrog
867 f2feebbd Kevin Wolf
            if (has_zero_init) {
868 d032044f Akkarit Sangpetch
                /* If the output image is being created as a copy on write image,
869 d032044f Akkarit Sangpetch
                   assume that sectors which are unallocated in the input image
870 d032044f Akkarit Sangpetch
                   are present in both the output's and input's base images (no
871 d032044f Akkarit Sangpetch
                   need to copy them). */
872 d032044f Akkarit Sangpetch
                if (out_baseimg) {
873 d032044f Akkarit Sangpetch
                    if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
874 d032044f Akkarit Sangpetch
                                           n, &n1)) {
875 d032044f Akkarit Sangpetch
                        sector_num += n1;
876 d032044f Akkarit Sangpetch
                        continue;
877 d032044f Akkarit Sangpetch
                    }
878 d032044f Akkarit Sangpetch
                    /* The next 'n1' sectors are allocated in the input image. Copy
879 d032044f Akkarit Sangpetch
                       only those as they may be followed by unallocated sectors. */
880 d032044f Akkarit Sangpetch
                    n = n1;
881 93c65b47 aliguori
                }
882 93c65b47 aliguori
            } else {
883 93c65b47 aliguori
                n1 = n;
884 f58c7b35 ths
            }
885 f58c7b35 ths
886 c2abccec MORITA Kazutaka
            ret = bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n);
887 c2abccec MORITA Kazutaka
            if (ret < 0) {
888 15654a6d Jes Sorensen
                error_report("error while reading");
889 c2abccec MORITA Kazutaka
                goto out;
890 c2abccec MORITA Kazutaka
            }
891 ea2384d3 bellard
            /* NOTE: at the same time we convert, we do not write zero
892 ea2384d3 bellard
               sectors to have a chance to compress the image. Ideally, we
893 ea2384d3 bellard
               should add a specific call to have the info to go faster */
894 ea2384d3 bellard
            buf1 = buf;
895 ea2384d3 bellard
            while (n > 0) {
896 f58c7b35 ths
                /* If the output image is being created as a copy on write image,
897 f58c7b35 ths
                   copy all sectors even the ones containing only NUL bytes,
898 93c65b47 aliguori
                   because they may differ from the sectors in the base image.
899 93c65b47 aliguori

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