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

30
#ifdef CONFIG_BSD
bellard's avatar
bellard committed
31 32 33
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
34
#include <sys/queue.h>
35
#ifndef __DragonFly__
bellard's avatar
bellard committed
36 37
#include <sys/disk.h>
#endif
38
#endif
bellard's avatar
bellard committed
39

40 41 42 43
#ifdef _WIN32
#include <windows.h>
#endif

bellard's avatar
bellard committed
44 45 46
#define SECTOR_BITS 9
#define SECTOR_SIZE (1 << SECTOR_BITS)

47 48
static BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
49
        BlockDriverCompletionFunc *cb, void *opaque);
50 51
static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
52
        BlockDriverCompletionFunc *cb, void *opaque);
53 54
static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
        BlockDriverCompletionFunc *cb, void *opaque);
55
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
bellard's avatar
bellard committed
56 57 58
                        uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
                         const uint8_t *buf, int nb_sectors);
bellard's avatar
bellard committed
59

60 61
BlockDriverState *bdrv_first;

bellard's avatar
bellard committed
62 63
static BlockDriver *first_drv;

bellard's avatar
bellard committed
64
int path_is_absolute(const char *path)
65
{
bellard's avatar
bellard committed
66
    const char *p;
bellard's avatar
bellard committed
67 68 69 70 71
#ifdef _WIN32
    /* specific case for names like: "\\.\d:" */
    if (*path == '/' || *path == '\\')
        return 1;
#endif
bellard's avatar
bellard committed
72 73 74 75 76
    p = strchr(path, ':');
    if (p)
        p++;
    else
        p = path;
77 78 79 80 81
#ifdef _WIN32
    return (*p == '/' || *p == '\\');
#else
    return (*p == '/');
#endif
82 83
}

bellard's avatar
bellard committed
84 85 86 87 88 89
/* if filename is absolute, just copy it to dest. Otherwise, build a
   path to it by considering it is relative to base_path. URL are
   supported. */
void path_combine(char *dest, int dest_size,
                  const char *base_path,
                  const char *filename)
90
{
bellard's avatar
bellard committed
91 92 93 94 95 96 97 98 99 100 101 102 103
    const char *p, *p1;
    int len;

    if (dest_size <= 0)
        return;
    if (path_is_absolute(filename)) {
        pstrcpy(dest, dest_size, filename);
    } else {
        p = strchr(base_path, ':');
        if (p)
            p++;
        else
            p = base_path;
104 105 106 107 108 109 110 111 112
        p1 = strrchr(base_path, '/');
#ifdef _WIN32
        {
            const char *p2;
            p2 = strrchr(base_path, '\\');
            if (!p1 || p2 > p1)
                p1 = p2;
        }
#endif
bellard's avatar
bellard committed
113 114 115 116 117 118 119 120 121 122 123 124
        if (p1)
            p1++;
        else
            p1 = base_path;
        if (p1 > p)
            p = p1;
        len = p - base_path;
        if (len > dest_size - 1)
            len = dest_size - 1;
        memcpy(dest, base_path, len);
        dest[len] = '\0';
        pstrcat(dest, dest_size, filename);
125 126 127
    }
}

128
void bdrv_register(BlockDriver *bdrv)
bellard's avatar
bellard committed
129
{
130
    if (!bdrv->bdrv_aio_readv) {
bellard's avatar
bellard committed
131
        /* add AIO emulation layer */
132 133
        bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
        bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
134
    } else if (!bdrv->bdrv_read) {
bellard's avatar
bellard committed
135 136 137 138
        /* add synchronous IO emulation layer */
        bdrv->bdrv_read = bdrv_read_em;
        bdrv->bdrv_write = bdrv_write_em;
    }
139 140 141 142

    if (!bdrv->bdrv_aio_flush)
        bdrv->bdrv_aio_flush = bdrv_aio_flush_em;

bellard's avatar
bellard committed
143 144 145
    bdrv->next = first_drv;
    first_drv = bdrv;
}
bellard's avatar
bellard committed
146 147 148 149 150 151 152 153

/* create a new block device (by default it is empty) */
BlockDriverState *bdrv_new(const char *device_name)
{
    BlockDriverState **pbs, *bs;

    bs = qemu_mallocz(sizeof(BlockDriverState));
    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
bellard's avatar
bellard committed
154 155 156 157 158 159 160
    if (device_name[0] != '\0') {
        /* insert at the end */
        pbs = &bdrv_first;
        while (*pbs != NULL)
            pbs = &(*pbs)->next;
        *pbs = bs;
    }
bellard's avatar
bellard committed
161 162 163
    return bs;
}

bellard's avatar
bellard committed
164 165 166 167 168 169 170 171 172 173
BlockDriver *bdrv_find_format(const char *format_name)
{
    BlockDriver *drv1;
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
        if (!strcmp(drv1->format_name, format_name))
            return drv1;
    }
    return NULL;
}

174 175
int bdrv_create(BlockDriver *drv, const char* filename,
    QEMUOptionParameter *options)
bellard's avatar
bellard committed
176 177 178
{
    if (!drv->bdrv_create)
        return -ENOTSUP;
179 180

    return drv->bdrv_create(filename, options);
bellard's avatar
bellard committed
181 182
}

bellard's avatar
bellard committed
183
#ifdef _WIN32
184
void get_tmp_filename(char *filename, int size)
bellard's avatar
bellard committed
185
{
186
    char temp_dir[MAX_PATH];
187

188 189
    GetTempPath(MAX_PATH, temp_dir);
    GetTempFileName(temp_dir, "qem", 0, filename);
bellard's avatar
bellard committed
190 191
}
#else
192
void get_tmp_filename(char *filename, int size)
bellard's avatar
bellard committed
193
{
bellard's avatar
bellard committed
194
    int fd;
195
    const char *tmpdir;
bellard's avatar
bellard committed
196
    /* XXX: race condition possible */
aurel32's avatar
aurel32 committed
197 198 199 200
    tmpdir = getenv("TMPDIR");
    if (!tmpdir)
        tmpdir = "/tmp";
    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
bellard's avatar
bellard committed
201 202 203
    fd = mkstemp(filename);
    close(fd);
}
bellard's avatar
bellard committed
204
#endif
bellard's avatar
bellard committed
205

bellard's avatar
bellard committed
206
#ifdef _WIN32
bellard's avatar
bellard committed
207 208 209 210 211 212
static int is_windows_drive_prefix(const char *filename)
{
    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
            filename[1] == ':');
}
213

214
int is_windows_drive(const char *filename)
bellard's avatar
bellard committed
215
{
216
    if (is_windows_drive_prefix(filename) &&
bellard's avatar
bellard committed
217
        filename[2] == '\0')
bellard's avatar
bellard committed
218 219 220 221 222 223 224 225
        return 1;
    if (strstart(filename, "\\\\.\\", NULL) ||
        strstart(filename, "//./", NULL))
        return 1;
    return 0;
}
#endif

bellard's avatar
bellard committed
226 227 228 229
static BlockDriver *find_protocol(const char *filename)
{
    BlockDriver *drv1;
    char protocol[128];
230
    int len;
bellard's avatar
bellard committed
231
    const char *p;
bellard's avatar
bellard committed
232 233

#ifdef _WIN32
bellard's avatar
bellard committed
234 235
    if (is_windows_drive(filename) ||
        is_windows_drive_prefix(filename))
236
        return bdrv_find_format("raw");
bellard's avatar
bellard committed
237
#endif
238 239
    p = strchr(filename, ':');
    if (!p)
240
        return bdrv_find_format("raw");
241 242 243 244 245
    len = p - filename;
    if (len > sizeof(protocol) - 1)
        len = sizeof(protocol) - 1;
    memcpy(protocol, filename, len);
    protocol[len] = '\0';
bellard's avatar
bellard committed
246
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
247
        if (drv1->protocol_name &&
bellard's avatar
bellard committed
248 249 250 251 252 253
            !strcmp(drv1->protocol_name, protocol))
            return drv1;
    }
    return NULL;
}

254 255 256 257 258 259
/*
 * Detect host devices. By convention, /dev/cdrom[N] is always
 * recognized as a host CDROM.
 */
static BlockDriver *find_hdev_driver(const char *filename)
{
260 261
    int score_max = 0, score;
    BlockDriver *drv = NULL, *d;
262

263 264 265 266 267 268 269 270
    for (d = first_drv; d; d = d->next) {
        if (d->bdrv_probe_device) {
            score = d->bdrv_probe_device(filename);
            if (score > score_max) {
                score_max = score;
                drv = d;
            }
        }
bellard's avatar
bellard committed
271
    }
272

273
    return drv;
274
}
275

276 277 278 279 280 281 282
static BlockDriver *find_image_format(const char *filename)
{
    int ret, score, score_max;
    BlockDriver *drv1, *drv;
    uint8_t buf[2048];
    BlockDriverState *bs;

bellard's avatar
bellard committed
283
    drv = find_protocol(filename);
bellard's avatar
bellard committed
284
    /* no need to test disk image formats for vvfat */
285
    if (drv && strcmp(drv->format_name, "vvfat") == 0)
bellard's avatar
bellard committed
286
        return drv;
bellard's avatar
bellard committed
287

bellard's avatar
bellard committed
288 289 290 291 292 293 294 295 296
    ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
    if (ret < 0)
        return NULL;
    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
    bdrv_delete(bs);
    if (ret < 0) {
        return NULL;
    }

bellard's avatar
bellard committed
297 298
    score_max = 0;
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
bellard's avatar
bellard committed
299 300 301 302 303 304
        if (drv1->bdrv_probe) {
            score = drv1->bdrv_probe(buf, ret, filename);
            if (score > score_max) {
                score_max = score;
                drv = drv1;
            }
bellard's avatar
bellard committed
305
        }
bellard's avatar
bellard committed
306
    }
bellard's avatar
bellard committed
307 308 309
    return drv;
}

bellard's avatar
bellard committed
310
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
bellard's avatar
bellard committed
311
{
bellard's avatar
bellard committed
312 313 314 315 316 317 318 319
    BlockDriverState *bs;
    int ret;

    bs = bdrv_new("");
    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
    if (ret < 0) {
        bdrv_delete(bs);
        return ret;
320
    }
321
    bs->growable = 1;
bellard's avatar
bellard committed
322 323 324 325 326 327 328
    *pbs = bs;
    return 0;
}

int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
{
    return bdrv_open2(bs, filename, flags, NULL);
bellard's avatar
bellard committed
329 330
}

bellard's avatar
bellard committed
331
int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
bellard's avatar
bellard committed
332 333
               BlockDriver *drv)
{
bellard's avatar
bellard committed
334
    int ret, open_flags;
335 336
    char tmp_filename[PATH_MAX];
    char backing_filename[PATH_MAX];
337

bellard's avatar
bellard committed
338 339 340
    bs->read_only = 0;
    bs->is_temporary = 0;
    bs->encrypted = 0;
341
    bs->valid_key = 0;
342 343
    /* buffer_alignment defaulted to 512, drivers can change this value */
    bs->buffer_alignment = 512;
bellard's avatar
bellard committed
344

bellard's avatar
bellard committed
345
    if (flags & BDRV_O_SNAPSHOT) {
bellard's avatar
bellard committed
346 347
        BlockDriverState *bs1;
        int64_t total_size;
aliguori's avatar
aliguori committed
348
        int is_protocol = 0;
Kevin Wolf's avatar
Kevin Wolf committed
349 350
        BlockDriver *bdrv_qcow2;
        QEMUOptionParameter *options;
351

bellard's avatar
bellard committed
352 353
        /* if snapshot, we create a temporary backing file and open it
           instead of opening 'filename' directly */
354

bellard's avatar
bellard committed
355 356
        /* if there is a backing file, use it */
        bs1 = bdrv_new("");
357
        ret = bdrv_open2(bs1, filename, 0, drv);
358
        if (ret < 0) {
bellard's avatar
bellard committed
359
            bdrv_delete(bs1);
360
            return ret;
bellard's avatar
bellard committed
361
        }
bellard's avatar
bellard committed
362
        total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
aliguori's avatar
aliguori committed
363 364 365 366

        if (bs1->drv && bs1->drv->protocol_name)
            is_protocol = 1;

bellard's avatar
bellard committed
367
        bdrv_delete(bs1);
368

bellard's avatar
bellard committed
369
        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
aliguori's avatar
aliguori committed
370 371 372 373 374 375 376 377

        /* Real path is meaningless for protocols */
        if (is_protocol)
            snprintf(backing_filename, sizeof(backing_filename),
                     "%s", filename);
        else
            realpath(filename, backing_filename);

Kevin Wolf's avatar
Kevin Wolf committed
378 379 380 381 382 383 384 385 386 387 388
        bdrv_qcow2 = bdrv_find_format("qcow2");
        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);

        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);
        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
        if (drv) {
            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
                drv->format_name);
        }

        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
389 390
        if (ret < 0) {
            return ret;
bellard's avatar
bellard committed
391
        }
Kevin Wolf's avatar
Kevin Wolf committed
392

bellard's avatar
bellard committed
393
        filename = tmp_filename;
Kevin Wolf's avatar
Kevin Wolf committed
394
        drv = bdrv_qcow2;
bellard's avatar
bellard committed
395 396
        bs->is_temporary = 1;
    }
bellard's avatar
bellard committed
397

bellard's avatar
bellard committed
398
    pstrcpy(bs->filename, sizeof(bs->filename), filename);
bellard's avatar
bellard committed
399 400
    if (flags & BDRV_O_FILE) {
        drv = find_protocol(filename);
401
    } else if (!drv) {
402 403 404 405
        drv = find_hdev_driver(filename);
        if (!drv) {
            drv = find_image_format(filename);
        }
406 407 408 409
    }
    if (!drv) {
        ret = -ENOENT;
        goto unlink_and_fail;
bellard's avatar
bellard committed
410 411 412
    }
    bs->drv = drv;
    bs->opaque = qemu_mallocz(drv->instance_size);
413 414 415 416 417 418 419 420 421 422

    /*
     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
     * write cache to the guest.  We do need the fdatasync to flush
     * out transactions for block allocations, and we maybe have a
     * volatile write cache in our backing device to deal with.
     */
    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
        bs->enable_write_cache = 1;

bellard's avatar
bellard committed
423 424 425
    /* Note: for compatibility, we open disk image files as RDWR, and
       RDONLY as fallback */
    if (!(flags & BDRV_O_FILE))
426 427
        open_flags = BDRV_O_RDWR |
		(flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO));
bellard's avatar
bellard committed
428 429
    else
        open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
430
    ret = drv->bdrv_open(bs, filename, open_flags);
431
    if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
432
        ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
bellard's avatar
bellard committed
433 434
        bs->read_only = 1;
    }
bellard's avatar
bellard committed
435 436
    if (ret < 0) {
        qemu_free(bs->opaque);
bellard's avatar
bellard committed
437 438
        bs->opaque = NULL;
        bs->drv = NULL;
439 440 441
    unlink_and_fail:
        if (bs->is_temporary)
            unlink(filename);
bellard's avatar
bellard committed
442
        return ret;
443
    }
444 445 446
    if (drv->bdrv_getlength) {
        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
    }
bellard's avatar
bellard committed
447
#ifndef _WIN32
bellard's avatar
bellard committed
448 449 450 451
    if (bs->is_temporary) {
        unlink(filename);
    }
#endif
bellard's avatar
bellard committed
452
    if (bs->backing_file[0] != '\0') {
bellard's avatar
bellard committed
453
        /* if there is a backing file, use it */
454
        BlockDriver *back_drv = NULL;
bellard's avatar
bellard committed
455
        bs->backing_hd = bdrv_new("");
bellard's avatar
bellard committed
456 457
        path_combine(backing_filename, sizeof(backing_filename),
                     filename, bs->backing_file);
458 459 460 461
        if (bs->backing_format[0] != '\0')
            back_drv = bdrv_find_format(bs->backing_format);
        ret = bdrv_open2(bs->backing_hd, backing_filename, open_flags,
                         back_drv);
462 463 464 465
        if (ret < 0) {
            bdrv_close(bs);
            return ret;
        }
466 467
    }

468 469 470 471 472 473
    if (!bdrv_key_required(bs)) {
        /* call the change callback */
        bs->media_changed = 1;
        if (bs->change_cb)
            bs->change_cb(bs->change_opaque);
    }
bellard's avatar
bellard committed
474
    return 0;
bellard's avatar
bellard committed
475 476 477 478
}

void bdrv_close(BlockDriverState *bs)
{
bellard's avatar
bellard committed
479
    if (bs->drv) {
bellard's avatar
bellard committed
480 481 482 483 484 485 486 487
        if (bs->backing_hd)
            bdrv_delete(bs->backing_hd);
        bs->drv->bdrv_close(bs);
        qemu_free(bs->opaque);
#ifdef _WIN32
        if (bs->is_temporary) {
            unlink(bs->filename);
        }
bellard's avatar
bellard committed
488
#endif
bellard's avatar
bellard committed
489 490
        bs->opaque = NULL;
        bs->drv = NULL;
bellard's avatar
bellard committed
491 492

        /* call the change callback */
bellard's avatar
bellard committed
493
        bs->media_changed = 1;
bellard's avatar
bellard committed
494 495 496 497 498 499 500
        if (bs->change_cb)
            bs->change_cb(bs->change_opaque);
    }
}

void bdrv_delete(BlockDriverState *bs)
{
501 502 503 504 505 506 507 508
    BlockDriverState **pbs;

    pbs = &bdrv_first;
    while (*pbs != bs && *pbs != NULL)
        pbs = &(*pbs)->next;
    if (*pbs == bs)
        *pbs = bs->next;

bellard's avatar
bellard committed
509 510
    bdrv_close(bs);
    qemu_free(bs);
bellard's avatar
bellard committed
511 512
}

aliguori's avatar
aliguori committed
513 514 515 516 517 518 519 520 521 522 523 524 525 526
/*
 * Run consistency checks on an image
 *
 * Returns the number of errors or -errno when an internal error occurs
 */
int bdrv_check(BlockDriverState *bs)
{
    if (bs->drv->bdrv_check == NULL) {
        return -ENOTSUP;
    }

    return bs->drv->bdrv_check(bs);
}

527 528 529
/* commit COW file into the raw image */
int bdrv_commit(BlockDriverState *bs)
{
bellard's avatar
bellard committed
530
    BlockDriver *drv = bs->drv;
bellard's avatar
bellard committed
531
    int64_t i, total_sectors;
bellard's avatar
bellard committed
532 533
    int n, j;
    unsigned char sector[512];
534

bellard's avatar
bellard committed
535 536
    if (!drv)
        return -ENOMEDIUM;
537 538

    if (bs->read_only) {
bellard's avatar
bellard committed
539
	return -EACCES;
540 541
    }

bellard's avatar
bellard committed
542 543 544
    if (!bs->backing_hd) {
	return -ENOTSUP;
    }
545

bellard's avatar
bellard committed
546 547
    total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
    for (i = 0; i < total_sectors;) {
bellard's avatar
bellard committed
548
        if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
bellard's avatar
bellard committed
549 550 551 552 553 554 555 556 557
            for(j = 0; j < n; j++) {
                if (bdrv_read(bs, i, sector, 1) != 0) {
                    return -EIO;
                }

                if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
                    return -EIO;
                }
                i++;
558
	    }
bellard's avatar
bellard committed
559 560 561
	} else {
            i += n;
        }
562
    }
563

bellard's avatar
bellard committed
564 565
    if (drv->bdrv_make_empty)
	return drv->bdrv_make_empty(bs);
566

567 568 569
    return 0;
}

570 571 572 573 574 575 576 577 578 579 580 581 582
static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
                                   size_t size)
{
    int64_t len;

    if (!bdrv_is_inserted(bs))
        return -ENOMEDIUM;

    if (bs->growable)
        return 0;

    len = bdrv_getlength(bs);

Kevin Wolf's avatar
Kevin Wolf committed
583 584 585 586
    if (offset < 0)
        return -EIO;

    if ((offset > len) || (len - offset < size))
587 588 589 590 591 592 593 594
        return -EIO;

    return 0;
}

static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
                              int nb_sectors)
{
595
    return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
596 597
}

bellard's avatar
bellard committed
598
/* return < 0 if error. See bdrv_write() for the return codes */
599
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
bellard's avatar
bellard committed
600 601
              uint8_t *buf, int nb_sectors)
{
bellard's avatar
bellard committed
602 603
    BlockDriver *drv = bs->drv;

bellard's avatar
bellard committed
604 605
    if (!drv)
        return -ENOMEDIUM;
606 607
    if (bdrv_check_request(bs, sector_num, nb_sectors))
        return -EIO;
bellard's avatar
bellard committed
608

609
    return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
bellard's avatar
bellard committed
610 611
}

612
/* Return < 0 if error. Important errors are:
bellard's avatar
bellard committed
613 614 615 616 617
  -EIO         generic I/O error (may happen for all errors)
  -ENOMEDIUM   No media inserted.
  -EINVAL      Invalid sector number or nb_sectors
  -EACCES      Trying to write a read-only device
*/
618
int bdrv_write(BlockDriverState *bs, int64_t sector_num,
bellard's avatar
bellard committed
619 620
               const uint8_t *buf, int nb_sectors)
{
bellard's avatar
bellard committed
621
    BlockDriver *drv = bs->drv;
bellard's avatar
bellard committed
622 623
    if (!bs->drv)
        return -ENOMEDIUM;
bellard's avatar
bellard committed
624
    if (bs->read_only)
bellard's avatar
bellard committed
625
        return -EACCES;
626 627 628
    if (bdrv_check_request(bs, sector_num, nb_sectors))
        return -EIO;

629
    return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
bellard's avatar
bellard committed
630 631
}

632 633
int bdrv_pread(BlockDriverState *bs, int64_t offset,
               void *buf, int count1)
bellard's avatar
bellard committed
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
{
    uint8_t tmp_buf[SECTOR_SIZE];
    int len, nb_sectors, count;
    int64_t sector_num;

    count = count1;
    /* first read to align to sector start */
    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
    if (len > count)
        len = count;
    sector_num = offset >> SECTOR_BITS;
    if (len > 0) {
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
            return -EIO;
        memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
        count -= len;
        if (count == 0)
            return count1;
        sector_num++;
        buf += len;
    }

    /* read the sectors "in place" */
    nb_sectors = count >> SECTOR_BITS;
    if (nb_sectors > 0) {
        if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
            return -EIO;
        sector_num += nb_sectors;
        len = nb_sectors << SECTOR_BITS;
        buf += len;
        count -= len;
    }

    /* add data from the last sector */
    if (count > 0) {
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
            return -EIO;
        memcpy(buf, tmp_buf, count);
    }
    return count1;
}

676 677
int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
                const void *buf, int count1)
bellard's avatar
bellard committed
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
{
    uint8_t tmp_buf[SECTOR_SIZE];
    int len, nb_sectors, count;
    int64_t sector_num;

    count = count1;
    /* first write to align to sector start */
    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
    if (len > count)
        len = count;
    sector_num = offset >> SECTOR_BITS;
    if (len > 0) {
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
            return -EIO;
        memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
            return -EIO;
        count -= len;
        if (count == 0)
            return count1;
        sector_num++;
        buf += len;
    }

    /* write the sectors "in place" */
    nb_sectors = count >> SECTOR_BITS;
    if (nb_sectors > 0) {
        if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
            return -EIO;
        sector_num += nb_sectors;
        len = nb_sectors << SECTOR_BITS;
        buf += len;
        count -= len;
    }

    /* add data from the last sector */
    if (count > 0) {
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
            return -EIO;
        memcpy(tmp_buf, buf, count);
        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
            return -EIO;
    }
    return count1;
}

/**
 * Truncate file to 'offset' bytes (needed only for file protocols)
 */
int bdrv_truncate(BlockDriverState *bs, int64_t offset)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
731
        return -ENOMEDIUM;
bellard's avatar
bellard committed
732 733 734 735 736 737 738 739 740 741 742 743
    if (!drv->bdrv_truncate)
        return -ENOTSUP;
    return drv->bdrv_truncate(bs, offset);
}

/**
 * Length of a file in bytes. Return < 0 if error or unknown.
 */
int64_t bdrv_getlength(BlockDriverState *bs)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
744
        return -ENOMEDIUM;
bellard's avatar
bellard committed
745 746 747 748 749
    if (!drv->bdrv_getlength) {
        /* legacy mode */
        return bs->total_sectors * SECTOR_SIZE;
    }
    return drv->bdrv_getlength(bs);
bellard's avatar
bellard committed
750 751
}

bellard's avatar
bellard committed
752
/* return 0 as number of sectors if no device present or error */
753
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
bellard's avatar
bellard committed
754
{
bellard's avatar
bellard committed
755 756 757 758 759 760 761
    int64_t length;
    length = bdrv_getlength(bs);
    if (length < 0)
        length = 0;
    else
        length = length >> SECTOR_BITS;
    *nb_sectors_ptr = length;
bellard's avatar
bellard committed
762
}
bellard's avatar
bellard committed
763

764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
struct partition {
        uint8_t boot_ind;           /* 0x80 - active */
        uint8_t head;               /* starting head */
        uint8_t sector;             /* starting sector */
        uint8_t cyl;                /* starting cylinder */
        uint8_t sys_ind;            /* What partition type */
        uint8_t end_head;           /* end head */
        uint8_t end_sector;         /* end sector */
        uint8_t end_cyl;            /* end cylinder */
        uint32_t start_sect;        /* starting sector counting from 0 */
        uint32_t nr_sects;          /* nr of sectors in partition */
} __attribute__((packed));

/* try to guess the disk logical geometry from the MSDOS partition table. Return 0 if OK, -1 if could not guess */
static int guess_disk_lchs(BlockDriverState *bs,
                           int *pcylinders, int *pheads, int *psectors)
{
    uint8_t buf[512];
    int ret, i, heads, sectors, cylinders;
    struct partition *p;
    uint32_t nr_sects;
785
    uint64_t nb_sectors;
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824

    bdrv_get_geometry(bs, &nb_sectors);

    ret = bdrv_read(bs, 0, buf, 1);
    if (ret < 0)
        return -1;
    /* test msdos magic */
    if (buf[510] != 0x55 || buf[511] != 0xaa)
        return -1;
    for(i = 0; i < 4; i++) {
        p = ((struct partition *)(buf + 0x1be)) + i;
        nr_sects = le32_to_cpu(p->nr_sects);
        if (nr_sects && p->end_head) {
            /* We make the assumption that the partition terminates on
               a cylinder boundary */
            heads = p->end_head + 1;
            sectors = p->end_sector & 63;
            if (sectors == 0)
                continue;
            cylinders = nb_sectors / (heads * sectors);
            if (cylinders < 1 || cylinders > 16383)
                continue;
            *pheads = heads;
            *psectors = sectors;
            *pcylinders = cylinders;
#if 0
            printf("guessed geometry: LCHS=%d %d %d\n",
                   cylinders, heads, sectors);
#endif
            return 0;
        }
    }
    return -1;
}

void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs)
{
    int translation, lba_detected = 0;
    int cylinders, heads, secs;
825
    uint64_t nb_sectors;
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879

    /* if a geometry hint is available, use it */
    bdrv_get_geometry(bs, &nb_sectors);
    bdrv_get_geometry_hint(bs, &cylinders, &heads, &secs);
    translation = bdrv_get_translation_hint(bs);
    if (cylinders != 0) {
        *pcyls = cylinders;
        *pheads = heads;
        *psecs = secs;
    } else {
        if (guess_disk_lchs(bs, &cylinders, &heads, &secs) == 0) {
            if (heads > 16) {
                /* if heads > 16, it means that a BIOS LBA
                   translation was active, so the default
                   hardware geometry is OK */
                lba_detected = 1;
                goto default_geometry;
            } else {
                *pcyls = cylinders;
                *pheads = heads;
                *psecs = secs;
                /* disable any translation to be in sync with
                   the logical geometry */
                if (translation == BIOS_ATA_TRANSLATION_AUTO) {
                    bdrv_set_translation_hint(bs,
                                              BIOS_ATA_TRANSLATION_NONE);
                }
            }
        } else {
        default_geometry:
            /* if no geometry, use a standard physical disk geometry */
            cylinders = nb_sectors / (16 * 63);

            if (cylinders > 16383)
                cylinders = 16383;
            else if (cylinders < 2)
                cylinders = 2;
            *pcyls = cylinders;
            *pheads = 16;
            *psecs = 63;
            if ((lba_detected == 1) && (translation == BIOS_ATA_TRANSLATION_AUTO)) {
                if ((*pcyls * *pheads) <= 131072) {
                    bdrv_set_translation_hint(bs,
                                              BIOS_ATA_TRANSLATION_LARGE);
                } else {
                    bdrv_set_translation_hint(bs,
                                              BIOS_ATA_TRANSLATION_LBA);
                }
            }
        }
        bdrv_set_geometry_hint(bs, *pcyls, *pheads, *psecs);
    }
}

880
void bdrv_set_geometry_hint(BlockDriverState *bs,
bellard's avatar
bellard committed
881 882 883 884 885 886 887 888 889 890 891 892 893 894
                            int cyls, int heads, int secs)
{
    bs->cyls = cyls;
    bs->heads = heads;
    bs->secs = secs;
}

void bdrv_set_type_hint(BlockDriverState *bs, int type)
{
    bs->type = type;
    bs->removable = ((type == BDRV_TYPE_CDROM ||
                      type == BDRV_TYPE_FLOPPY));
}

895 896 897 898 899
void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
{
    bs->translation = translation;
}

900
void bdrv_get_geometry_hint(BlockDriverState *bs,
bellard's avatar
bellard committed
901 902 903 904 905 906 907 908 909 910 911 912
                            int *pcyls, int *pheads, int *psecs)
{
    *pcyls = bs->cyls;
    *pheads = bs->heads;
    *psecs = bs->secs;
}

int bdrv_get_type_hint(BlockDriverState *bs)
{
    return bs->type;
}

913 914 915 916 917
int bdrv_get_translation_hint(BlockDriverState *bs)
{
    return bs->translation;
}

bellard's avatar
bellard committed
918 919 920 921 922 923 924 925 926 927
int bdrv_is_removable(BlockDriverState *bs)
{
    return bs->removable;
}

int bdrv_is_read_only(BlockDriverState *bs)
{
    return bs->read_only;
}

928 929 930 931 932
int bdrv_is_sg(BlockDriverState *bs)
{
    return bs->sg;
}

933 934 935 936 937
int bdrv_enable_write_cache(BlockDriverState *bs)
{
    return bs->enable_write_cache;
}

bellard's avatar
bellard committed
938
/* XXX: no longer used */
939
void bdrv_set_change_cb(BlockDriverState *bs,
bellard's avatar
bellard committed
940 941 942 943 944 945
                        void (*change_cb)(void *opaque), void *opaque)
{
    bs->change_cb = change_cb;
    bs->change_opaque = opaque;
}

bellard's avatar
bellard committed
946 947 948 949 950 951 952
int bdrv_is_encrypted(BlockDriverState *bs)
{
    if (bs->backing_hd && bs->backing_hd->encrypted)
        return 1;
    return bs->encrypted;
}

953 954 955 956 957 958 959 960 961
int bdrv_key_required(BlockDriverState *bs)
{
    BlockDriverState *backing_hd = bs->backing_hd;

    if (backing_hd && backing_hd->encrypted && !backing_hd->valid_key)
        return 1;
    return (bs->encrypted && !bs->valid_key);
}

bellard's avatar
bellard committed
962 963 964 965 966 967 968 969 970 971 972 973
int bdrv_set_key(BlockDriverState *bs, const char *key)
{
    int ret;
    if (bs->backing_hd && bs->backing_hd->encrypted) {
        ret = bdrv_set_key(bs->backing_hd, key);
        if (ret < 0)
            return ret;
        if (!bs->encrypted)
            return 0;
    }
    if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
        return -1;
974
    ret = bs->drv->bdrv_set_key(bs, key);
975 976 977 978 979 980 981 982 983
    if (ret < 0) {
        bs->valid_key = 0;
    } else if (!bs->valid_key) {
        bs->valid_key = 1;
        /* call the change callback now, we skipped it on open */
        bs->media_changed = 1;
        if (bs->change_cb)
            bs->change_cb(bs->change_opaque);
    }
984
    return ret;
bellard's avatar
bellard committed
985 986 987 988
}

void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
{
bellard's avatar
bellard committed
989
    if (!bs->drv) {
bellard's avatar
bellard committed
990 991 992 993 994 995
        buf[0] = '\0';
    } else {
        pstrcpy(buf, buf_size, bs->drv->format_name);
    }
}

996
void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
bellard's avatar
bellard committed
997 998 999 1000 1001 1002 1003 1004 1005
                         void *opaque)
{
    BlockDriver *drv;

    for (drv = first_drv; drv != NULL; drv = drv->next) {
        it(opaque, drv->format_name);
    }
}

bellard's avatar
bellard committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
BlockDriverState *bdrv_find(const char *name)
{
    BlockDriverState *bs;

    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
        if (!strcmp(name, bs->device_name))
            return bs;
    }
    return NULL;
}

1017
void bdrv_iterate(void (*it)(void *opaque, BlockDriverState *bs), void *opaque)
bellard's avatar
bellard committed
1018 1019 1020 1021
{
    BlockDriverState *bs;

    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
1022
        it(opaque, bs);
bellard's avatar
bellard committed
1023 1024 1025
    }
}

bellard's avatar
bellard committed
1026 1027 1028 1029 1030
const char *bdrv_get_device_name(BlockDriverState *bs)
{
    return bs->device_name;
}

pbrook's avatar
pbrook committed
1031 1032
void bdrv_flush(BlockDriverState *bs)
{
1033 1034
    if (!bs->drv)
        return;
pbrook's avatar
pbrook committed
1035 1036 1037 1038 1039 1040
    if (bs->drv->bdrv_flush)
        bs->drv->bdrv_flush(bs);
    if (bs->backing_hd)
        bdrv_flush(bs->backing_hd);
}

aliguori's avatar
aliguori committed
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
void bdrv_flush_all(void)
{
    BlockDriverState *bs;

    for (bs = bdrv_first; bs != NULL; bs = bs->next)
        if (bs->drv && !bdrv_is_read_only(bs) && 
            (!bdrv_is_removable(bs) || bdrv_is_inserted(bs)))
            bdrv_flush(bs);
}

1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
/*
 * Returns true iff the specified sector is present in the disk image. Drivers
 * not implementing the functionality are assumed to not support backing files,
 * hence all their sectors are reported as allocated.
 *
 * 'pnum' is set to the number of sectors (including and immediately following
 * the specified sector) that are known to be in the same
 * allocated/unallocated state.
 *
 * 'nb_sectors' is the max value 'pnum' should be set to.
 */
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
	int *pnum)
{
    int64_t n;
    if (!bs->drv->bdrv_is_allocated) {
        if (sector_num >= bs->total_sectors) {
            *pnum = 0;
            return 0;
        }
        n = bs->total_sectors - sector_num;
        *pnum = (n < nb_sectors) ? (n) : (nb_sectors);
        return 1;
    }
    return bs->drv->bdrv_is_allocated(bs, sector_num, nb_sectors, pnum);
}

aliguori's avatar
aliguori committed
1078
void bdrv_info(Monitor *mon)
bellard's avatar
bellard committed
1079 1080 1081 1082
{
    BlockDriverState *bs;

    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
aliguori's avatar
aliguori committed
1083 1084
        monitor_printf(mon, "%s:", bs->device_name);
        monitor_printf(mon, " type=");
bellard's avatar
bellard committed
1085 1086
        switch(bs->type) {
        case BDRV_TYPE_HD:
aliguori's avatar
aliguori committed
1087
            monitor_printf(mon, "hd");
bellard's avatar
bellard committed
1088 1089
            break;
        case BDRV_TYPE_CDROM:
aliguori's avatar
aliguori committed
1090
            monitor_printf(mon, "cdrom");
bellard's avatar
bellard committed
1091 1092
            break;
        case BDRV_TYPE_FLOPPY:
aliguori's avatar
aliguori committed
1093
            monitor_printf(mon, "floppy");
bellard's avatar
bellard committed
1094 1095
            break;
        }
aliguori's avatar
aliguori committed
1096
        monitor_printf(mon, " removable=%d", bs->removable);
bellard's avatar
bellard committed
1097
        if (bs->removable) {
aliguori's avatar
aliguori committed
1098
            monitor_printf(mon, " locked=%d", bs->locked);
bellard's avatar
bellard committed
1099
        }
bellard's avatar
bellard committed
1100
        if (bs->drv) {
aliguori's avatar
aliguori committed
1101 1102
            monitor_printf(mon, " file=");
            monitor_print_filename(mon, bs->filename);
1103
            if (bs->backing_file[0] != '\0') {
aliguori's avatar
aliguori committed
1104 1105 1106 1107 1108 1109
                monitor_printf(mon, " backing_file=");
                monitor_print_filename(mon, bs->backing_file);
            }
            monitor_printf(mon, " ro=%d", bs->read_only);
            monitor_printf(mon, " drv=%s", bs->drv->format_name);
            monitor_printf(mon, " encrypted=%d", bdrv_is_encrypted(bs));
bellard's avatar
bellard committed
1110
        } else {
aliguori's avatar
aliguori committed
1111
            monitor_printf(mon, " [not inserted]");
bellard's avatar
bellard committed
1112
        }
aliguori's avatar
aliguori committed
1113
        monitor_printf(mon, "\n");
bellard's avatar
bellard committed
1114 1115
    }
}
1116 1117

/* The "info blockstats" command. */
aliguori's avatar
aliguori committed
1118
void bdrv_info_stats(Monitor *mon)
1119 1120 1121 1122
{
    BlockDriverState *bs;

    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
aliguori's avatar
aliguori committed
1123 1124 1125 1126 1127
        monitor_printf(mon, "%s:"
                       " rd_bytes=%" PRIu64
                       " wr_bytes=%" PRIu64
                       " rd_operations=%" PRIu64
                       " wr_operations=%" PRIu64
aliguori's avatar
aliguori committed
1128
                       "\n",
aliguori's avatar
aliguori committed
1129 1130 1131
                       bs->device_name,
                       bs->rd_bytes, bs->wr_bytes,
                       bs->rd_ops, bs->wr_ops);
1132 1133
    }
}
bellard's avatar
bellard committed
1134

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
const char *bdrv_get_encrypted_filename(BlockDriverState *bs)
{
    if (bs->backing_hd && bs->backing_hd->encrypted)
        return bs->backing_file;
    else if (bs->encrypted)
        return bs->filename;
    else
        return NULL;
}

1145
void bdrv_get_backing_filename(BlockDriverState *bs,
bellard's avatar
bellard committed
1146 1147 1148 1149 1150 1151 1152 1153 1154
                               char *filename, int filename_size)
{
    if (!bs->backing_hd) {
        pstrcpy(filename, filename_size, "");
    } else {
        pstrcpy(filename, filename_size, bs->backing_file);
    }
}

1155
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
bellard's avatar
bellard committed
1156 1157 1158 1159
                          const uint8_t *buf, int nb_sectors)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
1160
        return -ENOMEDIUM;
bellard's avatar
bellard committed
1161 1162
    if (!drv->bdrv_write_compressed)
        return -ENOTSUP;
Kevin Wolf's avatar
Kevin Wolf committed
1163 1164
    if (bdrv_check_request(bs, sector_num, nb_sectors))
        return -EIO;
bellard's avatar
bellard committed
1165 1166
    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
}
1167

bellard's avatar
bellard committed
1168 1169 1170 1171
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
1172
        return -ENOMEDIUM;
bellard's avatar
bellard committed
1173 1174 1175 1176 1177 1178
    if (!drv->bdrv_get_info)
        return -ENOTSUP;
    memset(bdi, 0, sizeof(*bdi));
    return drv->bdrv_get_info(bs, bdi);
}

1179 1180
int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
                      int64_t pos, int size)
1181 1182 1183 1184
{
    BlockDriver *drv = bs->drv;
    if (!drv)
        return -ENOMEDIUM;
1185
    if (!drv->bdrv_save_vmstate)
1186
        return -ENOTSUP;
1187
    return drv->bdrv_save_vmstate(bs, buf, pos, size);
1188 1189
}

1190 1191
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
                      int64_t pos, int size)
1192 1193 1194 1195
{
    BlockDriver *drv = bs->drv;
    if (!drv)
        return -ENOMEDIUM;
1196
    if (!drv->bdrv_load_vmstate)
1197
        return -ENOTSUP;
1198
    return drv->bdrv_load_vmstate(bs, buf, pos, size);
1199 1200
}

bellard's avatar
bellard committed
1201 1202 1203
/**************************************************************/
/* handling of snapshots */

1204
int bdrv_snapshot_create(BlockDriverState *bs,
bellard's avatar
bellard committed
1205 1206 1207 1208
                         QEMUSnapshotInfo *sn_info)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
1209
        return -ENOMEDIUM;
bellard's avatar
bellard committed
1210 1211 1212 1213 1214
    if (!drv->bdrv_snapshot_create)
        return -ENOTSUP;
    return drv->bdrv_snapshot_create(bs, sn_info);
}

1215
int bdrv_snapshot_goto(BlockDriverState *bs,
bellard's avatar
bellard committed
1216 1217 1218 1219
                       const char *snapshot_id)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
1220
        return -ENOMEDIUM;
bellard's avatar
bellard committed
1221 1222 1223 1224 1225 1226 1227 1228 1229
    if (!drv->bdrv_snapshot_goto)
        return -ENOTSUP;
    return drv->bdrv_snapshot_goto(bs, snapshot_id);
}

int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
1230
        return -ENOMEDIUM;
bellard's avatar
bellard committed
1231 1232 1233 1234 1235
    if (!drv->bdrv_snapshot_delete)
        return -ENOTSUP;
    return drv->bdrv_snapshot_delete(bs, snapshot_id);
}

1236
int bdrv_snapshot_list(BlockDriverState *bs,
bellard's avatar
bellard committed
1237 1238 1239 1240
                       QEMUSnapshotInfo **psn_info)
{
    BlockDriver *drv = bs->drv;
    if (!drv)
bellard's avatar
bellard committed
1241
        return -ENOMEDIUM;
bellard's avatar
bellard committed
1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
    if (!drv->bdrv_snapshot_list)
        return -ENOTSUP;
    return drv->bdrv_snapshot_list(bs, psn_info);
}

#define NB_SUFFIXES 4

char *get_human_readable_size(char *buf, int buf_size, int64_t size)
{
    static const char suffixes[NB_SUFFIXES] = "KMGT";
    int64_t base;
    int i;

    if (size <= 999) {
        snprintf(buf, buf_size, "%" PRId64, size);
    } else {
        base = 1024;
        for(i = 0; i < NB_SUFFIXES; i++) {
            if (size < (10 * base)) {
1261
                snprintf(buf, buf_size, "%0.1f%c",
bellard's avatar
bellard committed
1262 1263 1264 1265
                         (double)size / base,
                         suffixes[i]);
                break;
            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
1266
                snprintf(buf, buf_size, "%" PRId64 "%c",
bellard's avatar
bellard committed
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279
                         ((size + (base >> 1)) / base),
                         suffixes[i]);
                break;
            }
            base = base * 1024;
        }
    }
    return buf;
}

char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
{
    char buf1[128], date_buf[128], clock_buf[128];
1280 1281 1282
#ifdef _WIN32
    struct tm *ptm;
#else
bellard's avatar
bellard committed
1283
    struct tm tm;
1284
#endif
bellard's avatar
bellard committed
1285 1286 1287 1288
    time_t ti;
    int64_t secs;

    if (!sn) {
1289 1290
        snprintf(buf, buf_size,
                 "%-10s%-20s%7s%20s%15s",
bellard's avatar
bellard committed
1291 1292 1293
                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
    } else {
        ti = sn->date_sec;
1294 1295 1296 1297 1298
#ifdef _WIN32
        ptm = localtime(&ti);
        strftime(date_buf, sizeof(date_buf),
                 "%Y-%m-%d %H:%M:%S", ptm);
#else
bellard's avatar
bellard committed
1299 1300 1301
        localtime_r(&ti, &tm);
        strftime(date_buf, sizeof(date_buf),
                 "%Y-%m-%d %H:%M:%S", &tm);
1302
#endif
bellard's avatar
bellard committed
1303 1304 1305 1306 1307
        secs = sn->vm_clock_nsec / 1000000000;
        snprintf(clock_buf, sizeof(clock_buf),
                 "%02d:%02d:%02d.%03d",
                 (int)(secs / 3600),
                 (int)((secs / 60) % 60),
1308
                 (int)(secs % 60),
bellard's avatar
bellard committed
1309 1310
                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
        snprintf(buf, buf_size,
1311
                 "%-10s%-20s%7s%20s%15s",
bellard's avatar
bellard committed
1312 1313 1314 1315 1316 1317 1318 1319
                 sn->id_str, sn->name,
                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
                 date_buf,
                 clock_buf);
    }
    return buf;
}

bellard's avatar
bellard committed
1320

bellard's avatar
bellard committed
1321
/**************************************************************/
bellard's avatar
bellard committed
1322
/* async I/Os */
bellard's avatar
bellard committed
1323

1324
BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
1325
                                 QEMUIOVector *qiov, int nb_sectors,
1326
                                 BlockDriverCompletionFunc *cb, void *opaque)
bellard's avatar
bellard committed
1327 1328
{
    BlockDriver *drv = bs->drv;
1329
    BlockDriverAIOCB *ret;
bellard's avatar
bellard committed
1330