Statistics
| Branch: | Revision:

root / qemu-img.c @ dd4239d6

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

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