Statistics
| Branch: | Revision:

root / qemu-img.c @ 97aff481

History | View | Annotate | Download (27.4 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 f7b4a940 aliguori
#include "osdep.h"
26 ec36ba14 ths
#include "block_int.h"
27 9230eaf6 aliguori
#include <stdio.h>
28 ea2384d3 bellard
29 e8445331 bellard
#ifdef _WIN32
30 e8445331 bellard
#include <windows.h>
31 e8445331 bellard
#endif
32 e8445331 bellard
33 137519ce aurel32
/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
34 137519ce aurel32
#define BRDV_O_FLAGS BDRV_O_CACHE_WB
35 137519ce aurel32
36 a5e50b26 malc
static void QEMU_NORETURN error(const char *fmt, ...)
37 ea2384d3 bellard
{
38 ea2384d3 bellard
    va_list ap;
39 ea2384d3 bellard
    va_start(ap, fmt);
40 57d1a2b6 bellard
    fprintf(stderr, "qemu-img: ");
41 ea2384d3 bellard
    vfprintf(stderr, fmt, ap);
42 ea2384d3 bellard
    fprintf(stderr, "\n");
43 ea2384d3 bellard
    exit(1);
44 ea2384d3 bellard
    va_end(ap);
45 ea2384d3 bellard
}
46 ea2384d3 bellard
47 ea2384d3 bellard
static void format_print(void *opaque, const char *name)
48 ea2384d3 bellard
{
49 ea2384d3 bellard
    printf(" %s", name);
50 ea2384d3 bellard
}
51 ea2384d3 bellard
52 d2c639d6 blueswir1
/* Please keep in synch with qemu-img.texi */
53 3f379ab1 pbrook
static void help(void)
54 ea2384d3 bellard
{
55 68d0f70e bellard
    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
56 57d1a2b6 bellard
           "usage: qemu-img command [command options]\n"
57 ea2384d3 bellard
           "QEMU disk image utility\n"
58 ea2384d3 bellard
           "\n"
59 ea2384d3 bellard
           "Command syntax:\n"
60 1585969c aliguori
           "  check [-f fmt] filename\n"
61 9230eaf6 aliguori
           "  create [-e] [-6] [-F fmt] [-b base_image] [-f fmt] filename [size]\n"
62 ea2384d3 bellard
           "  commit [-f fmt] filename\n"
63 f58c7b35 ths
           "  convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
64 ea2384d3 bellard
           "  info [-f fmt] filename\n"
65 d2c639d6 blueswir1
           "  snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename\n"
66 ea2384d3 bellard
           "\n"
67 ea2384d3 bellard
           "Command parameters:\n"
68 ea2384d3 bellard
           "  'filename' is a disk image filename\n"
69 ea2384d3 bellard
           "  'base_image' is the read-only disk image which is used as base for a copy on\n"
70 ea2384d3 bellard
           "    write image; the copy on write image only stores the modified data\n"
71 f58c7b35 ths
           "  'output_base_image' forces the output image to be created as a copy on write\n"
72 f58c7b35 ths
           "    image of the specified base image; 'output_base_image' should have the same\n"
73 f58c7b35 ths
           "    content as the input's base image, however the path, image format, etc may\n"
74 f58c7b35 ths
           "    differ\n"
75 ea2384d3 bellard
           "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
76 d2c639d6 blueswir1
           "  'size' is the disk image size in kilobytes. Optional suffixes\n"
77 2fbc4095 aurel32
           "    'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
78 2fbc4095 aurel32
           "    supported any 'k' or 'K' is ignored\n"
79 ea2384d3 bellard
           "  'output_filename' is the destination disk image filename\n"
80 ea2384d3 bellard
           "  'output_fmt' is the destination format\n"
81 ea2384d3 bellard
           "  '-c' indicates that target image must be compressed (qcow format only)\n"
82 ea2384d3 bellard
           "  '-e' indicates that the target image must be encrypted (qcow format only)\n"
83 ec36ba14 ths
           "  '-6' indicates that the target image must use compatibility level 6 (vmdk 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 ea2384d3 bellard
static int img_create(int argc, char **argv)
218 ea2384d3 bellard
{
219 ec36ba14 ths
    int c, ret, flags;
220 ea2384d3 bellard
    const char *fmt = "raw";
221 9230eaf6 aliguori
    const char *base_fmt = NULL;
222 ea2384d3 bellard
    const char *filename;
223 ea2384d3 bellard
    const char *base_filename = NULL;
224 96b8f136 ths
    uint64_t size;
225 24501489 aurel32
    double sizef;
226 ea2384d3 bellard
    const char *p;
227 ea2384d3 bellard
    BlockDriver *drv;
228 3b46e624 ths
229 ec36ba14 ths
    flags = 0;
230 ea2384d3 bellard
    for(;;) {
231 9230eaf6 aliguori
        c = getopt(argc, argv, "F:b:f:he6");
232 ea2384d3 bellard
        if (c == -1)
233 ea2384d3 bellard
            break;
234 ea2384d3 bellard
        switch(c) {
235 ea2384d3 bellard
        case 'h':
236 ea2384d3 bellard
            help();
237 ea2384d3 bellard
            break;
238 9230eaf6 aliguori
        case 'F':
239 9230eaf6 aliguori
            base_fmt = optarg;
240 9230eaf6 aliguori
            break;
241 ea2384d3 bellard
        case 'b':
242 ea2384d3 bellard
            base_filename = optarg;
243 ea2384d3 bellard
            break;
244 ea2384d3 bellard
        case 'f':
245 ea2384d3 bellard
            fmt = optarg;
246 ea2384d3 bellard
            break;
247 ea2384d3 bellard
        case 'e':
248 ec36ba14 ths
            flags |= BLOCK_FLAG_ENCRYPT;
249 ea2384d3 bellard
            break;
250 d8871c5a ths
        case '6':
251 ec36ba14 ths
            flags |= BLOCK_FLAG_COMPAT6;
252 d8871c5a ths
            break;
253 ea2384d3 bellard
        }
254 ea2384d3 bellard
    }
255 5fafdf24 ths
    if (optind >= argc)
256 ea2384d3 bellard
        help();
257 ea2384d3 bellard
    filename = argv[optind++];
258 ea2384d3 bellard
    size = 0;
259 75c23805 bellard
    if (base_filename) {
260 e94f3a60 aliguori
        BlockDriverState *bs;
261 9230eaf6 aliguori
        BlockDriver *base_drv = NULL;
262 9230eaf6 aliguori
263 9230eaf6 aliguori
        if (base_fmt) {
264 9230eaf6 aliguori
            base_drv = bdrv_find_format(base_fmt);
265 9230eaf6 aliguori
            if (base_drv == NULL)
266 9230eaf6 aliguori
                error("Unknown basefile format '%s'", base_fmt);
267 9230eaf6 aliguori
        }
268 9230eaf6 aliguori
269 9230eaf6 aliguori
        bs = bdrv_new_open(base_filename, base_fmt);
270 75c23805 bellard
        bdrv_get_geometry(bs, &size);
271 75c23805 bellard
        size *= 512;
272 75c23805 bellard
        bdrv_delete(bs);
273 75c23805 bellard
    } else {
274 ea2384d3 bellard
        if (optind >= argc)
275 ea2384d3 bellard
            help();
276 ea2384d3 bellard
        p = argv[optind];
277 24501489 aurel32
        sizef = strtod(p, (char **)&p);
278 ea2384d3 bellard
        if (*p == 'M') {
279 24501489 aurel32
            size = (uint64_t)(sizef * 1024 * 1024);
280 ea2384d3 bellard
        } else if (*p == 'G') {
281 24501489 aurel32
            size = (uint64_t)(sizef * 1024 * 1024 * 1024);
282 ea2384d3 bellard
        } else if (*p == 'k' || *p == 'K' || *p == '\0') {
283 24501489 aurel32
            size = (uint64_t)(sizef * 1024);
284 ea2384d3 bellard
        } else {
285 ea2384d3 bellard
            help();
286 ea2384d3 bellard
        }
287 ea2384d3 bellard
    }
288 ea2384d3 bellard
    drv = bdrv_find_format(fmt);
289 ea2384d3 bellard
    if (!drv)
290 ea2384d3 bellard
        error("Unknown file format '%s'", fmt);
291 0cfec834 ths
    printf("Formatting '%s', fmt=%s",
292 ea2384d3 bellard
           filename, fmt);
293 ec36ba14 ths
    if (flags & BLOCK_FLAG_ENCRYPT)
294 ea2384d3 bellard
        printf(", encrypted");
295 ec36ba14 ths
    if (flags & BLOCK_FLAG_COMPAT6)
296 ec36ba14 ths
        printf(", compatibility level=6");
297 75c23805 bellard
    if (base_filename) {
298 75c23805 bellard
        printf(", backing_file=%s",
299 ea2384d3 bellard
               base_filename);
300 9230eaf6 aliguori
         if (base_fmt)
301 9230eaf6 aliguori
             printf(", backing_fmt=%s",
302 9230eaf6 aliguori
                    base_fmt);
303 75c23805 bellard
    }
304 96b8f136 ths
    printf(", size=%" PRIu64 " kB\n", size / 1024);
305 9230eaf6 aliguori
    ret = bdrv_create2(drv, filename, size / 512, base_filename, base_fmt, flags);
306 ea2384d3 bellard
    if (ret < 0) {
307 ea2384d3 bellard
        if (ret == -ENOTSUP) {
308 3c56521b bellard
            error("Formatting or formatting option not supported for file format '%s'", fmt);
309 6e9ea0c0 aurel32
        } else if (ret == -EFBIG) {
310 6e9ea0c0 aurel32
            error("The image size is too large for file format '%s'", fmt);
311 ea2384d3 bellard
        } else {
312 ea2384d3 bellard
            error("Error while formatting");
313 ea2384d3 bellard
        }
314 ea2384d3 bellard
    }
315 ea2384d3 bellard
    return 0;
316 ea2384d3 bellard
}
317 ea2384d3 bellard
318 1585969c aliguori
static int img_check(int argc, char **argv)
319 1585969c aliguori
{
320 1585969c aliguori
    int c, ret;
321 1585969c aliguori
    const char *filename, *fmt;
322 1585969c aliguori
    BlockDriver *drv;
323 1585969c aliguori
    BlockDriverState *bs;
324 1585969c aliguori
325 1585969c aliguori
    fmt = NULL;
326 1585969c aliguori
    for(;;) {
327 1585969c aliguori
        c = getopt(argc, argv, "f:h");
328 1585969c aliguori
        if (c == -1)
329 1585969c aliguori
            break;
330 1585969c aliguori
        switch(c) {
331 1585969c aliguori
        case 'h':
332 1585969c aliguori
            help();
333 1585969c aliguori
            break;
334 1585969c aliguori
        case 'f':
335 1585969c aliguori
            fmt = optarg;
336 1585969c aliguori
            break;
337 1585969c aliguori
        }
338 1585969c aliguori
    }
339 1585969c aliguori
    if (optind >= argc)
340 1585969c aliguori
        help();
341 1585969c aliguori
    filename = argv[optind++];
342 1585969c aliguori
343 1585969c aliguori
    bs = bdrv_new("");
344 1585969c aliguori
    if (!bs)
345 1585969c aliguori
        error("Not enough memory");
346 1585969c aliguori
    if (fmt) {
347 1585969c aliguori
        drv = bdrv_find_format(fmt);
348 1585969c aliguori
        if (!drv)
349 1585969c aliguori
            error("Unknown file format '%s'", fmt);
350 1585969c aliguori
    } else {
351 1585969c aliguori
        drv = NULL;
352 1585969c aliguori
    }
353 1585969c aliguori
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
354 1585969c aliguori
        error("Could not open '%s'", filename);
355 1585969c aliguori
    }
356 1585969c aliguori
    ret = bdrv_check(bs);
357 1585969c aliguori
    switch(ret) {
358 1585969c aliguori
    case 0:
359 1585969c aliguori
        printf("No errors were found on the image.\n");
360 1585969c aliguori
        break;
361 1585969c aliguori
    case -ENOTSUP:
362 1585969c aliguori
        error("This image format does not support checks");
363 1585969c aliguori
        break;
364 1585969c aliguori
    default:
365 1585969c aliguori
        if (ret < 0) {
366 1585969c aliguori
            error("An error occurred during the check");
367 1585969c aliguori
        } else {
368 1585969c aliguori
            printf("%d errors were found on the image.\n", ret);
369 1585969c aliguori
        }
370 1585969c aliguori
        break;
371 1585969c aliguori
    }
372 1585969c aliguori
373 1585969c aliguori
    bdrv_delete(bs);
374 1585969c aliguori
    return 0;
375 1585969c aliguori
}
376 1585969c aliguori
377 ea2384d3 bellard
static int img_commit(int argc, char **argv)
378 ea2384d3 bellard
{
379 ea2384d3 bellard
    int c, ret;
380 ea2384d3 bellard
    const char *filename, *fmt;
381 ea2384d3 bellard
    BlockDriver *drv;
382 ea2384d3 bellard
    BlockDriverState *bs;
383 ea2384d3 bellard
384 ea2384d3 bellard
    fmt = NULL;
385 ea2384d3 bellard
    for(;;) {
386 ea2384d3 bellard
        c = getopt(argc, argv, "f:h");
387 ea2384d3 bellard
        if (c == -1)
388 ea2384d3 bellard
            break;
389 ea2384d3 bellard
        switch(c) {
390 ea2384d3 bellard
        case 'h':
391 ea2384d3 bellard
            help();
392 ea2384d3 bellard
            break;
393 ea2384d3 bellard
        case 'f':
394 ea2384d3 bellard
            fmt = optarg;
395 ea2384d3 bellard
            break;
396 ea2384d3 bellard
        }
397 ea2384d3 bellard
    }
398 5fafdf24 ths
    if (optind >= argc)
399 ea2384d3 bellard
        help();
400 ea2384d3 bellard
    filename = argv[optind++];
401 ea2384d3 bellard
402 ea2384d3 bellard
    bs = bdrv_new("");
403 ea2384d3 bellard
    if (!bs)
404 ea2384d3 bellard
        error("Not enough memory");
405 ea2384d3 bellard
    if (fmt) {
406 ea2384d3 bellard
        drv = bdrv_find_format(fmt);
407 ea2384d3 bellard
        if (!drv)
408 ea2384d3 bellard
            error("Unknown file format '%s'", fmt);
409 ea2384d3 bellard
    } else {
410 ea2384d3 bellard
        drv = NULL;
411 ea2384d3 bellard
    }
412 137519ce aurel32
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
413 ea2384d3 bellard
        error("Could not open '%s'", filename);
414 ea2384d3 bellard
    }
415 ea2384d3 bellard
    ret = bdrv_commit(bs);
416 ea2384d3 bellard
    switch(ret) {
417 ea2384d3 bellard
    case 0:
418 ea2384d3 bellard
        printf("Image committed.\n");
419 ea2384d3 bellard
        break;
420 ea2384d3 bellard
    case -ENOENT:
421 ea2384d3 bellard
        error("No disk inserted");
422 ea2384d3 bellard
        break;
423 ea2384d3 bellard
    case -EACCES:
424 ea2384d3 bellard
        error("Image is read-only");
425 ea2384d3 bellard
        break;
426 ea2384d3 bellard
    case -ENOTSUP:
427 ea2384d3 bellard
        error("Image is already committed");
428 ea2384d3 bellard
        break;
429 ea2384d3 bellard
    default:
430 ea2384d3 bellard
        error("Error while committing image");
431 ea2384d3 bellard
        break;
432 ea2384d3 bellard
    }
433 ea2384d3 bellard
434 ea2384d3 bellard
    bdrv_delete(bs);
435 ea2384d3 bellard
    return 0;
436 ea2384d3 bellard
}
437 ea2384d3 bellard
438 ea2384d3 bellard
static int is_not_zero(const uint8_t *sector, int len)
439 ea2384d3 bellard
{
440 ea2384d3 bellard
    int i;
441 ea2384d3 bellard
    len >>= 2;
442 ea2384d3 bellard
    for(i = 0;i < len; i++) {
443 ea2384d3 bellard
        if (((uint32_t *)sector)[i] != 0)
444 ea2384d3 bellard
            return 1;
445 ea2384d3 bellard
    }
446 ea2384d3 bellard
    return 0;
447 ea2384d3 bellard
}
448 ea2384d3 bellard
449 f58c7b35 ths
/*
450 f58c7b35 ths
 * Returns true iff the first sector pointed to by 'buf' contains at least
451 f58c7b35 ths
 * a non-NUL byte.
452 f58c7b35 ths
 *
453 f58c7b35 ths
 * 'pnum' is set to the number of sectors (including and immediately following
454 f58c7b35 ths
 * the first one) that are known to be in the same allocated/unallocated state.
455 f58c7b35 ths
 */
456 ea2384d3 bellard
static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
457 ea2384d3 bellard
{
458 ea2384d3 bellard
    int v, i;
459 ea2384d3 bellard
460 ea2384d3 bellard
    if (n <= 0) {
461 ea2384d3 bellard
        *pnum = 0;
462 ea2384d3 bellard
        return 0;
463 ea2384d3 bellard
    }
464 ea2384d3 bellard
    v = is_not_zero(buf, 512);
465 ea2384d3 bellard
    for(i = 1; i < n; i++) {
466 ea2384d3 bellard
        buf += 512;
467 ea2384d3 bellard
        if (v != is_not_zero(buf, 512))
468 ea2384d3 bellard
            break;
469 ea2384d3 bellard
    }
470 ea2384d3 bellard
    *pnum = i;
471 ea2384d3 bellard
    return v;
472 ea2384d3 bellard
}
473 ea2384d3 bellard
474 ea2384d3 bellard
#define IO_BUF_SIZE 65536
475 ea2384d3 bellard
476 ea2384d3 bellard
static int img_convert(int argc, char **argv)
477 ea2384d3 bellard
{
478 926c2d23 balrog
    int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
479 f58c7b35 ths
    const char *fmt, *out_fmt, *out_baseimg, *out_filename;
480 ea2384d3 bellard
    BlockDriver *drv;
481 926c2d23 balrog
    BlockDriverState **bs, *out_bs;
482 96b8f136 ths
    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
483 96b8f136 ths
    uint64_t bs_sectors;
484 ea2384d3 bellard
    uint8_t buf[IO_BUF_SIZE];
485 ea2384d3 bellard
    const uint8_t *buf1;
486 faea38e7 bellard
    BlockDriverInfo bdi;
487 ea2384d3 bellard
488 ea2384d3 bellard
    fmt = NULL;
489 ea2384d3 bellard
    out_fmt = "raw";
490 f58c7b35 ths
    out_baseimg = NULL;
491 ec36ba14 ths
    flags = 0;
492 ea2384d3 bellard
    for(;;) {
493 f58c7b35 ths
        c = getopt(argc, argv, "f:O:B:hce6");
494 ea2384d3 bellard
        if (c == -1)
495 ea2384d3 bellard
            break;
496 ea2384d3 bellard
        switch(c) {
497 ea2384d3 bellard
        case 'h':
498 ea2384d3 bellard
            help();
499 ea2384d3 bellard
            break;
500 ea2384d3 bellard
        case 'f':
501 ea2384d3 bellard
            fmt = optarg;
502 ea2384d3 bellard
            break;
503 ea2384d3 bellard
        case 'O':
504 ea2384d3 bellard
            out_fmt = optarg;
505 ea2384d3 bellard
            break;
506 f58c7b35 ths
        case 'B':
507 f58c7b35 ths
            out_baseimg = optarg;
508 f58c7b35 ths
            break;
509 ea2384d3 bellard
        case 'c':
510 ec36ba14 ths
            flags |= BLOCK_FLAG_COMPRESS;
511 ea2384d3 bellard
            break;
512 ea2384d3 bellard
        case 'e':
513 ec36ba14 ths
            flags |= BLOCK_FLAG_ENCRYPT;
514 ec36ba14 ths
            break;
515 ec36ba14 ths
        case '6':
516 ec36ba14 ths
            flags |= BLOCK_FLAG_COMPAT6;
517 ea2384d3 bellard
            break;
518 ea2384d3 bellard
        }
519 ea2384d3 bellard
    }
520 3b46e624 ths
521 926c2d23 balrog
    bs_n = argc - optind - 1;
522 926c2d23 balrog
    if (bs_n < 1) help();
523 926c2d23 balrog
524 926c2d23 balrog
    out_filename = argv[argc - 1];
525 f58c7b35 ths
526 f58c7b35 ths
    if (bs_n > 1 && out_baseimg)
527 f58c7b35 ths
        error("-B makes no sense when concatenating multiple input images");
528 926c2d23 balrog
        
529 926c2d23 balrog
    bs = calloc(bs_n, sizeof(BlockDriverState *));
530 926c2d23 balrog
    if (!bs)
531 926c2d23 balrog
        error("Out of memory");
532 926c2d23 balrog
533 926c2d23 balrog
    total_sectors = 0;
534 926c2d23 balrog
    for (bs_i = 0; bs_i < bs_n; bs_i++) {
535 926c2d23 balrog
        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
536 926c2d23 balrog
        if (!bs[bs_i])
537 926c2d23 balrog
            error("Could not open '%s'", argv[optind + bs_i]);
538 926c2d23 balrog
        bdrv_get_geometry(bs[bs_i], &bs_sectors);
539 926c2d23 balrog
        total_sectors += bs_sectors;
540 926c2d23 balrog
    }
541 ea2384d3 bellard
542 ea2384d3 bellard
    drv = bdrv_find_format(out_fmt);
543 ea2384d3 bellard
    if (!drv)
544 d34dda5e ths
        error("Unknown file format '%s'", out_fmt);
545 5efa9d5a Anthony Liguori
    if (flags & BLOCK_FLAG_COMPRESS && strcmp(drv->format_name, "qcow") && strcmp(drv->format_name, "qcow2"))
546 ea2384d3 bellard
        error("Compression not supported for this file format");
547 5efa9d5a Anthony Liguori
    if (flags & BLOCK_FLAG_ENCRYPT && strcmp(drv->format_name, "qcow") && strcmp(drv->format_name, "qcow2"))
548 ea2384d3 bellard
        error("Encryption not supported for this file format");
549 5efa9d5a Anthony Liguori
    if (flags & BLOCK_FLAG_COMPAT6 && strcmp(drv->format_name, "vmdk"))
550 ec36ba14 ths
        error("Alternative compatibility level not supported for this file format");
551 ec36ba14 ths
    if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
552 ea2384d3 bellard
        error("Compression and encryption not supported at the same time");
553 926c2d23 balrog
554 f58c7b35 ths
    ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
555 ea2384d3 bellard
    if (ret < 0) {
556 ea2384d3 bellard
        if (ret == -ENOTSUP) {
557 93c65b47 aliguori
            error("Formatting not supported for file format '%s'", out_fmt);
558 6e9ea0c0 aurel32
        } else if (ret == -EFBIG) {
559 6e9ea0c0 aurel32
            error("The image size is too large for file format '%s'", out_fmt);
560 ea2384d3 bellard
        } else {
561 ea2384d3 bellard
            error("Error while formatting '%s'", out_filename);
562 ea2384d3 bellard
        }
563 ea2384d3 bellard
    }
564 3b46e624 ths
565 ea2384d3 bellard
    out_bs = bdrv_new_open(out_filename, out_fmt);
566 ea2384d3 bellard
567 926c2d23 balrog
    bs_i = 0;
568 926c2d23 balrog
    bs_offset = 0;
569 926c2d23 balrog
    bdrv_get_geometry(bs[0], &bs_sectors);
570 926c2d23 balrog
571 926c2d23 balrog
    if (flags & BLOCK_FLAG_COMPRESS) {
572 faea38e7 bellard
        if (bdrv_get_info(out_bs, &bdi) < 0)
573 faea38e7 bellard
            error("could not get block driver info");
574 faea38e7 bellard
        cluster_size = bdi.cluster_size;
575 ea2384d3 bellard
        if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
576 ea2384d3 bellard
            error("invalid cluster size");
577 ea2384d3 bellard
        cluster_sectors = cluster_size >> 9;
578 ea2384d3 bellard
        sector_num = 0;
579 ea2384d3 bellard
        for(;;) {
580 926c2d23 balrog
            int64_t bs_num;
581 926c2d23 balrog
            int remainder;
582 926c2d23 balrog
            uint8_t *buf2;
583 926c2d23 balrog
584 ea2384d3 bellard
            nb_sectors = total_sectors - sector_num;
585 ea2384d3 bellard
            if (nb_sectors <= 0)
586 ea2384d3 bellard
                break;
587 ea2384d3 bellard
            if (nb_sectors >= cluster_sectors)
588 ea2384d3 bellard
                n = cluster_sectors;
589 ea2384d3 bellard
            else
590 ea2384d3 bellard
                n = nb_sectors;
591 926c2d23 balrog
592 926c2d23 balrog
            bs_num = sector_num - bs_offset;
593 926c2d23 balrog
            assert (bs_num >= 0);
594 926c2d23 balrog
            remainder = n;
595 926c2d23 balrog
            buf2 = buf;
596 926c2d23 balrog
            while (remainder > 0) {
597 926c2d23 balrog
                int nlow;
598 926c2d23 balrog
                while (bs_num == bs_sectors) {
599 926c2d23 balrog
                    bs_i++;
600 926c2d23 balrog
                    assert (bs_i < bs_n);
601 926c2d23 balrog
                    bs_offset += bs_sectors;
602 926c2d23 balrog
                    bdrv_get_geometry(bs[bs_i], &bs_sectors);
603 926c2d23 balrog
                    bs_num = 0;
604 926c2d23 balrog
                    /* printf("changing part: sector_num=%lld, "
605 926c2d23 balrog
                       "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
606 926c2d23 balrog
                       sector_num, bs_i, bs_offset, bs_sectors); */
607 926c2d23 balrog
                }
608 926c2d23 balrog
                assert (bs_num < bs_sectors);
609 926c2d23 balrog
610 926c2d23 balrog
                nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
611 926c2d23 balrog
612 926c2d23 balrog
                if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) 
613 926c2d23 balrog
                    error("error while reading");
614 926c2d23 balrog
615 926c2d23 balrog
                buf2 += nlow * 512;
616 926c2d23 balrog
                bs_num += nlow;
617 926c2d23 balrog
618 926c2d23 balrog
                remainder -= nlow;
619 926c2d23 balrog
            }
620 926c2d23 balrog
            assert (remainder == 0);
621 926c2d23 balrog
622 ea2384d3 bellard
            if (n < cluster_sectors)
623 ea2384d3 bellard
                memset(buf + n * 512, 0, cluster_size - n * 512);
624 ea2384d3 bellard
            if (is_not_zero(buf, cluster_size)) {
625 5fafdf24 ths
                if (bdrv_write_compressed(out_bs, sector_num, buf,
626 faea38e7 bellard
                                          cluster_sectors) != 0)
627 ec3757de bellard
                    error("error while compressing sector %" PRId64,
628 ec3757de bellard
                          sector_num);
629 ea2384d3 bellard
            }
630 ea2384d3 bellard
            sector_num += n;
631 ea2384d3 bellard
        }
632 faea38e7 bellard
        /* signal EOF to align */
633 faea38e7 bellard
        bdrv_write_compressed(out_bs, 0, NULL, 0);
634 ea2384d3 bellard
    } else {
635 f58c7b35 ths
        sector_num = 0; // total number of sectors converted so far
636 ea2384d3 bellard
        for(;;) {
637 ea2384d3 bellard
            nb_sectors = total_sectors - sector_num;
638 ea2384d3 bellard
            if (nb_sectors <= 0)
639 ea2384d3 bellard
                break;
640 ea2384d3 bellard
            if (nb_sectors >= (IO_BUF_SIZE / 512))
641 ea2384d3 bellard
                n = (IO_BUF_SIZE / 512);
642 ea2384d3 bellard
            else
643 ea2384d3 bellard
                n = nb_sectors;
644 926c2d23 balrog
645 926c2d23 balrog
            while (sector_num - bs_offset >= bs_sectors) {
646 926c2d23 balrog
                bs_i ++;
647 926c2d23 balrog
                assert (bs_i < bs_n);
648 926c2d23 balrog
                bs_offset += bs_sectors;
649 926c2d23 balrog
                bdrv_get_geometry(bs[bs_i], &bs_sectors);
650 926c2d23 balrog
                /* printf("changing part: sector_num=%lld, bs_i=%d, "
651 926c2d23 balrog
                  "bs_offset=%lld, bs_sectors=%lld\n",
652 926c2d23 balrog
                   sector_num, bs_i, bs_offset, bs_sectors); */
653 926c2d23 balrog
            }
654 926c2d23 balrog
655 926c2d23 balrog
            if (n > bs_offset + bs_sectors - sector_num)
656 926c2d23 balrog
                n = bs_offset + bs_sectors - sector_num;
657 926c2d23 balrog
658 5efa9d5a Anthony Liguori
            if (strcmp(drv->format_name, "host_device")) {
659 93c65b47 aliguori
                if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
660 93c65b47 aliguori
                                       n, &n1)) {
661 93c65b47 aliguori
                    sector_num += n1;
662 93c65b47 aliguori
                    continue;
663 93c65b47 aliguori
                }
664 93c65b47 aliguori
                /* The next 'n1' sectors are allocated in the input image. Copy
665 93c65b47 aliguori
                   only those as they may be followed by unallocated sectors. */
666 93c65b47 aliguori
                n = n1;
667 93c65b47 aliguori
            } else {
668 93c65b47 aliguori
                n1 = n;
669 f58c7b35 ths
            }
670 f58c7b35 ths
671 926c2d23 balrog
            if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) 
672 ea2384d3 bellard
                error("error while reading");
673 ea2384d3 bellard
            /* NOTE: at the same time we convert, we do not write zero
674 ea2384d3 bellard
               sectors to have a chance to compress the image. Ideally, we
675 ea2384d3 bellard
               should add a specific call to have the info to go faster */
676 ea2384d3 bellard
            buf1 = buf;
677 ea2384d3 bellard
            while (n > 0) {
678 f58c7b35 ths
                /* If the output image is being created as a copy on write image,
679 f58c7b35 ths
                   copy all sectors even the ones containing only NUL bytes,
680 93c65b47 aliguori
                   because they may differ from the sectors in the base image.
681 93c65b47 aliguori

682 93c65b47 aliguori
                   If the output is to a host device, we also write out
683 93c65b47 aliguori
                   sectors that are entirely 0, since whatever data was
684 93c65b47 aliguori
                   already there is garbage, not 0s. */
685 5efa9d5a Anthony Liguori
                if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg ||
686 93c65b47 aliguori
                    is_allocated_sectors(buf1, n, &n1)) {
687 5fafdf24 ths
                    if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
688 ea2384d3 bellard
                        error("error while writing");
689 ea2384d3 bellard
                }
690 ea2384d3 bellard
                sector_num += n1;
691 ea2384d3 bellard
                n -= n1;
692 ea2384d3 bellard
                buf1 += n1 * 512;
693 ea2384d3 bellard
            }
694 ea2384d3 bellard
        }
695 ea2384d3 bellard
    }
696 ea2384d3 bellard
    bdrv_delete(out_bs);
697 926c2d23 balrog
    for (bs_i = 0; bs_i < bs_n; bs_i++)
698 926c2d23 balrog
        bdrv_delete(bs[bs_i]);
699 926c2d23 balrog
    free(bs);
700 ea2384d3 bellard
    return 0;
701 ea2384d3 bellard
}
702 ea2384d3 bellard
703 57d1a2b6 bellard
#ifdef _WIN32
704 57d1a2b6 bellard
static int64_t get_allocated_file_size(const char *filename)
705 57d1a2b6 bellard
{
706 e8445331 bellard
    typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
707 e8445331 bellard
    get_compressed_t get_compressed;
708 57d1a2b6 bellard
    struct _stati64 st;
709 e8445331 bellard
710 e8445331 bellard
    /* WinNT support GetCompressedFileSize to determine allocate size */
711 e8445331 bellard
    get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
712 e8445331 bellard
    if (get_compressed) {
713 e8445331 bellard
            DWORD high, low;
714 e8445331 bellard
            low = get_compressed(filename, &high);
715 e8445331 bellard
            if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
716 e8445331 bellard
            return (((int64_t) high) << 32) + low;
717 e8445331 bellard
    }
718 e8445331 bellard
719 5fafdf24 ths
    if (_stati64(filename, &st) < 0)
720 57d1a2b6 bellard
        return -1;
721 57d1a2b6 bellard
    return st.st_size;
722 57d1a2b6 bellard
}
723 57d1a2b6 bellard
#else
724 57d1a2b6 bellard
static int64_t get_allocated_file_size(const char *filename)
725 57d1a2b6 bellard
{
726 57d1a2b6 bellard
    struct stat st;
727 5fafdf24 ths
    if (stat(filename, &st) < 0)
728 57d1a2b6 bellard
        return -1;
729 57d1a2b6 bellard
    return (int64_t)st.st_blocks * 512;
730 57d1a2b6 bellard
}
731 57d1a2b6 bellard
#endif
732 57d1a2b6 bellard
733 faea38e7 bellard
static void dump_snapshots(BlockDriverState *bs)
734 faea38e7 bellard
{
735 faea38e7 bellard
    QEMUSnapshotInfo *sn_tab, *sn;
736 faea38e7 bellard
    int nb_sns, i;
737 faea38e7 bellard
    char buf[256];
738 faea38e7 bellard
739 faea38e7 bellard
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
740 faea38e7 bellard
    if (nb_sns <= 0)
741 faea38e7 bellard
        return;
742 faea38e7 bellard
    printf("Snapshot list:\n");
743 faea38e7 bellard
    printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
744 faea38e7 bellard
    for(i = 0; i < nb_sns; i++) {
745 faea38e7 bellard
        sn = &sn_tab[i];
746 faea38e7 bellard
        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
747 faea38e7 bellard
    }
748 faea38e7 bellard
    qemu_free(sn_tab);
749 faea38e7 bellard
}
750 faea38e7 bellard
751 ea2384d3 bellard
static int img_info(int argc, char **argv)
752 ea2384d3 bellard
{
753 ea2384d3 bellard
    int c;
754 ea2384d3 bellard
    const char *filename, *fmt;
755 ea2384d3 bellard
    BlockDriver *drv;
756 ea2384d3 bellard
    BlockDriverState *bs;
757 ea2384d3 bellard
    char fmt_name[128], size_buf[128], dsize_buf[128];
758 96b8f136 ths
    uint64_t total_sectors;
759 96b8f136 ths
    int64_t allocated_size;
760 93b6b2a3 bellard
    char backing_filename[1024];
761 93b6b2a3 bellard
    char backing_filename2[1024];
762 faea38e7 bellard
    BlockDriverInfo bdi;
763 ea2384d3 bellard
764 ea2384d3 bellard
    fmt = NULL;
765 ea2384d3 bellard
    for(;;) {
766 ea2384d3 bellard
        c = getopt(argc, argv, "f:h");
767 ea2384d3 bellard
        if (c == -1)
768 ea2384d3 bellard
            break;
769 ea2384d3 bellard
        switch(c) {
770 ea2384d3 bellard
        case 'h':
771 ea2384d3 bellard
            help();
772 ea2384d3 bellard
            break;
773 ea2384d3 bellard
        case 'f':
774 ea2384d3 bellard
            fmt = optarg;
775 ea2384d3 bellard
            break;
776 ea2384d3 bellard
        }
777 ea2384d3 bellard
    }
778 5fafdf24 ths
    if (optind >= argc)
779 ea2384d3 bellard
        help();
780 ea2384d3 bellard
    filename = argv[optind++];
781 ea2384d3 bellard
782 ea2384d3 bellard
    bs = bdrv_new("");
783 ea2384d3 bellard
    if (!bs)
784 ea2384d3 bellard
        error("Not enough memory");
785 ea2384d3 bellard
    if (fmt) {
786 ea2384d3 bellard
        drv = bdrv_find_format(fmt);
787 ea2384d3 bellard
        if (!drv)
788 ea2384d3 bellard
            error("Unknown file format '%s'", fmt);
789 ea2384d3 bellard
    } else {
790 ea2384d3 bellard
        drv = NULL;
791 ea2384d3 bellard
    }
792 137519ce aurel32
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
793 ea2384d3 bellard
        error("Could not open '%s'", filename);
794 ea2384d3 bellard
    }
795 ea2384d3 bellard
    bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
796 ea2384d3 bellard
    bdrv_get_geometry(bs, &total_sectors);
797 ea2384d3 bellard
    get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
798 57d1a2b6 bellard
    allocated_size = get_allocated_file_size(filename);
799 57d1a2b6 bellard
    if (allocated_size < 0)
800 a10ea30b blueswir1
        snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
801 de167e41 bellard
    else
802 5fafdf24 ths
        get_human_readable_size(dsize_buf, sizeof(dsize_buf),
803 de167e41 bellard
                                allocated_size);
804 ea2384d3 bellard
    printf("image: %s\n"
805 ea2384d3 bellard
           "file format: %s\n"
806 ec3757de bellard
           "virtual size: %s (%" PRId64 " bytes)\n"
807 ea2384d3 bellard
           "disk size: %s\n",
808 5fafdf24 ths
           filename, fmt_name, size_buf,
809 ec3757de bellard
           (total_sectors * 512),
810 ea2384d3 bellard
           dsize_buf);
811 ea2384d3 bellard
    if (bdrv_is_encrypted(bs))
812 ea2384d3 bellard
        printf("encrypted: yes\n");
813 faea38e7 bellard
    if (bdrv_get_info(bs, &bdi) >= 0) {
814 5fafdf24 ths
        if (bdi.cluster_size != 0)
815 faea38e7 bellard
            printf("cluster_size: %d\n", bdi.cluster_size);
816 faea38e7 bellard
    }
817 93b6b2a3 bellard
    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
818 faea38e7 bellard
    if (backing_filename[0] != '\0') {
819 93b6b2a3 bellard
        path_combine(backing_filename2, sizeof(backing_filename2),
820 93b6b2a3 bellard
                     filename, backing_filename);
821 5fafdf24 ths
        printf("backing file: %s (actual path: %s)\n",
822 93b6b2a3 bellard
               backing_filename,
823 93b6b2a3 bellard
               backing_filename2);
824 faea38e7 bellard
    }
825 faea38e7 bellard
    dump_snapshots(bs);
826 ea2384d3 bellard
    bdrv_delete(bs);
827 ea2384d3 bellard
    return 0;
828 ea2384d3 bellard
}
829 ea2384d3 bellard
830 f7b4a940 aliguori
#define SNAPSHOT_LIST   1
831 f7b4a940 aliguori
#define SNAPSHOT_CREATE 2
832 f7b4a940 aliguori
#define SNAPSHOT_APPLY  3
833 f7b4a940 aliguori
#define SNAPSHOT_DELETE 4
834 f7b4a940 aliguori
835 f7b4a940 aliguori
static void img_snapshot(int argc, char **argv)
836 f7b4a940 aliguori
{
837 f7b4a940 aliguori
    BlockDriverState *bs;
838 f7b4a940 aliguori
    QEMUSnapshotInfo sn;
839 f7b4a940 aliguori
    char *filename, *snapshot_name = NULL;
840 40a4539e aliguori
    int c, ret;
841 f7b4a940 aliguori
    int action = 0;
842 f7b4a940 aliguori
    qemu_timeval tv;
843 f7b4a940 aliguori
844 f7b4a940 aliguori
    /* Parse commandline parameters */
845 f7b4a940 aliguori
    for(;;) {
846 f7b4a940 aliguori
        c = getopt(argc, argv, "la:c:d:h");
847 f7b4a940 aliguori
        if (c == -1)
848 f7b4a940 aliguori
            break;
849 f7b4a940 aliguori
        switch(c) {
850 f7b4a940 aliguori
        case 'h':
851 f7b4a940 aliguori
            help();
852 f7b4a940 aliguori
            return;
853 f7b4a940 aliguori
        case 'l':
854 f7b4a940 aliguori
            if (action) {
855 f7b4a940 aliguori
                help();
856 f7b4a940 aliguori
                return;
857 f7b4a940 aliguori
            }
858 f7b4a940 aliguori
            action = SNAPSHOT_LIST;
859 f7b4a940 aliguori
            break;
860 f7b4a940 aliguori
        case 'a':
861 f7b4a940 aliguori
            if (action) {
862 f7b4a940 aliguori
                help();
863 f7b4a940 aliguori
                return;
864 f7b4a940 aliguori
            }
865 f7b4a940 aliguori
            action = SNAPSHOT_APPLY;
866 f7b4a940 aliguori
            snapshot_name = optarg;
867 f7b4a940 aliguori
            break;
868 f7b4a940 aliguori
        case 'c':
869 f7b4a940 aliguori
            if (action) {
870 f7b4a940 aliguori
                help();
871 f7b4a940 aliguori
                return;
872 f7b4a940 aliguori
            }
873 f7b4a940 aliguori
            action = SNAPSHOT_CREATE;
874 f7b4a940 aliguori
            snapshot_name = optarg;
875 f7b4a940 aliguori
            break;
876 f7b4a940 aliguori
        case 'd':
877 f7b4a940 aliguori
            if (action) {
878 f7b4a940 aliguori
                help();
879 f7b4a940 aliguori
                return;
880 f7b4a940 aliguori
            }
881 f7b4a940 aliguori
            action = SNAPSHOT_DELETE;
882 f7b4a940 aliguori
            snapshot_name = optarg;
883 f7b4a940 aliguori
            break;
884 f7b4a940 aliguori
        }
885 f7b4a940 aliguori
    }
886 f7b4a940 aliguori
887 f7b4a940 aliguori
    if (optind >= argc)
888 f7b4a940 aliguori
        help();
889 f7b4a940 aliguori
    filename = argv[optind++];
890 f7b4a940 aliguori
891 f7b4a940 aliguori
    /* Open the image */
892 f7b4a940 aliguori
    bs = bdrv_new("");
893 f7b4a940 aliguori
    if (!bs)
894 f7b4a940 aliguori
        error("Not enough memory");
895 f7b4a940 aliguori
896 f7b4a940 aliguori
    if (bdrv_open2(bs, filename, 0, NULL) < 0) {
897 f7b4a940 aliguori
        error("Could not open '%s'", filename);
898 f7b4a940 aliguori
    }
899 f7b4a940 aliguori
900 f7b4a940 aliguori
    /* Perform the requested action */
901 f7b4a940 aliguori
    switch(action) {
902 f7b4a940 aliguori
    case SNAPSHOT_LIST:
903 f7b4a940 aliguori
        dump_snapshots(bs);
904 f7b4a940 aliguori
        break;
905 f7b4a940 aliguori
906 f7b4a940 aliguori
    case SNAPSHOT_CREATE:
907 f7b4a940 aliguori
        memset(&sn, 0, sizeof(sn));
908 f7b4a940 aliguori
        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
909 f7b4a940 aliguori
910 f7b4a940 aliguori
        qemu_gettimeofday(&tv);
911 f7b4a940 aliguori
        sn.date_sec = tv.tv_sec;
912 f7b4a940 aliguori
        sn.date_nsec = tv.tv_usec * 1000;
913 f7b4a940 aliguori
914 f7b4a940 aliguori
        ret = bdrv_snapshot_create(bs, &sn);
915 f7b4a940 aliguori
        if (ret)
916 f7b4a940 aliguori
            error("Could not create snapshot '%s': %d (%s)",
917 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
918 f7b4a940 aliguori
        break;
919 f7b4a940 aliguori
920 f7b4a940 aliguori
    case SNAPSHOT_APPLY:
921 f7b4a940 aliguori
        ret = bdrv_snapshot_goto(bs, snapshot_name);
922 f7b4a940 aliguori
        if (ret)
923 f7b4a940 aliguori
            error("Could not apply snapshot '%s': %d (%s)",
924 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
925 f7b4a940 aliguori
        break;
926 f7b4a940 aliguori
927 f7b4a940 aliguori
    case SNAPSHOT_DELETE:
928 f7b4a940 aliguori
        ret = bdrv_snapshot_delete(bs, snapshot_name);
929 f7b4a940 aliguori
        if (ret)
930 f7b4a940 aliguori
            error("Could not delete snapshot '%s': %d (%s)",
931 f7b4a940 aliguori
                snapshot_name, ret, strerror(-ret));
932 f7b4a940 aliguori
        break;
933 f7b4a940 aliguori
    }
934 f7b4a940 aliguori
935 f7b4a940 aliguori
    /* Cleanup */
936 f7b4a940 aliguori
    bdrv_delete(bs);
937 f7b4a940 aliguori
}
938 f7b4a940 aliguori
939 ea2384d3 bellard
int main(int argc, char **argv)
940 ea2384d3 bellard
{
941 ea2384d3 bellard
    const char *cmd;
942 ea2384d3 bellard
943 ea2384d3 bellard
    bdrv_init();
944 ea2384d3 bellard
    if (argc < 2)
945 ea2384d3 bellard
        help();
946 ea2384d3 bellard
    cmd = argv[1];
947 8f9b157e aurel32
    argc--; argv++;
948 ea2384d3 bellard
    if (!strcmp(cmd, "create")) {
949 ea2384d3 bellard
        img_create(argc, argv);
950 1585969c aliguori
    } else if (!strcmp(cmd, "check")) {
951 1585969c aliguori
        img_check(argc, argv);
952 ea2384d3 bellard
    } else if (!strcmp(cmd, "commit")) {
953 ea2384d3 bellard
        img_commit(argc, argv);
954 ea2384d3 bellard
    } else if (!strcmp(cmd, "convert")) {
955 ea2384d3 bellard
        img_convert(argc, argv);
956 ea2384d3 bellard
    } else if (!strcmp(cmd, "info")) {
957 ea2384d3 bellard
        img_info(argc, argv);
958 f7b4a940 aliguori
    } else if (!strcmp(cmd, "snapshot")) {
959 f7b4a940 aliguori
        img_snapshot(argc, argv);
960 ea2384d3 bellard
    } else {
961 ea2384d3 bellard
        help();
962 ea2384d3 bellard
    }
963 ea2384d3 bellard
    return 0;
964 ea2384d3 bellard
}