Statistics
| Branch: | Revision:

root / qemu-img.c @ c2c5104b

History | View | Annotate | Download (25.7 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 {
310
            error("Error while formatting");
311
        }
312
    }
313
    return 0;
314
}
315

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

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

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

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

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

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

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

    
413
#define IO_BUF_SIZE 65536
414

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

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

    
460
    bs_n = argc - optind - 1;
461
    if (bs_n < 1) help();
462

    
463
    out_filename = argv[argc - 1];
464

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

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

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

    
493
    ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags);
494
    if (ret < 0) {
495
        if (ret == -ENOTSUP) {
496
            error("Formatting not supported for file format '%s'", out_fmt);
497
        } else {
498
            error("Error while formatting '%s'", out_filename);
499
        }
500
    }
501

    
502
    out_bs = bdrv_new_open(out_filename, out_fmt);
503

    
504
    bs_i = 0;
505
    bs_offset = 0;
506
    bdrv_get_geometry(bs[0], &bs_sectors);
507

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

    
521
            nb_sectors = total_sectors - sector_num;
522
            if (nb_sectors <= 0)
523
                break;
524
            if (nb_sectors >= cluster_sectors)
525
                n = cluster_sectors;
526
            else
527
                n = nb_sectors;
528

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

    
547
                nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder;
548

    
549
                if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) 
550
                    error("error while reading");
551

    
552
                buf2 += nlow * 512;
553
                bs_num += nlow;
554

    
555
                remainder -= nlow;
556
            }
557
            assert (remainder == 0);
558

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

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

    
592
            if (n > bs_offset + bs_sectors - sector_num)
593
                n = bs_offset + bs_sectors - sector_num;
594

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

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

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

    
640
#ifdef _WIN32
641
static int64_t get_allocated_file_size(const char *filename)
642
{
643
    typedef DWORD (WINAPI * get_compressed_t)(const char *filename, DWORD *high);
644
    get_compressed_t get_compressed;
645
    struct _stati64 st;
646

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

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

    
670
static void dump_snapshots(BlockDriverState *bs)
671
{
672
    QEMUSnapshotInfo *sn_tab, *sn;
673
    int nb_sns, i;
674
    char buf[256];
675

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

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

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

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

    
767
#define SNAPSHOT_LIST   1
768
#define SNAPSHOT_CREATE 2
769
#define SNAPSHOT_APPLY  3
770
#define SNAPSHOT_DELETE 4
771

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

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

    
824
    if (optind >= argc)
825
        help();
826
    filename = argv[optind++];
827

    
828
    /* Open the image */
829
    bs = bdrv_new("");
830
    if (!bs)
831
        error("Not enough memory");
832

    
833
    if (bdrv_open2(bs, filename, 0, NULL) < 0) {
834
        error("Could not open '%s'", filename);
835
    }
836

    
837
    /* Perform the requested action */
838
    switch(action) {
839
    case SNAPSHOT_LIST:
840
        dump_snapshots(bs);
841
        break;
842

    
843
    case SNAPSHOT_CREATE:
844
        memset(&sn, 0, sizeof(sn));
845
        pstrcpy(sn.name, sizeof(sn.name), snapshot_name);
846

    
847
        qemu_gettimeofday(&tv);
848
        sn.date_sec = tv.tv_sec;
849
        sn.date_nsec = tv.tv_usec * 1000;
850

    
851
        ret = bdrv_snapshot_create(bs, &sn);
852
        if (ret)
853
            error("Could not create snapshot '%s': %d (%s)",
854
                snapshot_name, ret, strerror(-ret));
855
        break;
856

    
857
    case SNAPSHOT_APPLY:
858
        ret = bdrv_snapshot_goto(bs, snapshot_name);
859
        if (ret)
860
            error("Could not apply snapshot '%s': %d (%s)",
861
                snapshot_name, ret, strerror(-ret));
862
        break;
863

    
864
    case SNAPSHOT_DELETE:
865
        ret = bdrv_snapshot_delete(bs, snapshot_name);
866
        if (ret)
867
            error("Could not delete snapshot '%s': %d (%s)",
868
                snapshot_name, ret, strerror(-ret));
869
        break;
870
    }
871

    
872
    /* Cleanup */
873
    bdrv_delete(bs);
874
}
875

    
876
int main(int argc, char **argv)
877
{
878
    const char *cmd;
879

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