Statistics
| Branch: | Revision:

root / qemu-img.c @ d084469c

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

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