Statistics
| Branch: | Revision:

root / qemu-img.c @ 153859be

History | View | Annotate | Download (29.6 kB)

1 ea2384d3 bellard
/*
2 fb43f4dd bellard
 * QEMU disk image utility
3 5fafdf24 ths
 *
4 68d0f70e bellard
 * Copyright (c) 2003-2008 Fabrice Bellard
5 5fafdf24 ths
 *
6 ea2384d3 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 ea2384d3 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 ea2384d3 bellard
 * in the Software without restriction, including without limitation the rights
9 ea2384d3 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 ea2384d3 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 ea2384d3 bellard
 * furnished to do so, subject to the following conditions:
12 ea2384d3 bellard
 *
13 ea2384d3 bellard
 * The above copyright notice and this permission notice shall be included in
14 ea2384d3 bellard
 * all copies or substantial portions of the Software.
15 ea2384d3 bellard
 *
16 ea2384d3 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 ea2384d3 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 ea2384d3 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 ea2384d3 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 ea2384d3 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 ea2384d3 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 ea2384d3 bellard
 * THE SOFTWARE.
23 ea2384d3 bellard
 */
24 faf07963 pbrook
#include "qemu-common.h"
25 9ea2ea71 Kevin Wolf
#include "qemu-option.h"
26 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 93c65b47 aliguori
                if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
751 93c65b47 aliguori
                                       n, &n1)) {
752 93c65b47 aliguori
                    sector_num += n1;
753 93c65b47 aliguori
                    continue;
754 93c65b47 aliguori
                }
755 93c65b47 aliguori
                /* The next 'n1' sectors are allocated in the input image. Copy
756 93c65b47 aliguori
                   only those as they may be followed by unallocated sectors. */
757 93c65b47 aliguori
                n = n1;
758 93c65b47 aliguori
            } else {
759 93c65b47 aliguori
                n1 = n;
760 f58c7b35 ths
            }
761 f58c7b35 ths
762 926c2d23 balrog
            if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) 
763 ea2384d3 bellard
                error("error while reading");
764 ea2384d3 bellard
            /* NOTE: at the same time we convert, we do not write zero
765 ea2384d3 bellard
               sectors to have a chance to compress the image. Ideally, we
766 ea2384d3 bellard
               should add a specific call to have the info to go faster */
767 ea2384d3 bellard
            buf1 = buf;
768 ea2384d3 bellard
            while (n > 0) {
769 f58c7b35 ths
                /* If the output image is being created as a copy on write image,
770 f58c7b35 ths
                   copy all sectors even the ones containing only NUL bytes,
771 93c65b47 aliguori
                   because they may differ from the sectors in the base image.
772 93c65b47 aliguori

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