Statistics
| Branch: | Revision:

root / qemu-img.c @ 6e9ea0c0

History | View | Annotate | Download (25.9 kB)

1
/*
2
 * QEMU disk image utility
3
 *
4
 * Copyright (c) 2003-2008 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "qemu-common.h"
25
#include "osdep.h"
26
#include "block_int.h"
27
#include <assert.h>
28
#include <stdio.h>
29

    
30
#ifdef _WIN32
31
#include <windows.h>
32
#endif
33

    
34
/* Default to cache=writeback as data integrity is not important for qemu-tcg. */
35
#define BRDV_O_FLAGS BDRV_O_CACHE_WB
36

    
37
static void QEMU_NORETURN error(const char *fmt, ...)
38
{
39
    va_list ap;
40
    va_start(ap, fmt);
41
    fprintf(stderr, "qemu-img: ");
42
    vfprintf(stderr, fmt, ap);
43
    fprintf(stderr, "\n");
44
    exit(1);
45
    va_end(ap);
46
}
47

    
48
static void format_print(void *opaque, const char *name)
49
{
50
    printf(" %s", name);
51
}
52

    
53
/* Please keep in synch with qemu-img.texi */
54
static void help(void)
55
{
56
    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
57
           "usage: qemu-img command [command options]\n"
58
           "QEMU disk image utility\n"
59
           "\n"
60
           "Command syntax:\n"
61
           "  create [-e] [-6] [-F fmt] [-b base_image] [-f fmt] filename [size]\n"
62
           "  commit [-f fmt] filename\n"
63
           "  convert [-c] [-e] [-6] [-f fmt] [-O output_fmt] [-B output_base_image] filename [filename2 [...]] output_filename\n"
64
           "  info [-f fmt] filename\n"
65
           "  snapshot [-l | -a snapshot | -c snapshot | -d snapshot] filename\n"
66
           "\n"
67
           "Command parameters:\n"
68
           "  'filename' is a disk image filename\n"
69
           "  'base_image' is the read-only disk image which is used as base for a copy on\n"
70
           "    write image; the copy on write image only stores the modified data\n"
71
           "  'output_base_image' forces the output image to be created as a copy on write\n"
72
           "    image of the specified base image; 'output_base_image' should have the same\n"
73
           "    content as the input's base image, however the path, image format, etc may\n"
74
           "    differ\n"
75
           "  'fmt' is the disk image format. It is guessed automatically in most cases\n"
76
           "  'size' is the disk image size in kilobytes. Optional suffixes\n"
77
           "    'M' (megabyte, 1024 * 1024) and 'G' (gigabyte, 1024 * 1024 * 1024) are\n"
78
           "    supported any 'k' or 'K' is ignored\n"
79
           "  'output_filename' is the destination disk image filename\n"
80
           "  'output_fmt' is the destination format\n"
81
           "  '-c' indicates that target image must be compressed (qcow format only)\n"
82
           "  '-e' indicates that the target image must be encrypted (qcow format only)\n"
83
           "  '-6' indicates that the target image must use compatibility level 6 (vmdk format only)\n"
84
           "  '-h' with or without a command shows this help and lists the supported formats\n"
85
           "\n"
86
           "Parameters to snapshot subcommand:\n"
87
           "  'snapshot' is the name of the snapshot to create, apply or delete\n"
88
           "  '-a' applies a snapshot (revert disk to saved state)\n"
89
           "  '-c' creates a snapshot\n"
90
           "  '-d' deletes a snapshot\n"
91
           "  '-l' lists all snapshots in the given image\n"
92
           );
93
    printf("\nSupported formats:");
94
    bdrv_iterate_format(format_print, NULL);
95
    printf("\n");
96
    exit(1);
97
}
98

    
99
#if defined(WIN32)
100
/* XXX: put correct support for win32 */
101
static int read_password(char *buf, int buf_size)
102
{
103
    int c, i;
104
    printf("Password: ");
105
    fflush(stdout);
106
    i = 0;
107
    for(;;) {
108
        c = getchar();
109
        if (c == '\n')
110
            break;
111
        if (i < (buf_size - 1))
112
            buf[i++] = c;
113
    }
114
    buf[i] = '\0';
115
    return 0;
116
}
117

    
118
#else
119

    
120
#include <termios.h>
121

    
122
static struct termios oldtty;
123

    
124
static void term_exit(void)
125
{
126
    tcsetattr (0, TCSANOW, &oldtty);
127
}
128

    
129
static void term_init(void)
130
{
131
    struct termios tty;
132

    
133
    tcgetattr (0, &tty);
134
    oldtty = tty;
135

    
136
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
137
                          |INLCR|IGNCR|ICRNL|IXON);
138
    tty.c_oflag |= OPOST;
139
    tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
140
    tty.c_cflag &= ~(CSIZE|PARENB);
141
    tty.c_cflag |= CS8;
142
    tty.c_cc[VMIN] = 1;
143
    tty.c_cc[VTIME] = 0;
144

    
145
    tcsetattr (0, TCSANOW, &tty);
146

    
147
    atexit(term_exit);
148
}
149

    
150
static int read_password(char *buf, int buf_size)
151
{
152
    uint8_t ch;
153
    int i, ret;
154

    
155
    printf("password: ");
156
    fflush(stdout);
157
    term_init();
158
    i = 0;
159
    for(;;) {
160
        ret = read(0, &ch, 1);
161
        if (ret == -1) {
162
            if (errno == EAGAIN || errno == EINTR) {
163
                continue;
164
            } else {
165
                ret = -1;
166
                break;
167
            }
168
        } else if (ret == 0) {
169
            ret = -1;
170
            break;
171
        } else {
172
            if (ch == '\r') {
173
                ret = 0;
174
                break;
175
            }
176
            if (i < (buf_size - 1))
177
                buf[i++] = ch;
178
        }
179
    }
180
    term_exit();
181
    buf[i] = '\0';
182
    printf("\n");
183
    return ret;
184
}
185
#endif
186

    
187
static BlockDriverState *bdrv_new_open(const char *filename,
188
                                       const char *fmt)
189
{
190
    BlockDriverState *bs;
191
    BlockDriver *drv;
192
    char password[256];
193

    
194
    bs = bdrv_new("");
195
    if (!bs)
196
        error("Not enough memory");
197
    if (fmt) {
198
        drv = bdrv_find_format(fmt);
199
        if (!drv)
200
            error("Unknown file format '%s'", fmt);
201
    } else {
202
        drv = NULL;
203
    }
204
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
205
        error("Could not open '%s'", filename);
206
    }
207
    if (bdrv_is_encrypted(bs)) {
208
        printf("Disk image '%s' is encrypted.\n", filename);
209
        if (read_password(password, sizeof(password)) < 0)
210
            error("No password given");
211
        if (bdrv_set_key(bs, password) < 0)
212
            error("invalid password");
213
    }
214
    return bs;
215
}
216

    
217
static int img_create(int argc, char **argv)
218
{
219
    int c, ret, flags;
220
    const char *fmt = "raw";
221
    const char *base_fmt = NULL;
222
    const char *filename;
223
    const char *base_filename = NULL;
224
    uint64_t size;
225
    double sizef;
226
    const char *p;
227
    BlockDriver *drv;
228

    
229
    flags = 0;
230
    for(;;) {
231
        c = getopt(argc, argv, "F:b:f:he6");
232
        if (c == -1)
233
            break;
234
        switch(c) {
235
        case 'h':
236
            help();
237
            break;
238
        case 'F':
239
            base_fmt = optarg;
240
            break;
241
        case 'b':
242
            base_filename = optarg;
243
            break;
244
        case 'f':
245
            fmt = optarg;
246
            break;
247
        case 'e':
248
            flags |= BLOCK_FLAG_ENCRYPT;
249
            break;
250
        case '6':
251
            flags |= BLOCK_FLAG_COMPAT6;
252
            break;
253
        }
254
    }
255
    if (optind >= argc)
256
        help();
257
    filename = argv[optind++];
258
    size = 0;
259
    if (base_filename) {
260
        BlockDriverState *bs;
261
        BlockDriver *base_drv = NULL;
262

    
263
        if (base_fmt) {
264
            base_drv = bdrv_find_format(base_fmt);
265
            if (base_drv == NULL)
266
                error("Unknown basefile format '%s'", base_fmt);
267
        }
268

    
269
        bs = bdrv_new_open(base_filename, base_fmt);
270
        bdrv_get_geometry(bs, &size);
271
        size *= 512;
272
        bdrv_delete(bs);
273
    } else {
274
        if (optind >= argc)
275
            help();
276
        p = argv[optind];
277
        sizef = strtod(p, (char **)&p);
278
        if (*p == 'M') {
279
            size = (uint64_t)(sizef * 1024 * 1024);
280
        } else if (*p == 'G') {
281
            size = (uint64_t)(sizef * 1024 * 1024 * 1024);
282
        } else if (*p == 'k' || *p == 'K' || *p == '\0') {
283
            size = (uint64_t)(sizef * 1024);
284
        } else {
285
            help();
286
        }
287
    }
288
    drv = bdrv_find_format(fmt);
289
    if (!drv)
290
        error("Unknown file format '%s'", fmt);
291
    printf("Formatting '%s', fmt=%s",
292
           filename, fmt);
293
    if (flags & BLOCK_FLAG_ENCRYPT)
294
        printf(", encrypted");
295
    if (flags & BLOCK_FLAG_COMPAT6)
296
        printf(", compatibility level=6");
297
    if (base_filename) {
298
        printf(", backing_file=%s",
299
               base_filename);
300
         if (base_fmt)
301
             printf(", backing_fmt=%s",
302
                    base_fmt);
303
    }
304
    printf(", size=%" PRIu64 " kB\n", size / 1024);
305
    ret = bdrv_create2(drv, filename, size / 512, base_filename, base_fmt, flags);
306
    if (ret < 0) {
307
        if (ret == -ENOTSUP) {
308
            error("Formatting or formatting option not supported for file format '%s'", fmt);
309
        } else if (ret == -EFBIG) {
310
            error("The image size is too large for file format '%s'", fmt);
311
        } else {
312
            error("Error while formatting");
313
        }
314
    }
315
    return 0;
316
}
317

    
318
static int img_commit(int argc, char **argv)
319
{
320
    int c, ret;
321
    const char *filename, *fmt;
322
    BlockDriver *drv;
323
    BlockDriverState *bs;
324

    
325
    fmt = NULL;
326
    for(;;) {
327
        c = getopt(argc, argv, "f:h");
328
        if (c == -1)
329
            break;
330
        switch(c) {
331
        case 'h':
332
            help();
333
            break;
334
        case 'f':
335
            fmt = optarg;
336
            break;
337
        }
338
    }
339
    if (optind >= argc)
340
        help();
341
    filename = argv[optind++];
342

    
343
    bs = bdrv_new("");
344
    if (!bs)
345
        error("Not enough memory");
346
    if (fmt) {
347
        drv = bdrv_find_format(fmt);
348
        if (!drv)
349
            error("Unknown file format '%s'", fmt);
350
    } else {
351
        drv = NULL;
352
    }
353
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
354
        error("Could not open '%s'", filename);
355
    }
356
    ret = bdrv_commit(bs);
357
    switch(ret) {
358
    case 0:
359
        printf("Image committed.\n");
360
        break;
361
    case -ENOENT:
362
        error("No disk inserted");
363
        break;
364
    case -EACCES:
365
        error("Image is read-only");
366
        break;
367
    case -ENOTSUP:
368
        error("Image is already committed");
369
        break;
370
    default:
371
        error("Error while committing image");
372
        break;
373
    }
374

    
375
    bdrv_delete(bs);
376
    return 0;
377
}
378

    
379
static int is_not_zero(const uint8_t *sector, int len)
380
{
381
    int i;
382
    len >>= 2;
383
    for(i = 0;i < len; i++) {
384
        if (((uint32_t *)sector)[i] != 0)
385
            return 1;
386
    }
387
    return 0;
388
}
389

    
390
/*
391
 * Returns true iff the first sector pointed to by 'buf' contains at least
392
 * a non-NUL byte.
393
 *
394
 * 'pnum' is set to the number of sectors (including and immediately following
395
 * the first one) that are known to be in the same allocated/unallocated state.
396
 */
397
static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
398
{
399
    int v, i;
400

    
401
    if (n <= 0) {
402
        *pnum = 0;
403
        return 0;
404
    }
405
    v = is_not_zero(buf, 512);
406
    for(i = 1; i < n; i++) {
407
        buf += 512;
408
        if (v != is_not_zero(buf, 512))
409
            break;
410
    }
411
    *pnum = i;
412
    return v;
413
}
414

    
415
#define IO_BUF_SIZE 65536
416

    
417
static int img_convert(int argc, char **argv)
418
{
419
    int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
420
    const char *fmt, *out_fmt, *out_baseimg, *out_filename;
421
    BlockDriver *drv;
422
    BlockDriverState **bs, *out_bs;
423
    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
424
    uint64_t bs_sectors;
425
    uint8_t buf[IO_BUF_SIZE];
426
    const uint8_t *buf1;
427
    BlockDriverInfo bdi;
428

    
429
    fmt = NULL;
430
    out_fmt = "raw";
431
    out_baseimg = NULL;
432
    flags = 0;
433
    for(;;) {
434
        c = getopt(argc, argv, "f:O:B:hce6");
435
        if (c == -1)
436
            break;
437
        switch(c) {
438
        case 'h':
439
            help();
440
            break;
441
        case 'f':
442
            fmt = optarg;
443
            break;
444
        case 'O':
445
            out_fmt = optarg;
446
            break;
447
        case 'B':
448
            out_baseimg = optarg;
449
            break;
450
        case 'c':
451
            flags |= BLOCK_FLAG_COMPRESS;
452
            break;
453
        case 'e':
454
            flags |= BLOCK_FLAG_ENCRYPT;
455
            break;
456
        case '6':
457
            flags |= BLOCK_FLAG_COMPAT6;
458
            break;
459
        }
460
    }
461

    
462
    bs_n = argc - optind - 1;
463
    if (bs_n < 1) help();
464

    
465
    out_filename = argv[argc - 1];
466

    
467
    if (bs_n > 1 && out_baseimg)
468
        error("-B makes no sense when concatenating multiple input images");
469
        
470
    bs = calloc(bs_n, sizeof(BlockDriverState *));
471
    if (!bs)
472
        error("Out of memory");
473

    
474
    total_sectors = 0;
475
    for (bs_i = 0; bs_i < bs_n; bs_i++) {
476
        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
477
        if (!bs[bs_i])
478
            error("Could not open '%s'", argv[optind + bs_i]);
479
        bdrv_get_geometry(bs[bs_i], &bs_sectors);
480
        total_sectors += bs_sectors;
481
    }
482

    
483
    drv = bdrv_find_format(out_fmt);
484
    if (!drv)
485
        error("Unknown file format '%s'", out_fmt);
486
    if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2)
487
        error("Compression not supported for this file format");
488
    if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2)
489
        error("Encryption not supported for this file format");
490
    if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk)
491
        error("Alternative compatibility level not supported for this file format");
492
    if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
493
        error("Compression and encryption not supported at the same time");
494

    
495
    ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
496
    if (ret < 0) {
497
        if (ret == -ENOTSUP) {
498
            error("Formatting not supported for file format '%s'", out_fmt);
499
        } else if (ret == -EFBIG) {
500
            error("The image size is too large for file format '%s'", out_fmt);
501
        } else {
502
            error("Error while formatting '%s'", out_filename);
503
        }
504
    }
505

    
506
    out_bs = bdrv_new_open(out_filename, out_fmt);
507

    
508
    bs_i = 0;
509
    bs_offset = 0;
510
    bdrv_get_geometry(bs[0], &bs_sectors);
511

    
512
    if (flags & BLOCK_FLAG_COMPRESS) {
513
        if (bdrv_get_info(out_bs, &bdi) < 0)
514
            error("could not get block driver info");
515
        cluster_size = bdi.cluster_size;
516
        if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
517
            error("invalid cluster size");
518
        cluster_sectors = cluster_size >> 9;
519
        sector_num = 0;
520
        for(;;) {
521
            int64_t bs_num;
522
            int remainder;
523
            uint8_t *buf2;
524

    
525
            nb_sectors = total_sectors - sector_num;
526
            if (nb_sectors <= 0)
527
                break;
528
            if (nb_sectors >= cluster_sectors)
529
                n = cluster_sectors;
530
            else
531
                n = nb_sectors;
532

    
533
            bs_num = sector_num - bs_offset;
534
            assert (bs_num >= 0);
535
            remainder = n;
536
            buf2 = buf;
537
            while (remainder > 0) {
538
                int nlow;
539
                while (bs_num == bs_sectors) {
540
                    bs_i++;
541
                    assert (bs_i < bs_n);
542
                    bs_offset += bs_sectors;
543
                    bdrv_get_geometry(bs[bs_i], &bs_sectors);
544
                    bs_num = 0;
545
                    /* printf("changing part: sector_num=%lld, "
546
                       "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
547
                       sector_num, bs_i, bs_offset, bs_sectors); */
548
                }
549
                assert (bs_num < bs_sectors);
550

    
551
                nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
552

    
553
                if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) 
554
                    error("error while reading");
555

    
556
                buf2 += nlow * 512;
557
                bs_num += nlow;
558

    
559
                remainder -= nlow;
560
            }
561
            assert (remainder == 0);
562

    
563
            if (n < cluster_sectors)
564
                memset(buf + n * 512, 0, cluster_size - n * 512);
565
            if (is_not_zero(buf, cluster_size)) {
566
                if (bdrv_write_compressed(out_bs, sector_num, buf,
567
                                          cluster_sectors) != 0)
568
                    error("error while compressing sector %" PRId64,
569
                          sector_num);
570
            }
571
            sector_num += n;
572
        }
573
        /* signal EOF to align */
574
        bdrv_write_compressed(out_bs, 0, NULL, 0);
575
    } else {
576
        sector_num = 0; // total number of sectors converted so far
577
        for(;;) {
578
            nb_sectors = total_sectors - sector_num;
579
            if (nb_sectors <= 0)
580
                break;
581
            if (nb_sectors >= (IO_BUF_SIZE / 512))
582
                n = (IO_BUF_SIZE / 512);
583
            else
584
                n = nb_sectors;
585

    
586
            while (sector_num - bs_offset >= bs_sectors) {
587
                bs_i ++;
588
                assert (bs_i < bs_n);
589
                bs_offset += bs_sectors;
590
                bdrv_get_geometry(bs[bs_i], &bs_sectors);
591
                /* printf("changing part: sector_num=%lld, bs_i=%d, "
592
                  "bs_offset=%lld, bs_sectors=%lld\n",
593
                   sector_num, bs_i, bs_offset, bs_sectors); */
594
            }
595

    
596
            if (n > bs_offset + bs_sectors - sector_num)
597
                n = bs_offset + bs_sectors - sector_num;
598

    
599
            if (drv != &bdrv_host_device) {
600
                if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
601
                                       n, &n1)) {
602
                    sector_num += n1;
603
                    continue;
604
                }
605
                /* The next 'n1' sectors are allocated in the input image. Copy
606
                   only those as they may be followed by unallocated sectors. */
607
                n = n1;
608
            } else {
609
                n1 = n;
610
            }
611

    
612
            if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) 
613
                error("error while reading");
614
            /* NOTE: at the same time we convert, we do not write zero
615
               sectors to have a chance to compress the image. Ideally, we
616
               should add a specific call to have the info to go faster */
617
            buf1 = buf;
618
            while (n > 0) {
619
                /* If the output image is being created as a copy on write image,
620
                   copy all sectors even the ones containing only NUL bytes,
621
                   because they may differ from the sectors in the base image.
622

623
                   If the output is to a host device, we also write out
624
                   sectors that are entirely 0, since whatever data was
625
                   already there is garbage, not 0s. */
626
                if (drv == &bdrv_host_device || out_baseimg ||
627
                    is_allocated_sectors(buf1, n, &n1)) {
628
                    if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
629
                        error("error while writing");
630
                }
631
                sector_num += n1;
632
                n -= n1;
633
                buf1 += n1 * 512;
634
            }
635
        }
636
    }
637
    bdrv_delete(out_bs);
638
    for (bs_i = 0; bs_i < bs_n; bs_i++)
639
        bdrv_delete(bs[bs_i]);
640
    free(bs);
641
    return 0;
642
}
643

    
644
#ifdef _WIN32
645
static int64_t get_allocated_file_size(const char *filename)
646
{
647
    typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
648
    get_compressed_t get_compressed;
649
    struct _stati64 st;
650

    
651
    /* WinNT support GetCompressedFileSize to determine allocate size */
652
    get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
653
    if (get_compressed) {
654
            DWORD high, low;
655
            low = get_compressed(filename, &high);
656
            if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
657
            return (((int64_t) high) << 32) + low;
658
    }
659

    
660
    if (_stati64(filename, &st) < 0)
661
        return -1;
662
    return st.st_size;
663
}
664
#else
665
static int64_t get_allocated_file_size(const char *filename)
666
{
667
    struct stat st;
668
    if (stat(filename, &st) < 0)
669
        return -1;
670
    return (int64_t)st.st_blocks * 512;
671
}
672
#endif
673

    
674
static void dump_snapshots(BlockDriverState *bs)
675
{
676
    QEMUSnapshotInfo *sn_tab, *sn;
677
    int nb_sns, i;
678
    char buf[256];
679

    
680
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
681
    if (nb_sns <= 0)
682
        return;
683
    printf("Snapshot list:\n");
684
    printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
685
    for(i = 0; i < nb_sns; i++) {
686
        sn = &sn_tab[i];
687
        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
688
    }
689
    qemu_free(sn_tab);
690
}
691

    
692
static int img_info(int argc, char **argv)
693
{
694
    int c;
695
    const char *filename, *fmt;
696
    BlockDriver *drv;
697
    BlockDriverState *bs;
698
    char fmt_name[128], size_buf[128], dsize_buf[128];
699
    uint64_t total_sectors;
700
    int64_t allocated_size;
701
    char backing_filename[1024];
702
    char backing_filename2[1024];
703
    BlockDriverInfo bdi;
704

    
705
    fmt = NULL;
706
    for(;;) {
707
        c = getopt(argc, argv, "f:h");
708
        if (c == -1)
709
            break;
710
        switch(c) {
711
        case 'h':
712
            help();
713
            break;
714
        case 'f':
715
            fmt = optarg;
716
            break;
717
        }
718
    }
719
    if (optind >= argc)
720
        help();
721
    filename = argv[optind++];
722

    
723
    bs = bdrv_new("");
724
    if (!bs)
725
        error("Not enough memory");
726
    if (fmt) {
727
        drv = bdrv_find_format(fmt);
728
        if (!drv)
729
            error("Unknown file format '%s'", fmt);
730
    } else {
731
        drv = NULL;
732
    }
733
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
734
        error("Could not open '%s'", filename);
735
    }
736
    bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
737
    bdrv_get_geometry(bs, &total_sectors);
738
    get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
739
    allocated_size = get_allocated_file_size(filename);
740
    if (allocated_size < 0)
741
        snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
742
    else
743
        get_human_readable_size(dsize_buf, sizeof(dsize_buf),
744
                                allocated_size);
745
    printf("image: %s\n"
746
           "file format: %s\n"
747
           "virtual size: %s (%" PRId64 " bytes)\n"
748
           "disk size: %s\n",
749
           filename, fmt_name, size_buf,
750
           (total_sectors * 512),
751
           dsize_buf);
752
    if (bdrv_is_encrypted(bs))
753
        printf("encrypted: yes\n");
754
    if (bdrv_get_info(bs, &bdi) >= 0) {
755
        if (bdi.cluster_size != 0)
756
            printf("cluster_size: %d\n", bdi.cluster_size);
757
    }
758
    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
759
    if (backing_filename[0] != '\0') {
760
        path_combine(backing_filename2, sizeof(backing_filename2),
761
                     filename, backing_filename);
762
        printf("backing file: %s (actual path: %s)\n",
763
               backing_filename,
764
               backing_filename2);
765
    }
766
    dump_snapshots(bs);
767
    bdrv_delete(bs);
768
    return 0;
769
}
770

    
771
#define SNAPSHOT_LIST   1
772
#define SNAPSHOT_CREATE 2
773
#define SNAPSHOT_APPLY  3
774
#define SNAPSHOT_DELETE 4
775

    
776
static void img_snapshot(int argc, char **argv)
777
{
778
    BlockDriverState *bs;
779
    QEMUSnapshotInfo sn;
780
    char *filename, *snapshot_name = NULL;
781
    int c, ret;
782
    int action = 0;
783
    qemu_timeval tv;
784

    
785
    /* Parse commandline parameters */
786
    for(;;) {
787
        c = getopt(argc, argv, "la:c:d:h");
788
        if (c == -1)
789
            break;
790
        switch(c) {
791
        case 'h':
792
            help();
793
            return;
794
        case 'l':
795
            if (action) {
796
                help();
797
                return;
798
            }
799
            action = SNAPSHOT_LIST;
800
            break;
801
        case 'a':
802
            if (action) {
803
                help();
804
                return;
805
            }
806
            action = SNAPSHOT_APPLY;
807
            snapshot_name = optarg;
808
            break;
809
        case 'c':
810
            if (action) {
811
                help();
812
                return;
813
            }
814
            action = SNAPSHOT_CREATE;
815
            snapshot_name = optarg;
816
            break;
817
        case 'd':
818
            if (action) {
819
                help();
820
                return;
821
            }
822
            action = SNAPSHOT_DELETE;
823
            snapshot_name = optarg;
824
            break;
825
        }
826
    }
827

    
828
    if (optind >= argc)
829
        help();
830
    filename = argv[optind++];
831

    
832
    /* Open the image */
833
    bs = bdrv_new("");
834
    if (!bs)
835
        error("Not enough memory");
836

    
837
    if (bdrv_open2(bs, filename, 0, NULL) < 0) {
838
        error("Could not open '%s'", filename);
839
    }
840

    
841
    /* Perform the requested action */
842
    switch(action) {
843
    case SNAPSHOT_LIST:
844
        dump_snapshots(bs);
845
        break;
846

    
847
    case SNAPSHOT_CREATE:
848
        memset(&sn, 0, sizeof(sn));
849
        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
850

    
851
        qemu_gettimeofday(&tv);
852
        sn.date_sec = tv.tv_sec;
853
        sn.date_nsec = tv.tv_usec * 1000;
854

    
855
        ret = bdrv_snapshot_create(bs, &sn);
856
        if (ret)
857
            error("Could not create snapshot '%s': %d (%s)",
858
                snapshot_name, ret, strerror(-ret));
859
        break;
860

    
861
    case SNAPSHOT_APPLY:
862
        ret = bdrv_snapshot_goto(bs, snapshot_name);
863
        if (ret)
864
            error("Could not apply snapshot '%s': %d (%s)",
865
                snapshot_name, ret, strerror(-ret));
866
        break;
867

    
868
    case SNAPSHOT_DELETE:
869
        ret = bdrv_snapshot_delete(bs, snapshot_name);
870
        if (ret)
871
            error("Could not delete snapshot '%s': %d (%s)",
872
                snapshot_name, ret, strerror(-ret));
873
        break;
874
    }
875

    
876
    /* Cleanup */
877
    bdrv_delete(bs);
878
}
879

    
880
int main(int argc, char **argv)
881
{
882
    const char *cmd;
883

    
884
    bdrv_init();
885
    if (argc < 2)
886
        help();
887
    cmd = argv[1];
888
    argc--; argv++;
889
    if (!strcmp(cmd, "create")) {
890
        img_create(argc, argv);
891
    } else if (!strcmp(cmd, "commit")) {
892
        img_commit(argc, argv);
893
    } else if (!strcmp(cmd, "convert")) {
894
        img_convert(argc, argv);
895
    } else if (!strcmp(cmd, "info")) {
896
        img_info(argc, argv);
897
    } else if (!strcmp(cmd, "snapshot")) {
898
        img_snapshot(argc, argv);
899
    } else {
900
        help();
901
    }
902
    return 0;
903
}