Statistics
| Branch: | Revision:

root / qemu-img.c @ 5efa9d5a

History | View | Annotate | Download (27.4 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 <stdio.h>
28

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

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

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

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

    
52
/* Please keep in synch with qemu-img.texi */
53
static void help(void)
54
{
55
    printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004-2008 Fabrice Bellard\n"
56
           "usage: qemu-img command [command options]\n"
57
           "QEMU disk image utility\n"
58
           "\n"
59
           "Command syntax:\n"
60
           "  check [-f fmt] filename\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_check(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_check(bs);
357
    switch(ret) {
358
    case 0:
359
        printf("No errors were found on the image.\n");
360
        break;
361
    case -ENOTSUP:
362
        error("This image format does not support checks");
363
        break;
364
    default:
365
        if (ret < 0) {
366
            error("An error occurred during the check");
367
        } else {
368
            printf("%d errors were found on the image.\n", ret);
369
        }
370
        break;
371
    }
372

    
373
    bdrv_delete(bs);
374
    return 0;
375
}
376

    
377
static int img_commit(int argc, char **argv)
378
{
379
    int c, ret;
380
    const char *filename, *fmt;
381
    BlockDriver *drv;
382
    BlockDriverState *bs;
383

    
384
    fmt = NULL;
385
    for(;;) {
386
        c = getopt(argc, argv, "f:h");
387
        if (c == -1)
388
            break;
389
        switch(c) {
390
        case 'h':
391
            help();
392
            break;
393
        case 'f':
394
            fmt = optarg;
395
            break;
396
        }
397
    }
398
    if (optind >= argc)
399
        help();
400
    filename = argv[optind++];
401

    
402
    bs = bdrv_new("");
403
    if (!bs)
404
        error("Not enough memory");
405
    if (fmt) {
406
        drv = bdrv_find_format(fmt);
407
        if (!drv)
408
            error("Unknown file format '%s'", fmt);
409
    } else {
410
        drv = NULL;
411
    }
412
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
413
        error("Could not open '%s'", filename);
414
    }
415
    ret = bdrv_commit(bs);
416
    switch(ret) {
417
    case 0:
418
        printf("Image committed.\n");
419
        break;
420
    case -ENOENT:
421
        error("No disk inserted");
422
        break;
423
    case -EACCES:
424
        error("Image is read-only");
425
        break;
426
    case -ENOTSUP:
427
        error("Image is already committed");
428
        break;
429
    default:
430
        error("Error while committing image");
431
        break;
432
    }
433

    
434
    bdrv_delete(bs);
435
    return 0;
436
}
437

    
438
static int is_not_zero(const uint8_t *sector, int len)
439
{
440
    int i;
441
    len >>= 2;
442
    for(i = 0;i < len; i++) {
443
        if (((uint32_t *)sector)[i] != 0)
444
            return 1;
445
    }
446
    return 0;
447
}
448

    
449
/*
450
 * Returns true iff the first sector pointed to by 'buf' contains at least
451
 * a non-NUL byte.
452
 *
453
 * 'pnum' is set to the number of sectors (including and immediately following
454
 * the first one) that are known to be in the same allocated/unallocated state.
455
 */
456
static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
457
{
458
    int v, i;
459

    
460
    if (n <= 0) {
461
        *pnum = 0;
462
        return 0;
463
    }
464
    v = is_not_zero(buf, 512);
465
    for(i = 1; i < n; i++) {
466
        buf += 512;
467
        if (v != is_not_zero(buf, 512))
468
            break;
469
    }
470
    *pnum = i;
471
    return v;
472
}
473

    
474
#define IO_BUF_SIZE 65536
475

    
476
static int img_convert(int argc, char **argv)
477
{
478
    int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
479
    const char *fmt, *out_fmt, *out_baseimg, *out_filename;
480
    BlockDriver *drv;
481
    BlockDriverState **bs, *out_bs;
482
    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
483
    uint64_t bs_sectors;
484
    uint8_t buf[IO_BUF_SIZE];
485
    const uint8_t *buf1;
486
    BlockDriverInfo bdi;
487

    
488
    fmt = NULL;
489
    out_fmt = "raw";
490
    out_baseimg = NULL;
491
    flags = 0;
492
    for(;;) {
493
        c = getopt(argc, argv, "f:O:B:hce6");
494
        if (c == -1)
495
            break;
496
        switch(c) {
497
        case 'h':
498
            help();
499
            break;
500
        case 'f':
501
            fmt = optarg;
502
            break;
503
        case 'O':
504
            out_fmt = optarg;
505
            break;
506
        case 'B':
507
            out_baseimg = optarg;
508
            break;
509
        case 'c':
510
            flags |= BLOCK_FLAG_COMPRESS;
511
            break;
512
        case 'e':
513
            flags |= BLOCK_FLAG_ENCRYPT;
514
            break;
515
        case '6':
516
            flags |= BLOCK_FLAG_COMPAT6;
517
            break;
518
        }
519
    }
520

    
521
    bs_n = argc - optind - 1;
522
    if (bs_n < 1) help();
523

    
524
    out_filename = argv[argc - 1];
525

    
526
    if (bs_n > 1 && out_baseimg)
527
        error("-B makes no sense when concatenating multiple input images");
528
        
529
    bs = calloc(bs_n, sizeof(BlockDriverState *));
530
    if (!bs)
531
        error("Out of memory");
532

    
533
    total_sectors = 0;
534
    for (bs_i = 0; bs_i < bs_n; bs_i++) {
535
        bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
536
        if (!bs[bs_i])
537
            error("Could not open '%s'", argv[optind + bs_i]);
538
        bdrv_get_geometry(bs[bs_i], &bs_sectors);
539
        total_sectors += bs_sectors;
540
    }
541

    
542
    drv = bdrv_find_format(out_fmt);
543
    if (!drv)
544
        error("Unknown file format '%s'", out_fmt);
545
    if (flags & BLOCK_FLAG_COMPRESS && strcmp(drv->format_name, "qcow") && strcmp(drv->format_name, "qcow2"))
546
        error("Compression not supported for this file format");
547
    if (flags & BLOCK_FLAG_ENCRYPT && strcmp(drv->format_name, "qcow") && strcmp(drv->format_name, "qcow2"))
548
        error("Encryption not supported for this file format");
549
    if (flags & BLOCK_FLAG_COMPAT6 && strcmp(drv->format_name, "vmdk"))
550
        error("Alternative compatibility level not supported for this file format");
551
    if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS)
552
        error("Compression and encryption not supported at the same time");
553

    
554
    ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
555
    if (ret < 0) {
556
        if (ret == -ENOTSUP) {
557
            error("Formatting not supported for file format '%s'", out_fmt);
558
        } else if (ret == -EFBIG) {
559
            error("The image size is too large for file format '%s'", out_fmt);
560
        } else {
561
            error("Error while formatting '%s'", out_filename);
562
        }
563
    }
564

    
565
    out_bs = bdrv_new_open(out_filename, out_fmt);
566

    
567
    bs_i = 0;
568
    bs_offset = 0;
569
    bdrv_get_geometry(bs[0], &bs_sectors);
570

    
571
    if (flags & BLOCK_FLAG_COMPRESS) {
572
        if (bdrv_get_info(out_bs, &bdi) < 0)
573
            error("could not get block driver info");
574
        cluster_size = bdi.cluster_size;
575
        if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
576
            error("invalid cluster size");
577
        cluster_sectors = cluster_size >> 9;
578
        sector_num = 0;
579
        for(;;) {
580
            int64_t bs_num;
581
            int remainder;
582
            uint8_t *buf2;
583

    
584
            nb_sectors = total_sectors - sector_num;
585
            if (nb_sectors <= 0)
586
                break;
587
            if (nb_sectors >= cluster_sectors)
588
                n = cluster_sectors;
589
            else
590
                n = nb_sectors;
591

    
592
            bs_num = sector_num - bs_offset;
593
            assert (bs_num >= 0);
594
            remainder = n;
595
            buf2 = buf;
596
            while (remainder > 0) {
597
                int nlow;
598
                while (bs_num == bs_sectors) {
599
                    bs_i++;
600
                    assert (bs_i < bs_n);
601
                    bs_offset += bs_sectors;
602
                    bdrv_get_geometry(bs[bs_i], &bs_sectors);
603
                    bs_num = 0;
604
                    /* printf("changing part: sector_num=%lld, "
605
                       "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
606
                       sector_num, bs_i, bs_offset, bs_sectors); */
607
                }
608
                assert (bs_num < bs_sectors);
609

    
610
                nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
611

    
612
                if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) 
613
                    error("error while reading");
614

    
615
                buf2 += nlow * 512;
616
                bs_num += nlow;
617

    
618
                remainder -= nlow;
619
            }
620
            assert (remainder == 0);
621

    
622
            if (n < cluster_sectors)
623
                memset(buf + n * 512, 0, cluster_size - n * 512);
624
            if (is_not_zero(buf, cluster_size)) {
625
                if (bdrv_write_compressed(out_bs, sector_num, buf,
626
                                          cluster_sectors) != 0)
627
                    error("error while compressing sector %" PRId64,
628
                          sector_num);
629
            }
630
            sector_num += n;
631
        }
632
        /* signal EOF to align */
633
        bdrv_write_compressed(out_bs, 0, NULL, 0);
634
    } else {
635
        sector_num = 0; // total number of sectors converted so far
636
        for(;;) {
637
            nb_sectors = total_sectors - sector_num;
638
            if (nb_sectors <= 0)
639
                break;
640
            if (nb_sectors >= (IO_BUF_SIZE / 512))
641
                n = (IO_BUF_SIZE / 512);
642
            else
643
                n = nb_sectors;
644

    
645
            while (sector_num - bs_offset >= bs_sectors) {
646
                bs_i ++;
647
                assert (bs_i < bs_n);
648
                bs_offset += bs_sectors;
649
                bdrv_get_geometry(bs[bs_i], &bs_sectors);
650
                /* printf("changing part: sector_num=%lld, bs_i=%d, "
651
                  "bs_offset=%lld, bs_sectors=%lld\n",
652
                   sector_num, bs_i, bs_offset, bs_sectors); */
653
            }
654

    
655
            if (n > bs_offset + bs_sectors - sector_num)
656
                n = bs_offset + bs_sectors - sector_num;
657

    
658
            if (strcmp(drv->format_name, "host_device")) {
659
                if (!bdrv_is_allocated(bs[bs_i], sector_num - bs_offset,
660
                                       n, &n1)) {
661
                    sector_num += n1;
662
                    continue;
663
                }
664
                /* The next 'n1' sectors are allocated in the input image. Copy
665
                   only those as they may be followed by unallocated sectors. */
666
                n = n1;
667
            } else {
668
                n1 = n;
669
            }
670

    
671
            if (bdrv_read(bs[bs_i], sector_num - bs_offset, buf, n) < 0) 
672
                error("error while reading");
673
            /* NOTE: at the same time we convert, we do not write zero
674
               sectors to have a chance to compress the image. Ideally, we
675
               should add a specific call to have the info to go faster */
676
            buf1 = buf;
677
            while (n > 0) {
678
                /* If the output image is being created as a copy on write image,
679
                   copy all sectors even the ones containing only NUL bytes,
680
                   because they may differ from the sectors in the base image.
681

682
                   If the output is to a host device, we also write out
683
                   sectors that are entirely 0, since whatever data was
684
                   already there is garbage, not 0s. */
685
                if (strcmp(drv->format_name, "host_device") == 0 || out_baseimg ||
686
                    is_allocated_sectors(buf1, n, &n1)) {
687
                    if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
688
                        error("error while writing");
689
                }
690
                sector_num += n1;
691
                n -= n1;
692
                buf1 += n1 * 512;
693
            }
694
        }
695
    }
696
    bdrv_delete(out_bs);
697
    for (bs_i = 0; bs_i < bs_n; bs_i++)
698
        bdrv_delete(bs[bs_i]);
699
    free(bs);
700
    return 0;
701
}
702

    
703
#ifdef _WIN32
704
static int64_t get_allocated_file_size(const char *filename)
705
{
706
    typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
707
    get_compressed_t get_compressed;
708
    struct _stati64 st;
709

    
710
    /* WinNT support GetCompressedFileSize to determine allocate size */
711
    get_compressed = (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), "GetCompressedFileSizeA");
712
    if (get_compressed) {
713
            DWORD high, low;
714
            low = get_compressed(filename, &high);
715
            if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR)
716
            return (((int64_t) high) << 32) + low;
717
    }
718

    
719
    if (_stati64(filename, &st) < 0)
720
        return -1;
721
    return st.st_size;
722
}
723
#else
724
static int64_t get_allocated_file_size(const char *filename)
725
{
726
    struct stat st;
727
    if (stat(filename, &st) < 0)
728
        return -1;
729
    return (int64_t)st.st_blocks * 512;
730
}
731
#endif
732

    
733
static void dump_snapshots(BlockDriverState *bs)
734
{
735
    QEMUSnapshotInfo *sn_tab, *sn;
736
    int nb_sns, i;
737
    char buf[256];
738

    
739
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
740
    if (nb_sns <= 0)
741
        return;
742
    printf("Snapshot list:\n");
743
    printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
744
    for(i = 0; i < nb_sns; i++) {
745
        sn = &sn_tab[i];
746
        printf("%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
747
    }
748
    qemu_free(sn_tab);
749
}
750

    
751
static int img_info(int argc, char **argv)
752
{
753
    int c;
754
    const char *filename, *fmt;
755
    BlockDriver *drv;
756
    BlockDriverState *bs;
757
    char fmt_name[128], size_buf[128], dsize_buf[128];
758
    uint64_t total_sectors;
759
    int64_t allocated_size;
760
    char backing_filename[1024];
761
    char backing_filename2[1024];
762
    BlockDriverInfo bdi;
763

    
764
    fmt = NULL;
765
    for(;;) {
766
        c = getopt(argc, argv, "f:h");
767
        if (c == -1)
768
            break;
769
        switch(c) {
770
        case 'h':
771
            help();
772
            break;
773
        case 'f':
774
            fmt = optarg;
775
            break;
776
        }
777
    }
778
    if (optind >= argc)
779
        help();
780
    filename = argv[optind++];
781

    
782
    bs = bdrv_new("");
783
    if (!bs)
784
        error("Not enough memory");
785
    if (fmt) {
786
        drv = bdrv_find_format(fmt);
787
        if (!drv)
788
            error("Unknown file format '%s'", fmt);
789
    } else {
790
        drv = NULL;
791
    }
792
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
793
        error("Could not open '%s'", filename);
794
    }
795
    bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
796
    bdrv_get_geometry(bs, &total_sectors);
797
    get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
798
    allocated_size = get_allocated_file_size(filename);
799
    if (allocated_size < 0)
800
        snprintf(dsize_buf, sizeof(dsize_buf), "unavailable");
801
    else
802
        get_human_readable_size(dsize_buf, sizeof(dsize_buf),
803
                                allocated_size);
804
    printf("image: %s\n"
805
           "file format: %s\n"
806
           "virtual size: %s (%" PRId64 " bytes)\n"
807
           "disk size: %s\n",
808
           filename, fmt_name, size_buf,
809
           (total_sectors * 512),
810
           dsize_buf);
811
    if (bdrv_is_encrypted(bs))
812
        printf("encrypted: yes\n");
813
    if (bdrv_get_info(bs, &bdi) >= 0) {
814
        if (bdi.cluster_size != 0)
815
            printf("cluster_size: %d\n", bdi.cluster_size);
816
    }
817
    bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename));
818
    if (backing_filename[0] != '\0') {
819
        path_combine(backing_filename2, sizeof(backing_filename2),
820
                     filename, backing_filename);
821
        printf("backing file: %s (actual path: %s)\n",
822
               backing_filename,
823
               backing_filename2);
824
    }
825
    dump_snapshots(bs);
826
    bdrv_delete(bs);
827
    return 0;
828
}
829

    
830
#define SNAPSHOT_LIST   1
831
#define SNAPSHOT_CREATE 2
832
#define SNAPSHOT_APPLY  3
833
#define SNAPSHOT_DELETE 4
834

    
835
static void img_snapshot(int argc, char **argv)
836
{
837
    BlockDriverState *bs;
838
    QEMUSnapshotInfo sn;
839
    char *filename, *snapshot_name = NULL;
840
    int c, ret;
841
    int action = 0;
842
    qemu_timeval tv;
843

    
844
    /* Parse commandline parameters */
845
    for(;;) {
846
        c = getopt(argc, argv, "la:c:d:h");
847
        if (c == -1)
848
            break;
849
        switch(c) {
850
        case 'h':
851
            help();
852
            return;
853
        case 'l':
854
            if (action) {
855
                help();
856
                return;
857
            }
858
            action = SNAPSHOT_LIST;
859
            break;
860
        case 'a':
861
            if (action) {
862
                help();
863
                return;
864
            }
865
            action = SNAPSHOT_APPLY;
866
            snapshot_name = optarg;
867
            break;
868
        case 'c':
869
            if (action) {
870
                help();
871
                return;
872
            }
873
            action = SNAPSHOT_CREATE;
874
            snapshot_name = optarg;
875
            break;
876
        case 'd':
877
            if (action) {
878
                help();
879
                return;
880
            }
881
            action = SNAPSHOT_DELETE;
882
            snapshot_name = optarg;
883
            break;
884
        }
885
    }
886

    
887
    if (optind >= argc)
888
        help();
889
    filename = argv[optind++];
890

    
891
    /* Open the image */
892
    bs = bdrv_new("");
893
    if (!bs)
894
        error("Not enough memory");
895

    
896
    if (bdrv_open2(bs, filename, 0, NULL) < 0) {
897
        error("Could not open '%s'", filename);
898
    }
899

    
900
    /* Perform the requested action */
901
    switch(action) {
902
    case SNAPSHOT_LIST:
903
        dump_snapshots(bs);
904
        break;
905

    
906
    case SNAPSHOT_CREATE:
907
        memset(&sn, 0, sizeof(sn));
908
        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
909

    
910
        qemu_gettimeofday(&tv);
911
        sn.date_sec = tv.tv_sec;
912
        sn.date_nsec = tv.tv_usec * 1000;
913

    
914
        ret = bdrv_snapshot_create(bs, &sn);
915
        if (ret)
916
            error("Could not create snapshot '%s': %d (%s)",
917
                snapshot_name, ret, strerror(-ret));
918
        break;
919

    
920
    case SNAPSHOT_APPLY:
921
        ret = bdrv_snapshot_goto(bs, snapshot_name);
922
        if (ret)
923
            error("Could not apply snapshot '%s': %d (%s)",
924
                snapshot_name, ret, strerror(-ret));
925
        break;
926

    
927
    case SNAPSHOT_DELETE:
928
        ret = bdrv_snapshot_delete(bs, snapshot_name);
929
        if (ret)
930
            error("Could not delete snapshot '%s': %d (%s)",
931
                snapshot_name, ret, strerror(-ret));
932
        break;
933
    }
934

    
935
    /* Cleanup */
936
    bdrv_delete(bs);
937
}
938

    
939
int main(int argc, char **argv)
940
{
941
    const char *cmd;
942

    
943
    bdrv_init();
944
    if (argc < 2)
945
        help();
946
    cmd = argv[1];
947
    argc--; argv++;
948
    if (!strcmp(cmd, "create")) {
949
        img_create(argc, argv);
950
    } else if (!strcmp(cmd, "check")) {
951
        img_check(argc, argv);
952
    } else if (!strcmp(cmd, "commit")) {
953
        img_commit(argc, argv);
954
    } else if (!strcmp(cmd, "convert")) {
955
        img_convert(argc, argv);
956
    } else if (!strcmp(cmd, "info")) {
957
        img_info(argc, argv);
958
    } else if (!strcmp(cmd, "snapshot")) {
959
        img_snapshot(argc, argv);
960
    } else {
961
        help();
962
    }
963
    return 0;
964
}