Statistics
| Branch: | Revision:

root / qemu-img.c @ 2ac71179

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

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

    
119
#else
120

    
121
#include <termios.h>
122

    
123
static struct termios oldtty;
124

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

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

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

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

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

    
148
    atexit(term_exit);
149
}
150

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

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

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

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

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

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

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

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

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

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

    
344
    bs = bdrv_new("");
345
    if (!bs)
346
        error("Not enough memory");
347
    if (fmt) {
348
        drv = bdrv_find_format(fmt);
349
        if (!drv)
350
            error("Unknown file format '%s'", fmt);
351
    } else {
352
        drv = NULL;
353
    }
354
    if (bdrv_open2(bs, filename, BRDV_O_FLAGS, drv) < 0) {
355
        error("Could not open '%s'", filename);
356
    }
357
    ret = bdrv_check(bs);
358
    switch(ret) {
359
    case 0:
360
        printf("No errors were found on the image.\n");
361
        break;
362
    case -ENOTSUP:
363
        error("This image format does not support checks");
364
        break;
365
    default:
366
        if (ret < 0) {
367
            error("An error occurred during the check");
368
        } else {
369
            printf("%d errors were found on the image.\n", ret);
370
        }
371
        break;
372
    }
373

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

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

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

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

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

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

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

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

    
475
#define IO_BUF_SIZE 65536
476

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

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

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

    
525
    out_filename = argv[argc - 1];
526

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

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

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

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

    
566
    out_bs = bdrv_new_open(out_filename, out_fmt);
567

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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