18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU System Emulator block driver
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2003 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "config-host.h"
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h"
266af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h"
27e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "block/block_int.h"
281befd3440439e8181a31140674e847f2d3e1481eDavid 'Digit' Turner#include "qemu/iov.h"
29e90d665cd63a0bc5c3306e1ee3e98ad362546b16David 'Digit' Turner#include "qemu/module.h"
302a7dde0b2f96b05048320a0840cde7ab3d4be9feDavid 'Digit' Turner//#include "qapi/qmp/types.h"
31e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "qapi/qmp/qjson.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
332c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h>
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/stat.h>
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/ioctl.h>
37cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#include <sys/queue.h>
385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef __DragonFly__
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/disk.h>
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <windows.h>
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_readv_em(BlockDriverState *bs,
485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverCompletionFunc *cb, void *opaque);
53cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
54cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque);
55cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
56cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        BlockDriverCompletionFunc *cb, void *opaque);
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint8_t *buf, int nb_sectors);
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         const uint8_t *buf, int nb_sectors);
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QTAILQ_HEAD(, BlockDriverState) bdrv_states =
63cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_HEAD_INITIALIZER(bdrv_states);
64cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
65cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic QLIST_HEAD(, BlockDriver) bdrv_drivers =
66cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_HEAD_INITIALIZER(bdrv_drivers);
675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
68cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/* The device to use for VM snapshots */
69cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic BlockDriverState *bs_snapshots;
70cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
71cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/* If non-zero, use only whitelisted block drivers */
72cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int use_bdrv_whitelist;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint _path_is_absolute(const char *path)
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* specific case for names like: "\\.\d:" */
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*path == '/' || *path == '\\')
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr(path, ':');
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p)
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p++;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = path;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/' || *p == '\\');
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (*p == '/');
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* if filename is absolute, just copy it to dest. Otherwise, build a
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   path to it by considering it is relative to base_path. URL are
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   supported. */
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid path_combine(char *dest, int dest_size,
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *base_path,
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  const char *filename)
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *p, *p1;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int len;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dest_size <= 0)
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (_path_is_absolute(filename)) {
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcpy(dest, dest_size, filename);
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = strchr(base_path, ':');
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p)
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p++;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = base_path;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p1 = strrchr(base_path, '/');
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const char *p2;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p2 = strrchr(base_path, '\\');
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!p1 || p2 > p1)
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                p1 = p2;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1)
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1++;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p1 = base_path;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (p1 > p)
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = p1;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = p - base_path;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (len > dest_size - 1)
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = dest_size - 1;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        memcpy(dest, base_path, len);
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dest[len] = '\0';
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pstrcat(dest, dest_size, filename);
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid bdrv_register(BlockDriver *bdrv)
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv->bdrv_aio_readv) {
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add AIO emulation layer */
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_readv = bdrv_aio_readv_em;
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv->bdrv_aio_writev = bdrv_aio_writev_em;
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else if (!bdrv->bdrv_read) {
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add synchronous IO emulation layer */
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_read = bdrv_read_em;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv->bdrv_write = bdrv_write_em;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
149cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
150cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bdrv->bdrv_aio_flush)
151cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv->bdrv_aio_flush = bdrv_aio_flush_em;
152cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
153cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_INSERT_HEAD(&bdrv_drivers, bdrv, list);
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* create a new block device (by default it is empty) */
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriverState *bdrv_new(const char *device_name)
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
159cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
161aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    bs = g_malloc0(sizeof(BlockDriverState));
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (device_name[0] != '\0') {
164cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_INSERT_TAIL(&bdrv_states, bs, list);
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return bs;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBlockDriver *bdrv_find_format(const char *format_name)
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1;
172cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
173cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(drv1->format_name, format_name)) {
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return drv1;
175cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
180cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int bdrv_is_whitelisted(BlockDriver *drv)
181cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
182cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    static const char *whitelist[] = {
183cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        CONFIG_BDRV_WHITELIST
184cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    };
185cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char **p;
186cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
187cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!whitelist[0])
188cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 1;               /* no whitelist, anything goes */
189cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
190cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (p = whitelist; *p; p++) {
191cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!strcmp(drv->format_name, *p)) {
192cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return 1;
193cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
194cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
195cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
196cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
197cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
198cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriver *bdrv_find_whitelisted_format(const char *format_name)
199cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
200cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bdrv_find_format(format_name);
201cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return drv && bdrv_is_whitelisted(drv) ? drv : NULL;
202cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
203cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint bdrv_create(BlockDriver *drv, const char* filename,
2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    QEMUOptionParameter *options)
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv->bdrv_create)
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOTSUP;
2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv->bdrv_create(filename, options);
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
213cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_create_file(const char* filename, QEMUOptionParameter *options)
214cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
215cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv;
216cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
217cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = bdrv_find_protocol(filename);
218cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv == NULL) {
219cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv = bdrv_find_format("file");
220cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
221cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
222cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bdrv_create(drv, filename, options);
223cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
224cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char temp_dir[MAX_PATH];
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempPath(MAX_PATH, temp_dir);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    GetTempFileName(temp_dir, "qem", 0, filename);
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid get_tmp_filename(char *filename, int size)
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int fd;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *tmpdir;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: race condition possible */
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmpdir = getenv("TMPDIR");
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!tmpdir)
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmpdir = "/tmp";
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    snprintf(filename, size, "%s/vl.XXXXXX", tmpdir);
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = mkstemp(filename);
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    close(fd);
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int is_windows_drive_prefix(const char *filename)
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            filename[1] == ':');
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint is_windows_drive(const char *filename)
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (is_windows_drive_prefix(filename) &&
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename[2] == '\0')
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (strstart(filename, "\\\\.\\", NULL) ||
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        strstart(filename, "//./", NULL))
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Detect host devices. By convention, /dev/cdrom[N] is always
2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * recognized as a host CDROM.
2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic BlockDriver *find_hdev_driver(const char *filename)
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int score_max = 0, score;
2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    BlockDriver *drv = NULL, *d;
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
277cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(d, &bdrv_drivers, list) {
2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (d->bdrv_probe_device) {
2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            score = d->bdrv_probe_device(filename);
2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (score > score_max) {
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                score_max = score;
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv = d;
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return drv;
2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
290cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerBlockDriver *bdrv_find_protocol(const char *filename)
291cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
292cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv1;
293cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    char protocol[128];
294cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int len;
295cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    const char *p;
296cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
297cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* TODO Drivers without bdrv_file_open must be specified explicitly */
298cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
299cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
300cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * XXX(hch): we really should not let host device detection
301cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * override an explicit protocol specification, but moving this
302cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * later breaks access to device names with colons in them.
303cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Thanks to the brain-dead persistent naming schemes on udev-
304cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * based Linux systems those actually are quite common.
305cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
306cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv1 = find_hdev_driver(filename);
307cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv1) {
308cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return drv1;
309cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
310cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
311cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifdef _WIN32
312cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     if (is_windows_drive(filename) ||
313cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         is_windows_drive_prefix(filename))
314cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner         return bdrv_find_format("file");
315cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
316cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
317cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    p = strchr(filename, ':');
318cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!p) {
319cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return bdrv_find_format("file");
320cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
321cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    len = p - filename;
322cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (len > sizeof(protocol) - 1)
323cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        len = sizeof(protocol) - 1;
324cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    memcpy(protocol, filename, len);
325cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    protocol[len] = '\0';
326cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
327cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (drv1->protocol_name &&
328cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            !strcmp(drv1->protocol_name, protocol)) {
329cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return drv1;
330cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
331cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
332cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return NULL;
333cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
334cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
335cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int find_image_format(const char *filename, BlockDriver **pdrv)
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret, score, score_max;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv1, *drv;
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint8_t buf[2048];
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
342cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_file_open(&bs, filename, 0);
343cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
344cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = NULL;
345cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
346cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
347cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
348cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
349cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->sg || !bdrv_is_inserted(bs)) {
350cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs);
351cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        drv = bdrv_find_format("raw");
352cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (!drv) {
353cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = -ENOENT;
354cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
355cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = drv;
356cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
357cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_delete(bs);
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
362cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        *pdrv = NULL;
363cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return ret;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    score_max = 0;
367cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = NULL;
368cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QLIST_FOREACH(drv1, &bdrv_drivers, list) {
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (drv1->bdrv_probe) {
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            score = drv1->bdrv_probe(buf, ret, filename);
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (score > score_max) {
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                score_max = score;
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                drv = drv1;
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
377cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
378cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = -ENOENT;
379cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
380cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    *pdrv = drv;
381cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
384cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/**
385cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Set the current 'total_sectors' value
386cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
387cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
388cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
389cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv = bs->drv;
390cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
391cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */
392cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->sg)
393cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return 0;
394cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
395cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* query actual device if possible, otherwise just trust the hint */
396cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_getlength) {
397cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int64_t length = drv->bdrv_getlength(bs);
398cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (length < 0) {
399cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return length;
400cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
401cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        hint = length >> BDRV_SECTOR_BITS;
402cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
403cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
404cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->total_sectors = hint;
405cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
406cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
407cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
408cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
409cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Common part for opening disk images and files
410cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
411cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerstatic int bdrv_open_common(BlockDriverState *bs, const char *filename,
412cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int flags, BlockDriver *drv)
413cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
414cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret, open_flags;
415cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
416cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(drv != NULL);
417cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
418cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->file = NULL;
419cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->total_sectors = 0;
420cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->encrypted = 0;
421cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->valid_key = 0;
422cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->open_flags = flags;
423cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* buffer_alignment defaulted to 512, drivers can change this value */
424cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->buffer_alignment = 512;
425cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
426cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    pstrcpy(bs->filename, sizeof(bs->filename), filename);
427cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
428cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv)) {
429cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
430cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
431cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
432cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->drv = drv;
433aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    bs->opaque = g_malloc0(drv->instance_size);
434cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
435cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
436cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
437cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * write cache to the guest.  We do need the fdatasync to flush
438cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * out transactions for block allocations, and we maybe have a
439cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * volatile write cache in our backing device to deal with.
440cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
441cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
442cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->enable_write_cache = 1;
443cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
444cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
445cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Clear flags that are internal to the block layer before opening the
446cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * image.
447cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
448cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
449cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
450cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
451cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Snapshots should be writeable.
452cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
453cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
454cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        open_flags |= BDRV_O_RDWR;
455cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
456cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
457cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Open the image, either directly or using a protocol */
458cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_file_open) {
459cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = drv->bdrv_file_open(bs, filename, open_flags);
460cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    } else {
461cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_file_open(&bs->file, filename, open_flags);
462cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (ret >= 0) {
463cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = drv->bdrv_open(bs, open_flags);
464cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
465cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
466cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
467cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
468cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto free_and_fail;
469cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
470cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
471cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->keep_read_only = bs->read_only = !(open_flags & BDRV_O_RDWR);
472cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
473cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = refresh_total_sectors(bs, bs->total_sectors);
474cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ret < 0) {
475cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto free_and_fail;
476cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
477cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
478cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#ifndef _WIN32
479cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
480cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        unlink(filename);
481cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
482cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#endif
483cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
484cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
485cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerfree_and_fail:
486cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file) {
487cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->file);
488cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->file = NULL;
489cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
490aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(bs->opaque);
491cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->opaque = NULL;
492cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->drv = NULL;
493cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
494cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
495cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
496cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
497cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Opens a file using a protocol (file, host_device, nbd, ...)
498cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriverState *bs;
502cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriver *drv;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
505cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    drv = bdrv_find_protocol(filename);
506cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
507cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOENT;
508cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
509cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bs = bdrv_new("");
511cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_open_common(bs, filename, flags, drv);
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs);
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return ret;
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    bs->growable = 1;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pbs = bs;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
521cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
522cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Opens a disk image (raw, qcow2, vmdk, ...)
523cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner */
524cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_open(BlockDriverState *bs, const char *filename, int flags,
525cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner              BlockDriver *drv)
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
527cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret;
528cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int probed = 0;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & BDRV_O_SNAPSHOT) {
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        BlockDriverState *bs1;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int64_t total_size;
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int is_protocol = 0;
5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *bdrv_qcow2;
5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        QEMUOptionParameter *options;
536cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char tmp_filename[PATH_MAX];
537cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char backing_filename[PATH_MAX];
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if snapshot, we create a temporary backing file and open it
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           instead of opening 'filename' directly */
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if there is a backing file, use it */
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs1 = bdrv_new("");
544cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs1, filename, 0, drv);
5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs1);
5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
549cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs1->drv && bs1->drv->protocol_name)
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            is_protocol = 1;
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bdrv_delete(bs1);
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Real path is meaningless for protocols */
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (is_protocol)
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            snprintf(backing_filename, sizeof(backing_filename),
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     "%s", filename);
562cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        else if (!realpath(filename, backing_filename))
563cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return -errno;
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bdrv_qcow2 = bdrv_find_format("qcow2");
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
568cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (drv) {
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                drv->format_name);
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ret = bdrv_create(bdrv_qcow2, tmp_filename, options);
576cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        free_option_parameters(options);
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        filename = tmp_filename;
5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        drv = bdrv_qcow2;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->is_temporary = 1;
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
586cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Find the right image format driver */
587cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!drv) {
588cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = find_image_format(filename, &drv);
589cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        probed = 1;
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
591cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!drv) {
5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto unlink_and_fail;
5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
595cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
596cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* Open the image */
597cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ret = bdrv_open_common(bs, filename, flags, drv);
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
599cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        goto unlink_and_fail;
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
601cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
602cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->probed = probed;
603cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
604cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* If there is a backing file, use it */
605cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if ((flags & BDRV_O_NO_BACKING) == 0 && bs->backing_file[0] != '\0') {
606cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        char backing_filename[PATH_MAX];
607cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        int back_flags;
6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        BlockDriver *back_drv = NULL;
609cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->backing_hd = bdrv_new("");
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        path_combine(backing_filename, sizeof(backing_filename),
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     filename, bs->backing_file);
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->backing_format[0] != '\0')
6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            back_drv = bdrv_find_format(bs->backing_format);
615cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
616cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* backing files always opened read-only */
617cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        back_flags =
618cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            flags & ~(BDRV_O_RDWR | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
619cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
620cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs->backing_hd, backing_filename, back_flags, back_drv);
6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (ret < 0) {
6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bdrv_close(bs);
6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return ret;
6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
625cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->is_temporary) {
626cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd->keep_read_only = !(flags & BDRV_O_RDWR);
627cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        } else {
628cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* base image inherits from "parent" */
629cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd->keep_read_only = bs->keep_read_only;
630cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!bdrv_key_required(bs)) {
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* call the change callback */
6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        bs->media_changed = 1;
6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (bs->change_cb)
6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            bs->change_cb(bs->change_opaque);
6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
639cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
641cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
642cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerunlink_and_fail:
643cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->is_temporary) {
644cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        unlink(filename);
645cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
646cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_close(BlockDriverState *bs)
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (bs->drv) {
652cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs == bs_snapshots) {
653cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_snapshots = NULL;
654cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
655cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->backing_hd) {
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bdrv_delete(bs->backing_hd);
657cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd = NULL;
658cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv->bdrv_close(bs);
660aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner        g_free(bs->opaque);
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->is_temporary) {
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unlink(bs->filename);
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->opaque = NULL;
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->drv = NULL;
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
669cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (bs->file != NULL) {
670cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_close(bs->file);
671cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
672cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* call the change callback */
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        bs->media_changed = 1;
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (bs->change_cb)
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bs->change_cb(bs->change_opaque);
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
680cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_close_all(void)
681cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
682cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
683cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
684cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
685cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_close(bs);
686cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
687cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
688cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid bdrv_delete(BlockDriverState *bs)
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
691cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(!bs->peer);
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
693cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /* remove from list, if necessary */
694cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->device_name[0] != '\0') {
695cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        QTAILQ_REMOVE(&bdrv_states, bs, list);
696cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bdrv_close(bs);
699cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->file != NULL) {
700cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->file);
701cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
702cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
703cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs != bs_snapshots);
704aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(bs);
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
707cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_attach(BlockDriverState *bs, DeviceState *qdev)
708cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
709cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->peer) {
710cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EBUSY;
711cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
712cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->peer = qdev;
713cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return 0;
714cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
715cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
716cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_detach(BlockDriverState *bs, DeviceState *qdev)
717cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
718cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    assert(bs->peer == qdev);
719cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    bs->peer = NULL;
720cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
721cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
722cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' TurnerDeviceState *bdrv_get_attached(BlockDriverState *bs)
723cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
724cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->peer;
725cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
726cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Run consistency checks on an image
7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *
730cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Returns 0 if the check could be completed (it doesn't mean that the image is
731cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * free of errors) or -errno when an internal error occured. The results of the
732cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * check are stored in res.
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
734cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerint bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (bs->drv->bdrv_check == NULL) {
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -ENOTSUP;
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
740cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    memset(res, 0, sizeof(*res));
741cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return bs->drv->bdrv_check(bs, res);
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
744cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner#define COMMIT_BUF_SECTORS 2048
745cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* commit COW file into the raw image */
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint bdrv_commit(BlockDriverState *bs)
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    BlockDriver *drv = bs->drv;
750cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int64_t sector, total_sectors;
751cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int n, ro, open_flags;
752cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    int ret = 0, rw_ret = 0;
753cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    uint8_t *buf;
754cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    char filename[1024];
755cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs_rw, *bs_ro;
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!drv)
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -ENOMEDIUM;
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
760cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (!bs->backing_hd) {
761cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -ENOTSUP;
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
764cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->backing_hd->keep_read_only) {
765cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        return -EACCES;
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
768cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    ro = bs->backing_hd->read_only;
769cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    strncpy(filename, bs->backing_hd->filename, sizeof(filename));
770cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    open_flags =  bs->backing_hd->open_flags;
771cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
772cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ro) {
773cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* re-open as RW */
774cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->backing_hd);
775cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = NULL;
776cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_rw = bdrv_new("");
777cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        rw_ret = bdrv_open(bs_rw, filename, open_flags | BDRV_O_RDWR, drv);
778cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (rw_ret < 0) {
779cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs_rw);
780cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* try to re-open read-only */
781cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs_ro = bdrv_new("");
782cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
783cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (ret < 0) {
784cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bdrv_delete(bs_ro);
785cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                /* drive not functional anymore */
786cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                bs->drv = NULL;
787cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                return ret;
788cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
789cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->backing_hd = bs_ro;
790cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return rw_ret;
791cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
792cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = bs_rw;
793cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
795cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
796aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    buf = g_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
797cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
798cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    for (sector = 0; sector < total_sectors; sector += n) {
799cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (drv->bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
800cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
801cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (bdrv_read(bs, sector, buf, n) != 0) {
802cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                ret = -EIO;
803cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto ro_cleanup;
804cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
805cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
806cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            if (bdrv_write(bs->backing_hd, sector, buf, n) != 0) {
807cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                ret = -EIO;
808cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner                goto ro_cleanup;
809cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            }
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
813cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (drv->bdrv_make_empty) {
814cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = drv->bdrv_make_empty(bs);
815cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs);
816cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    /*
819cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * Make sure all data we wrote to the backing device is actually
820cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     * stable on disk.
821cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner     */
822cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (bs->backing_hd)
823cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_flush(bs->backing_hd);
824cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
825cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnerro_cleanup:
826aa8236dc1b1ea300ab18716db5b8fab42aca3ca7David 'Digit' Turner    g_free(buf);
827cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
828cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    if (ro) {
829cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        /* re-open as RO */
830cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_delete(bs->backing_hd);
831cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = NULL;
832cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs_ro = bdrv_new("");
833cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        ret = bdrv_open(bs_ro, filename, open_flags & ~BDRV_O_RDWR, drv);
834cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        if (ret < 0) {
835cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bdrv_delete(bs_ro);
836cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            /* drive not functional anymore */
837cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            bs->drv = NULL;
838cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner            return ret;
839cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        }
840cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd = bs_ro;
841cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bs->backing_hd->keep_read_only = 0;
842cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
843cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
844cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    return ret;
845cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
846cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
847cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turnervoid bdrv_commit_all(void)
848cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner{
849cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    BlockDriverState *bs;
850cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
851cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    QTAILQ_FOREACH(bs, &bdrv_states, list) {
852cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner        bdrv_commit(bs);
853cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner    }
854cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner}
855cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner
856cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner/*
857cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * Return values:
858cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * 0        - success
859cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -EINVAL  - backing format specified, but no file
860cb42a1b1461e02efb034582ac5d8f71534723b92David 'Digit' Turner * -ENOSPC  - can't update the backing file because no space is left in the
861