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