Statistics
| Branch: | Revision:

root / qemu-img.c @ 075e36b8

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

779 93c65b47 aliguori
                   If the output is to a host device, we also write out
780 93c65b47 aliguori
                   sectors that are entirely 0, since whatever data was
781 93c65b47 aliguori
                   already there is garbage, not 0s. */
782 5efa9d5a Anthony Liguori
                if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg ||
783 93c65b47 aliguori
                    is_allocated_sectors(buf1, n, &n1)) {
784 5fafdf24 ths
                    if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
785 ea2384d3 bellard
                        error("error while writing");
786 ea2384d3 bellard
                }
787 ea2384d3 bellard
                sector_num += n1;
788 ea2384d3 bellard
                n -= n1;
789 ea2384d3 bellard
                buf1 += n1 * 512;
790 ea2384d3 bellard
            }
791 ea2384d3 bellard
        }
792 ea2384d3 bellard
    }
793 ea2384d3 bellard
    bdrv_delete(out_bs);
794 926c2d23 balrog
    for (bs_i = 0; bs_i < bs_n; bs_i++)
795 926c2d23 balrog
        bdrv_delete(bs[bs_i]);
796 926c2d23 balrog
    free(bs);
797 ea2384d3 bellard
    return 0;
798 ea2384d3 bellard
}
799 ea2384d3 bellard
800 57d1a2b6 bellard
#ifdef _WIN32
801 57d1a2b6 bellard
static int64_t get_allocated_file_size(const char *filename)
802 57d1a2b6 bellard
{
803 e8445331 bellard
    typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
804 e8445331 bellard
    get_compressed_t get_compressed;
805 57d1a2b6 bellard
    struct _stati64 st;
806 e8445331 bellard
807 e8445331 bellard
    /* WinNT support GetCompressedFileSize to determine allocate size */
808 e8445331 bellard
    get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
809 e8445331 bellard
    if (get_compressed) {
810 e8445331 bellard
            DWORD high, low;
811 e8445331 bellard
            low = get_compressed(filename, &high);
812 e8445331 bellard
            if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
813 e8445331 bellard
            return (((int64_t) high) << 32) + low;
814 e8445331 bellard
    }
815 e8445331 bellard
816 5fafdf24 ths
    if (_stati64(filename, &st) < 0)
817 57d1a2b6 bellard
        return -1;
818 57d1a2b6 bellard
    return st.st_size;
819 57d1a2b6 bellard
}
820 57d1a2b6 bellard
#else
821 57d1a2b6 bellard
static int64_t get_allocated_file_size(const char *filename)
822 57d1a2b6 bellard
{
823 57d1a2b6 bellard
    struct stat st;
824 5fafdf24 ths
    if (stat(filename, &st) < 0)
825 57d1a2b6 bellard
        return -1;
826 57d1a2b6 bellard
    return (int64_t)st.st_blocks * 512;
827 57d1a2b6 bellard
}
828 57d1a2b6 bellard
#endif
829 57d1a2b6 bellard
830 faea38e7 bellard
static void dump_snapshots(BlockDriverState *bs)
831 faea38e7 bellard
{
832 faea38e7 bellard
    QEMUSnapshotInfo *sn_tab, *sn;
833 faea38e7 bellard
    int nb_sns, i;
834 faea38e7 bellard
    char buf[256];
835 faea38e7 bellard
836 faea38e7 bellard
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
837 faea38e7 bellard
    if (nb_sns <= 0)
838 faea38e7 bellard
        return;
839 faea38e7 bellard
    printf("Snapshot list:\n");
840 faea38e7 bellard
    printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
841 faea38e7 bellard
    for(i = 0; i < nb_sns; i++) {
842 faea38e7 bellard
        sn = &sn_tab[i];
843 faea38e7 bellard
        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
844 faea38e7 bellard
    }
845 faea38e7 bellard
    qemu_free(sn_tab);
846 faea38e7 bellard
}
847 faea38e7 bellard
848 ea2384d3 bellard
static int img_info(int argc, char **argv)
849 ea2384d3 bellard
{
850 ea2384d3 bellard
    int c;
851 ea2384d3 bellard
    const char *filename, *fmt;
852 ea2384d3 bellard
    BlockDriver *drv;
853 ea2384d3 bellard
    BlockDriverState *bs;
854 ea2384d3 bellard
    char fmt_name[128], size_buf[128], dsize_buf[128];
855 96b8f136 ths
    uint64_t total_sectors;
856 96b8f136 ths
    int64_t allocated_size;
857 93b6b2a3 bellard
    char backing_filename[1024];
858 93b6b2a3 bellard
    char backing_filename2[1024];
859 faea38e7 bellard
    BlockDriverInfo bdi;
860 ea2384d3 bellard
861 ea2384d3 bellard
    fmt = NULL;
862 ea2384d3 bellard
    for(;;) {
863 ea2384d3 bellard
        c = getopt(argc, argv, "f:h");
864 ea2384d3 bellard
        if (c == -1)
865 ea2384d3 bellard
            break;
866 ea2384d3 bellard
        switch(c) {
867 ea2384d3 bellard
        case 'h':
868 ea2384d3 bellard
            help();
869 ea2384d3 bellard
            break;
870 ea2384d3 bellard
        case 'f':
871 ea2384d3 bellard
            fmt = optarg;
872 ea2384d3 bellard
            break;
873 ea2384d3 bellard
        }
874 ea2384d3 bellard
    }
875 5fafdf24 ths
    if (optind >= argc)
876 ea2384d3 bellard
        help();
877 ea2384d3 bellard
    filename = argv[optind++];
878 ea2384d3 bellard
879 ea2384d3 bellard
    bs = bdrv_new("");
880 ea2384d3 bellard
    if (!bs)
881 ea2384d3 bellard
        error("Not enough memory");
882 ea2384d3 bellard
    if (fmt) {
883 ea2384d3 bellard
        drv = bdrv_find_format(fmt);
884 ea2384d3 bellard
        if (!drv)
885 ea2384d3 bellard
            error("Unknown file format '%s'", fmt);
886 ea2384d3 bellard
    } else {
887 ea2384d3 bellard
        drv = NULL;
888 ea2384d3 bellard
    }
889 137519ce aurel32
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
890 ea2384d3 bellard
        error("Could not open '%s'", filename);
891 ea2384d3 bellard
    }
892 ea2384d3 bellard
    bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
893 ea2384d3 bellard
    bdrv_get_geometry(bs, &total_sectors);
894 ea2384d3 bellard
    get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
895 57d1a2b6 bellard
    allocated_size = get_allocated_file_size(filename);
896 57d1a2b6 bellard
    if (allocated_size < 0)
897 a10ea30b blueswir1
        snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
898 de167e41 bellard
    else
899 5fafdf24 ths
        get_human_readable_size(dsize_buf, sizeof(dsize_buf),
900 de167e41 bellard
                                allocated_size);
901 ea2384d3 bellard
    printf("image: %s\n"
902 ea2384d3 bellard
           "file format: %s\n"
903 ec3757de bellard
           "virtual size: %s (%" PRId64 " bytes)\n"
904 ea2384d3 bellard
           "disk size: %s\n",
905 5fafdf24 ths
           filename, fmt_name, size_buf,
906 ec3757de bellard
           (total_sectors * 512),
907 ea2384d3 bellard
           dsize_buf);
908 ea2384d3 bellard
    if (bdrv_is_encrypted(bs))
909 ea2384d3 bellard
        printf("encrypted: yes\n");
910 faea38e7 bellard
    if (bdrv_get_info(bs, &bdi) >= 0) {
911 5fafdf24 ths
        if (bdi.cluster_size != 0)
912 faea38e7 bellard
            printf("cluster_size: %d\n", bdi.cluster_size);
913 faea38e7 bellard
    }
914 93b6b2a3 bellard
    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
915 faea38e7 bellard
    if (backing_filename[0] != '\0') {
916 93b6b2a3 bellard
        path_combine(backing_filename2, sizeof(backing_filename2),
917 93b6b2a3 bellard
                     filename, backing_filename);
918 5fafdf24 ths
        printf("backing file: %s (actual path: %s)\n",
919 93b6b2a3 bellard
               backing_filename,
920 93b6b2a3 bellard
               backing_filename2);
921 faea38e7 bellard
    }
922 faea38e7 bellard
    dump_snapshots(bs);
923 ea2384d3 bellard
    bdrv_delete(bs);
924 ea2384d3 bellard
    return 0;
925 ea2384d3 bellard
}
926 ea2384d3 bellard
927 f7b4a940 aliguori
#define SNAPSHOT_LIST   1
928 f7b4a940 aliguori
#define SNAPSHOT_CREATE 2
929 f7b4a940 aliguori
#define SNAPSHOT_APPLY  3
930 f7b4a940 aliguori
#define SNAPSHOT_DELETE 4
931 f7b4a940 aliguori
932 153859be Stuart Brady
static int img_snapshot(int argc, char **argv)
933 f7b4a940 aliguori
{
934 f7b4a940 aliguori
    BlockDriverState *bs;
935 f7b4a940 aliguori
    QEMUSnapshotInfo sn;
936 f7b4a940 aliguori
    char *filename, *snapshot_name = NULL;
937 40a4539e aliguori
    int c, ret;
938 f7b4a940 aliguori
    int action = 0;
939 f7b4a940 aliguori
    qemu_timeval tv;
940 f7b4a940 aliguori
941 f7b4a940 aliguori
    /* Parse commandline parameters */
942 f7b4a940 aliguori
    for(;;) {
943 f7b4a940 aliguori
        c = getopt(argc, argv, "la:c:d:h");
944 f7b4a940 aliguori
        if (c == -1)
945 f7b4a940 aliguori
            break;
946 f7b4a940 aliguori
        switch(c) {
947 f7b4a940 aliguori
        case 'h':
948 f7b4a940 aliguori
            help();
949 153859be Stuart Brady
            return 0;
950 f7b4a940 aliguori
        case 'l':
951 f7b4a940 aliguori
            if (action) {
952 f7b4a940 aliguori
                help();
953 153859be Stuart Brady
                return 0;
954 f7b4a940 aliguori
            }
955 f7b4a940 aliguori
            action = SNAPSHOT_LIST;
956 f7b4a940 aliguori
            break;
957 f7b4a940 aliguori
        case 'a':
958 f7b4a940 aliguori
            if (action) {
959 f7b4a940 aliguori
                help();
960 153859be Stuart Brady
                return 0;
961 f7b4a940 aliguori
            }
962 f7b4a940 aliguori
            action = SNAPSHOT_APPLY;
963 f7b4a940 aliguori
            snapshot_name = optarg;
964 f7b4a940 aliguori
            break;
965 f7b4a940 aliguori
        case 'c':
966 f7b4a940 aliguori
            if (action) {
967 f7b4a940 aliguori
                help();
968 153859be Stuart Brady
                return 0;
969 f7b4a940 aliguori
            }
970 f7b4a940 aliguori
            action = SNAPSHOT_CREATE;
971 f7b4a940 aliguori
            snapshot_name = optarg;
972 f7b4a940 aliguori
            break;
973 f7b4a940 aliguori
        case 'd':
974 f7b4a940 aliguori
            if (action) {
975 f7b4a940 aliguori
                help();
976 153859be Stuart Brady
                return 0;
977 f7b4a940 aliguori
            }
978 f7b4a940 aliguori
            action = SNAPSHOT_DELETE;
979 f7b4a940 aliguori
            snapshot_name = optarg;
980 f7b4a940 aliguori
            break;
981 f7b4a940 aliguori
        }
982 f7b4a940 aliguori
    }
983 f7b4a940 aliguori
984 f7b4a940 aliguori
    if (optind >= argc)
985 f7b4a940 aliguori
        help();
986 f7b4a940 aliguori
    filename = argv[optind++];
987 f7b4a940 aliguori
988 f7b4a940 aliguori
    /* Open the image */
989 f7b4a940 aliguori
    bs = bdrv_new("");
990 f7b4a940 aliguori
    if (!bs)
991 f7b4a940 aliguori
        error("Not enough memory");
992 f7b4a940 aliguori
993 f7b4a940 aliguori
    if (bdrv_open2(bs, filename, 0, NULL) < 0) {
994 f7b4a940 aliguori
        error("Could not open '%s'", filename);
995 f7b4a940 aliguori
    }
996 f7b4a940 aliguori
997 f7b4a940 aliguori
    /* Perform the requested action */
998 f7b4a940 aliguori
    switch(action) {
999 f7b4a940 aliguori
    case SNAPSHOT_LIST:
1000 f7b4a940 aliguori
        dump_snapshots(bs);
1001 f7b4a940 aliguori
        break;
1002 f7b4a940 aliguori
1003 f7b4a940 aliguori
    case SNAPSHOT_CREATE:
1004 f7b4a940 aliguori
        memset(&sn, 0, sizeof(sn));
1005 f7b4a940 aliguori
        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
1006 f7b4a940 aliguori
1007 f7b4a940 aliguori
        qemu_gettimeofday(&tv);
1008 f7b4a940 aliguori
        sn.date_sec = tv.tv_sec;
1009 f7b4a940 aliguori
        sn.date_nsec = tv.tv_usec * 1000;
1010 f7b4a940 aliguori
1011 f7b4a940 aliguori
        ret = bdrv_snapshot_create(bs, &sn);
1012 f7b4a940 aliguori
        if (ret)
1013 f7b4a940 aliguori
            error("Could not create snapshot '%s': %d (%s)",
1014 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
1015 f7b4a940 aliguori
        break;
1016 f7b4a940 aliguori
1017 f7b4a940 aliguori
    case SNAPSHOT_APPLY:
1018 f7b4a940 aliguori
        ret = bdrv_snapshot_goto(bs, snapshot_name);
1019 f7b4a940 aliguori
        if (ret)
1020 f7b4a940 aliguori
            error("Could not apply snapshot '%s': %d (%s)",
1021 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
1022 f7b4a940 aliguori
        break;
1023 f7b4a940 aliguori
1024 f7b4a940 aliguori
    case SNAPSHOT_DELETE:
1025 f7b4a940 aliguori
        ret = bdrv_snapshot_delete(bs, snapshot_name);
1026 f7b4a940 aliguori
        if (ret)
1027 f7b4a940 aliguori
            error("Could not delete snapshot '%s': %d (%s)",
1028 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
1029 f7b4a940 aliguori
        break;
1030 f7b4a940 aliguori
    }
1031 f7b4a940 aliguori
1032 f7b4a940 aliguori
    /* Cleanup */
1033 f7b4a940 aliguori
    bdrv_delete(bs);
1034 153859be Stuart Brady
1035 153859be Stuart Brady
    return 0;
1036 f7b4a940 aliguori
}
1037 f7b4a940 aliguori
1038 153859be Stuart Brady
static const img_cmd_t img_cmds[] = {
1039 153859be Stuart Brady
#define DEF(option, callback, arg_string)        \
1040 153859be Stuart Brady
    { option, callback },
1041 153859be Stuart Brady
#include "qemu-img-cmds.h"
1042 153859be Stuart Brady
#undef DEF
1043 153859be Stuart Brady
#undef GEN_DOCS
1044 153859be Stuart Brady
    { NULL, NULL, },
1045 153859be Stuart Brady
};
1046 153859be Stuart Brady
1047 ea2384d3 bellard
int main(int argc, char **argv)
1048 ea2384d3 bellard
{
1049 153859be Stuart Brady
    const img_cmd_t *cmd;
1050 153859be Stuart Brady
    const char *cmdname;
1051 ea2384d3 bellard
1052 ea2384d3 bellard
    bdrv_init();
1053 ea2384d3 bellard
    if (argc < 2)
1054 ea2384d3 bellard
        help();
1055 153859be Stuart Brady
    cmdname = argv[1];
1056 8f9b157e aurel32
    argc--; argv++;
1057 153859be Stuart Brady
1058 153859be Stuart Brady
    /* find the command */
1059 153859be Stuart Brady
    for(cmd = img_cmds; cmd->name != NULL; cmd++) {
1060 153859be Stuart Brady
        if (!strcmp(cmdname, cmd->name)) {
1061 153859be Stuart Brady
            return cmd->handler(argc, argv);
1062 153859be Stuart Brady
        }
1063 ea2384d3 bellard
    }
1064 153859be Stuart Brady
1065 153859be Stuart Brady
    /* not found */
1066 153859be Stuart Brady
    help();
1067 ea2384d3 bellard
    return 0;
1068 ea2384d3 bellard
}