Commit 223d4670a0cf539a0e8cc6a23aad28a8340dded8

Authored by ths
1 parent 50a9569b

Split block-raw.c into block-raw-posix.c and block-raw-win32.c, by

Anthony Liguori.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3814 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
@@ -119,9 +119,16 @@ libqemu_common.a: $(OBJS) @@ -119,9 +119,16 @@ libqemu_common.a: $(OBJS)
119 rm -f $@ 119 rm -f $@
120 $(AR) rcs $@ $(OBJS) 120 $(AR) rcs $@ $(OBJS)
121 121
  122 +QEMU_IMG_BLOCK_OBJS = $(BLOCK_OBJS)
  123 +ifdef CONFIG_WIN32
  124 +QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-win32.o
  125 +else
  126 +QEMU_IMG_BLOCK_OBJS += qemu-img-block-raw-posix.o
  127 +endif
  128 +
122 ###################################################################### 129 ######################################################################
123 130
124 -qemu-img$(EXESUF): qemu-img.o qemu-img-block.o qemu-img-block-raw.o $(BLOCK_OBJS) 131 +qemu-img$(EXESUF): qemu-img.o qemu-img-block.o $(QEMU_IMG_BLOCK_OBJS)
125 $(CC) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS) 132 $(CC) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
126 133
127 qemu-img-%.o: %.c 134 qemu-img-%.o: %.c
Makefile.target
@@ -398,7 +398,11 @@ endif @@ -398,7 +398,11 @@ endif
398 # must use static linking to avoid leaving stuff in virtual address space 398 # must use static linking to avoid leaving stuff in virtual address space
399 VL_OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o 399 VL_OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o
400 # XXX: suppress QEMU_TOOL tests 400 # XXX: suppress QEMU_TOOL tests
401 -VL_OBJS+=block-raw.o 401 +ifdef CONFIG_WIN32
  402 +VL_OBJS+=block-raw-win32.o
  403 +else
  404 +VL_OBJS+=block-raw-posix.o
  405 +endif
402 406
403 ifdef CONFIG_ALSA 407 ifdef CONFIG_ALSA
404 LIBS += -lasound 408 LIBS += -lasound
block-raw.c renamed to block-raw-posix.c
1 /* 1 /*
2 - * Block driver for RAW files 2 + * Block driver for RAW files (posix)
3 * 3 *
4 * Copyright (c) 2006 Fabrice Bellard 4 * Copyright (c) 2006 Fabrice Bellard
5 * 5 *
@@ -28,7 +28,6 @@ @@ -28,7 +28,6 @@
28 #endif 28 #endif
29 #include "block_int.h" 29 #include "block_int.h"
30 #include <assert.h> 30 #include <assert.h>
31 -#ifndef _WIN32  
32 #include <aio.h> 31 #include <aio.h>
33 32
34 #ifdef CONFIG_COCOA 33 #ifdef CONFIG_COCOA
@@ -900,522 +899,3 @@ BlockDriver bdrv_host_device = { @@ -900,522 +899,3 @@ BlockDriver bdrv_host_device = {
900 .bdrv_eject = raw_eject, 899 .bdrv_eject = raw_eject,
901 .bdrv_set_locked = raw_set_locked, 900 .bdrv_set_locked = raw_set_locked,
902 }; 901 };
903 -  
904 -#else /* _WIN32 */  
905 -  
906 -/* XXX: use another file ? */  
907 -#include <winioctl.h>  
908 -  
909 -#define FTYPE_FILE 0  
910 -#define FTYPE_CD 1  
911 -#define FTYPE_HARDDISK 2  
912 -  
913 -typedef struct BDRVRawState {  
914 - HANDLE hfile;  
915 - int type;  
916 - char drive_path[16]; /* format: "d:\" */  
917 -} BDRVRawState;  
918 -  
919 -typedef struct RawAIOCB {  
920 - BlockDriverAIOCB common;  
921 - HANDLE hEvent;  
922 - OVERLAPPED ov;  
923 - int count;  
924 -} RawAIOCB;  
925 -  
926 -int qemu_ftruncate64(int fd, int64_t length)  
927 -{  
928 - LARGE_INTEGER li;  
929 - LONG high;  
930 - HANDLE h;  
931 - BOOL res;  
932 -  
933 - if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)  
934 - return -1;  
935 -  
936 - h = (HANDLE)_get_osfhandle(fd);  
937 -  
938 - /* get current position, ftruncate do not change position */  
939 - li.HighPart = 0;  
940 - li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);  
941 - if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)  
942 - return -1;  
943 -  
944 - high = length >> 32;  
945 - if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))  
946 - return -1;  
947 - res = SetEndOfFile(h);  
948 -  
949 - /* back to old position */  
950 - SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);  
951 - return res ? 0 : -1;  
952 -}  
953 -  
954 -static int set_sparse(int fd)  
955 -{  
956 - DWORD returned;  
957 - return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,  
958 - NULL, 0, NULL, 0, &returned, NULL);  
959 -}  
960 -  
961 -static int raw_open(BlockDriverState *bs, const char *filename, int flags)  
962 -{  
963 - BDRVRawState *s = bs->opaque;  
964 - int access_flags, create_flags;  
965 - DWORD overlapped;  
966 -  
967 - s->type = FTYPE_FILE;  
968 -  
969 - if ((flags & BDRV_O_ACCESS) == O_RDWR) {  
970 - access_flags = GENERIC_READ | GENERIC_WRITE;  
971 - } else {  
972 - access_flags = GENERIC_READ;  
973 - }  
974 - if (flags & BDRV_O_CREAT) {  
975 - create_flags = CREATE_ALWAYS;  
976 - } else {  
977 - create_flags = OPEN_EXISTING;  
978 - }  
979 -#ifdef QEMU_IMG  
980 - overlapped = FILE_ATTRIBUTE_NORMAL;  
981 -#else  
982 - overlapped = FILE_FLAG_OVERLAPPED;  
983 -#endif  
984 - s->hfile = CreateFile(filename, access_flags,  
985 - FILE_SHARE_READ, NULL,  
986 - create_flags, overlapped, NULL);  
987 - if (s->hfile == INVALID_HANDLE_VALUE) {  
988 - int err = GetLastError();  
989 -  
990 - if (err == ERROR_ACCESS_DENIED)  
991 - return -EACCES;  
992 - return -1;  
993 - }  
994 - return 0;  
995 -}  
996 -  
997 -static int raw_pread(BlockDriverState *bs, int64_t offset,  
998 - uint8_t *buf, int count)  
999 -{  
1000 - BDRVRawState *s = bs->opaque;  
1001 - OVERLAPPED ov;  
1002 - DWORD ret_count;  
1003 - int ret;  
1004 -  
1005 - memset(&ov, 0, sizeof(ov));  
1006 - ov.Offset = offset;  
1007 - ov.OffsetHigh = offset >> 32;  
1008 - ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);  
1009 - if (!ret) {  
1010 - ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);  
1011 - if (!ret)  
1012 - return -EIO;  
1013 - else  
1014 - return ret_count;  
1015 - }  
1016 - return ret_count;  
1017 -}  
1018 -  
1019 -static int raw_pwrite(BlockDriverState *bs, int64_t offset,  
1020 - const uint8_t *buf, int count)  
1021 -{  
1022 - BDRVRawState *s = bs->opaque;  
1023 - OVERLAPPED ov;  
1024 - DWORD ret_count;  
1025 - int ret;  
1026 -  
1027 - memset(&ov, 0, sizeof(ov));  
1028 - ov.Offset = offset;  
1029 - ov.OffsetHigh = offset >> 32;  
1030 - ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);  
1031 - if (!ret) {  
1032 - ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);  
1033 - if (!ret)  
1034 - return -EIO;  
1035 - else  
1036 - return ret_count;  
1037 - }  
1038 - return ret_count;  
1039 -}  
1040 -  
1041 -#if 0  
1042 -#ifndef QEMU_IMG  
1043 -static void raw_aio_cb(void *opaque)  
1044 -{  
1045 - RawAIOCB *acb = opaque;  
1046 - BlockDriverState *bs = acb->common.bs;  
1047 - BDRVRawState *s = bs->opaque;  
1048 - DWORD ret_count;  
1049 - int ret;  
1050 -  
1051 - ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);  
1052 - if (!ret || ret_count != acb->count) {  
1053 - acb->common.cb(acb->common.opaque, -EIO);  
1054 - } else {  
1055 - acb->common.cb(acb->common.opaque, 0);  
1056 - }  
1057 -}  
1058 -#endif  
1059 -  
1060 -static RawAIOCB *raw_aio_setup(BlockDriverState *bs,  
1061 - int64_t sector_num, uint8_t *buf, int nb_sectors,  
1062 - BlockDriverCompletionFunc *cb, void *opaque)  
1063 -{  
1064 - RawAIOCB *acb;  
1065 - int64_t offset;  
1066 -  
1067 - acb = qemu_aio_get(bs, cb, opaque);  
1068 - if (acb->hEvent) {  
1069 - acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  
1070 - if (!acb->hEvent) {  
1071 - qemu_aio_release(acb);  
1072 - return NULL;  
1073 - }  
1074 - }  
1075 - memset(&acb->ov, 0, sizeof(acb->ov));  
1076 - offset = sector_num * 512;  
1077 - acb->ov.Offset = offset;  
1078 - acb->ov.OffsetHigh = offset >> 32;  
1079 - acb->ov.hEvent = acb->hEvent;  
1080 - acb->count = nb_sectors * 512;  
1081 -#ifndef QEMU_IMG  
1082 - qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);  
1083 -#endif  
1084 - return acb;  
1085 -}  
1086 -  
1087 -static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,  
1088 - int64_t sector_num, uint8_t *buf, int nb_sectors,  
1089 - BlockDriverCompletionFunc *cb, void *opaque)  
1090 -{  
1091 - BDRVRawState *s = bs->opaque;  
1092 - RawAIOCB *acb;  
1093 - int ret;  
1094 -  
1095 - acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);  
1096 - if (!acb)  
1097 - return NULL;  
1098 - ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);  
1099 - if (!ret) {  
1100 - qemu_aio_release(acb);  
1101 - return NULL;  
1102 - }  
1103 -#ifdef QEMU_IMG  
1104 - qemu_aio_release(acb);  
1105 -#endif  
1106 - return (BlockDriverAIOCB *)acb;  
1107 -}  
1108 -  
1109 -static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,  
1110 - int64_t sector_num, uint8_t *buf, int nb_sectors,  
1111 - BlockDriverCompletionFunc *cb, void *opaque)  
1112 -{  
1113 - BDRVRawState *s = bs->opaque;  
1114 - RawAIOCB *acb;  
1115 - int ret;  
1116 -  
1117 - acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);  
1118 - if (!acb)  
1119 - return NULL;  
1120 - ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);  
1121 - if (!ret) {  
1122 - qemu_aio_release(acb);  
1123 - return NULL;  
1124 - }  
1125 -#ifdef QEMU_IMG  
1126 - qemu_aio_release(acb);  
1127 -#endif  
1128 - return (BlockDriverAIOCB *)acb;  
1129 -}  
1130 -  
1131 -static void raw_aio_cancel(BlockDriverAIOCB *blockacb)  
1132 -{  
1133 -#ifndef QEMU_IMG  
1134 - RawAIOCB *acb = (RawAIOCB *)blockacb;  
1135 - BlockDriverState *bs = acb->common.bs;  
1136 - BDRVRawState *s = bs->opaque;  
1137 -  
1138 - qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);  
1139 - /* XXX: if more than one async I/O it is not correct */  
1140 - CancelIo(s->hfile);  
1141 - qemu_aio_release(acb);  
1142 -#endif  
1143 -}  
1144 -#endif /* #if 0 */  
1145 -  
1146 -static void raw_flush(BlockDriverState *bs)  
1147 -{  
1148 - BDRVRawState *s = bs->opaque;  
1149 - FlushFileBuffers(s->hfile);  
1150 -}  
1151 -  
1152 -static void raw_close(BlockDriverState *bs)  
1153 -{  
1154 - BDRVRawState *s = bs->opaque;  
1155 - CloseHandle(s->hfile);  
1156 -}  
1157 -  
1158 -static int raw_truncate(BlockDriverState *bs, int64_t offset)  
1159 -{  
1160 - BDRVRawState *s = bs->opaque;  
1161 - DWORD low, high;  
1162 -  
1163 - low = offset;  
1164 - high = offset >> 32;  
1165 - if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))  
1166 - return -EIO;  
1167 - if (!SetEndOfFile(s->hfile))  
1168 - return -EIO;  
1169 - return 0;  
1170 -}  
1171 -  
1172 -static int64_t raw_getlength(BlockDriverState *bs)  
1173 -{  
1174 - BDRVRawState *s = bs->opaque;  
1175 - LARGE_INTEGER l;  
1176 - ULARGE_INTEGER available, total, total_free;  
1177 - DISK_GEOMETRY_EX dg;  
1178 - DWORD count;  
1179 - BOOL status;  
1180 -  
1181 - switch(s->type) {  
1182 - case FTYPE_FILE:  
1183 - l.LowPart = GetFileSize(s->hfile, &l.HighPart);  
1184 - if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)  
1185 - return -EIO;  
1186 - break;  
1187 - case FTYPE_CD:  
1188 - if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))  
1189 - return -EIO;  
1190 - l.QuadPart = total.QuadPart;  
1191 - break;  
1192 - case FTYPE_HARDDISK:  
1193 - status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,  
1194 - NULL, 0, &dg, sizeof(dg), &count, NULL);  
1195 - if (status != 0) {  
1196 - l = dg.DiskSize;  
1197 - }  
1198 - break;  
1199 - default:  
1200 - return -EIO;  
1201 - }  
1202 - return l.QuadPart;  
1203 -}  
1204 -  
1205 -static int raw_create(const char *filename, int64_t total_size,  
1206 - const char *backing_file, int flags)  
1207 -{  
1208 - int fd;  
1209 -  
1210 - if (flags || backing_file)  
1211 - return -ENOTSUP;  
1212 -  
1213 - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,  
1214 - 0644);  
1215 - if (fd < 0)  
1216 - return -EIO;  
1217 - set_sparse(fd);  
1218 - ftruncate(fd, total_size * 512);  
1219 - close(fd);  
1220 - return 0;  
1221 -}  
1222 -  
1223 -void qemu_aio_init(void)  
1224 -{  
1225 -}  
1226 -  
1227 -void qemu_aio_poll(void)  
1228 -{  
1229 -}  
1230 -  
1231 -void qemu_aio_flush(void)  
1232 -{  
1233 -}  
1234 -  
1235 -void qemu_aio_wait_start(void)  
1236 -{  
1237 -}  
1238 -  
1239 -void qemu_aio_wait(void)  
1240 -{  
1241 -#ifndef QEMU_IMG  
1242 - qemu_bh_poll();  
1243 -#endif  
1244 -}  
1245 -  
1246 -void qemu_aio_wait_end(void)  
1247 -{  
1248 -}  
1249 -  
1250 -BlockDriver bdrv_raw = {  
1251 - "raw",  
1252 - sizeof(BDRVRawState),  
1253 - NULL, /* no probe for protocols */  
1254 - raw_open,  
1255 - NULL,  
1256 - NULL,  
1257 - raw_close,  
1258 - raw_create,  
1259 - raw_flush,  
1260 -  
1261 -#if 0  
1262 - .bdrv_aio_read = raw_aio_read,  
1263 - .bdrv_aio_write = raw_aio_write,  
1264 - .bdrv_aio_cancel = raw_aio_cancel,  
1265 - .aiocb_size = sizeof(RawAIOCB);  
1266 -#endif  
1267 - .protocol_name = "file",  
1268 - .bdrv_pread = raw_pread,  
1269 - .bdrv_pwrite = raw_pwrite,  
1270 - .bdrv_truncate = raw_truncate,  
1271 - .bdrv_getlength = raw_getlength,  
1272 -};  
1273 -  
1274 -/***********************************************/  
1275 -/* host device */  
1276 -  
1277 -static int find_cdrom(char *cdrom_name, int cdrom_name_size)  
1278 -{  
1279 - char drives[256], *pdrv = drives;  
1280 - UINT type;  
1281 -  
1282 - memset(drives, 0, sizeof(drives));  
1283 - GetLogicalDriveStrings(sizeof(drives), drives);  
1284 - while(pdrv[0] != '\0') {  
1285 - type = GetDriveType(pdrv);  
1286 - switch(type) {  
1287 - case DRIVE_CDROM:  
1288 - snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);  
1289 - return 0;  
1290 - break;  
1291 - }  
1292 - pdrv += lstrlen(pdrv) + 1;  
1293 - }  
1294 - return -1;  
1295 -}  
1296 -  
1297 -static int find_device_type(BlockDriverState *bs, const char *filename)  
1298 -{  
1299 - BDRVRawState *s = bs->opaque;  
1300 - UINT type;  
1301 - const char *p;  
1302 -  
1303 - if (strstart(filename, "\\\\.\\", &p) ||  
1304 - strstart(filename, "//./", &p)) {  
1305 - if (stristart(p, "PhysicalDrive", NULL))  
1306 - return FTYPE_HARDDISK;  
1307 - snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);  
1308 - type = GetDriveType(s->drive_path);  
1309 - if (type == DRIVE_CDROM)  
1310 - return FTYPE_CD;  
1311 - else  
1312 - return FTYPE_FILE;  
1313 - } else {  
1314 - return FTYPE_FILE;  
1315 - }  
1316 -}  
1317 -  
1318 -static int hdev_open(BlockDriverState *bs, const char *filename, int flags)  
1319 -{  
1320 - BDRVRawState *s = bs->opaque;  
1321 - int access_flags, create_flags;  
1322 - DWORD overlapped;  
1323 - char device_name[64];  
1324 -  
1325 - if (strstart(filename, "/dev/cdrom", NULL)) {  
1326 - if (find_cdrom(device_name, sizeof(device_name)) < 0)  
1327 - return -ENOENT;  
1328 - filename = device_name;  
1329 - } else {  
1330 - /* transform drive letters into device name */  
1331 - if (((filename[0] >= 'a' && filename[0] <= 'z') ||  
1332 - (filename[0] >= 'A' && filename[0] <= 'Z')) &&  
1333 - filename[1] == ':' && filename[2] == '\0') {  
1334 - snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);  
1335 - filename = device_name;  
1336 - }  
1337 - }  
1338 - s->type = find_device_type(bs, filename);  
1339 -  
1340 - if ((flags & BDRV_O_ACCESS) == O_RDWR) {  
1341 - access_flags = GENERIC_READ | GENERIC_WRITE;  
1342 - } else {  
1343 - access_flags = GENERIC_READ;  
1344 - }  
1345 - create_flags = OPEN_EXISTING;  
1346 -  
1347 -#ifdef QEMU_IMG  
1348 - overlapped = FILE_ATTRIBUTE_NORMAL;  
1349 -#else  
1350 - overlapped = FILE_FLAG_OVERLAPPED;  
1351 -#endif  
1352 - s->hfile = CreateFile(filename, access_flags,  
1353 - FILE_SHARE_READ, NULL,  
1354 - create_flags, overlapped, NULL);  
1355 - if (s->hfile == INVALID_HANDLE_VALUE) {  
1356 - int err = GetLastError();  
1357 -  
1358 - if (err == ERROR_ACCESS_DENIED)  
1359 - return -EACCES;  
1360 - return -1;  
1361 - }  
1362 - return 0;  
1363 -}  
1364 -  
1365 -#if 0  
1366 -/***********************************************/  
1367 -/* removable device additional commands */  
1368 -  
1369 -static int raw_is_inserted(BlockDriverState *bs)  
1370 -{  
1371 - return 1;  
1372 -}  
1373 -  
1374 -static int raw_media_changed(BlockDriverState *bs)  
1375 -{  
1376 - return -ENOTSUP;  
1377 -}  
1378 -  
1379 -static int raw_eject(BlockDriverState *bs, int eject_flag)  
1380 -{  
1381 - DWORD ret_count;  
1382 -  
1383 - if (s->type == FTYPE_FILE)  
1384 - return -ENOTSUP;  
1385 - if (eject_flag) {  
1386 - DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,  
1387 - NULL, 0, NULL, 0, &lpBytesReturned, NULL);  
1388 - } else {  
1389 - DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,  
1390 - NULL, 0, NULL, 0, &lpBytesReturned, NULL);  
1391 - }  
1392 -}  
1393 -  
1394 -static int raw_set_locked(BlockDriverState *bs, int locked)  
1395 -{  
1396 - return -ENOTSUP;  
1397 -}  
1398 -#endif  
1399 -  
1400 -BlockDriver bdrv_host_device = {  
1401 - "host_device",  
1402 - sizeof(BDRVRawState),  
1403 - NULL, /* no probe for protocols */  
1404 - hdev_open,  
1405 - NULL,  
1406 - NULL,  
1407 - raw_close,  
1408 - NULL,  
1409 - raw_flush,  
1410 -  
1411 -#if 0  
1412 - .bdrv_aio_read = raw_aio_read,  
1413 - .bdrv_aio_write = raw_aio_write,  
1414 - .bdrv_aio_cancel = raw_aio_cancel,  
1415 - .aiocb_size = sizeof(RawAIOCB);  
1416 -#endif  
1417 - .bdrv_pread = raw_pread,  
1418 - .bdrv_pwrite = raw_pwrite,  
1419 - .bdrv_getlength = raw_getlength,  
1420 -};  
1421 -#endif /* _WIN32 */  
block-raw-win32.c 0 โ†’ 100644
  1 +/*
  2 + * Block driver for RAW files (win32)
  3 + *
  4 + * Copyright (c) 2006 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "qemu-common.h"
  25 +#ifndef QEMU_IMG
  26 +#include "qemu-timer.h"
  27 +#include "exec-all.h"
  28 +#endif
  29 +#include "block_int.h"
  30 +#include <assert.h>
  31 +#include <winioctl.h>
  32 +
  33 +#define FTYPE_FILE 0
  34 +#define FTYPE_CD 1
  35 +#define FTYPE_HARDDISK 2
  36 +
  37 +typedef struct BDRVRawState {
  38 + HANDLE hfile;
  39 + int type;
  40 + char drive_path[16]; /* format: "d:\" */
  41 +} BDRVRawState;
  42 +
  43 +typedef struct RawAIOCB {
  44 + BlockDriverAIOCB common;
  45 + HANDLE hEvent;
  46 + OVERLAPPED ov;
  47 + int count;
  48 +} RawAIOCB;
  49 +
  50 +int qemu_ftruncate64(int fd, int64_t length)
  51 +{
  52 + LARGE_INTEGER li;
  53 + LONG high;
  54 + HANDLE h;
  55 + BOOL res;
  56 +
  57 + if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
  58 + return -1;
  59 +
  60 + h = (HANDLE)_get_osfhandle(fd);
  61 +
  62 + /* get current position, ftruncate do not change position */
  63 + li.HighPart = 0;
  64 + li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
  65 + if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
  66 + return -1;
  67 +
  68 + high = length >> 32;
  69 + if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
  70 + return -1;
  71 + res = SetEndOfFile(h);
  72 +
  73 + /* back to old position */
  74 + SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
  75 + return res ? 0 : -1;
  76 +}
  77 +
  78 +static int set_sparse(int fd)
  79 +{
  80 + DWORD returned;
  81 + return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
  82 + NULL, 0, NULL, 0, &returned, NULL);
  83 +}
  84 +
  85 +static int raw_open(BlockDriverState *bs, const char *filename, int flags)
  86 +{
  87 + BDRVRawState *s = bs->opaque;
  88 + int access_flags, create_flags;
  89 + DWORD overlapped;
  90 +
  91 + s->type = FTYPE_FILE;
  92 +
  93 + if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  94 + access_flags = GENERIC_READ | GENERIC_WRITE;
  95 + } else {
  96 + access_flags = GENERIC_READ;
  97 + }
  98 + if (flags & BDRV_O_CREAT) {
  99 + create_flags = CREATE_ALWAYS;
  100 + } else {
  101 + create_flags = OPEN_EXISTING;
  102 + }
  103 +#ifdef QEMU_IMG
  104 + overlapped = FILE_ATTRIBUTE_NORMAL;
  105 +#else
  106 + overlapped = FILE_FLAG_OVERLAPPED;
  107 +#endif
  108 + s->hfile = CreateFile(filename, access_flags,
  109 + FILE_SHARE_READ, NULL,
  110 + create_flags, overlapped, NULL);
  111 + if (s->hfile == INVALID_HANDLE_VALUE) {
  112 + int err = GetLastError();
  113 +
  114 + if (err == ERROR_ACCESS_DENIED)
  115 + return -EACCES;
  116 + return -1;
  117 + }
  118 + return 0;
  119 +}
  120 +
  121 +static int raw_pread(BlockDriverState *bs, int64_t offset,
  122 + uint8_t *buf, int count)
  123 +{
  124 + BDRVRawState *s = bs->opaque;
  125 + OVERLAPPED ov;
  126 + DWORD ret_count;
  127 + int ret;
  128 +
  129 + memset(&ov, 0, sizeof(ov));
  130 + ov.Offset = offset;
  131 + ov.OffsetHigh = offset >> 32;
  132 + ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
  133 + if (!ret) {
  134 + ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  135 + if (!ret)
  136 + return -EIO;
  137 + else
  138 + return ret_count;
  139 + }
  140 + return ret_count;
  141 +}
  142 +
  143 +static int raw_pwrite(BlockDriverState *bs, int64_t offset,
  144 + const uint8_t *buf, int count)
  145 +{
  146 + BDRVRawState *s = bs->opaque;
  147 + OVERLAPPED ov;
  148 + DWORD ret_count;
  149 + int ret;
  150 +
  151 + memset(&ov, 0, sizeof(ov));
  152 + ov.Offset = offset;
  153 + ov.OffsetHigh = offset >> 32;
  154 + ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
  155 + if (!ret) {
  156 + ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  157 + if (!ret)
  158 + return -EIO;
  159 + else
  160 + return ret_count;
  161 + }
  162 + return ret_count;
  163 +}
  164 +
  165 +#if 0
  166 +#ifndef QEMU_IMG
  167 +static void raw_aio_cb(void *opaque)
  168 +{
  169 + RawAIOCB *acb = opaque;
  170 + BlockDriverState *bs = acb->common.bs;
  171 + BDRVRawState *s = bs->opaque;
  172 + DWORD ret_count;
  173 + int ret;
  174 +
  175 + ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
  176 + if (!ret || ret_count != acb->count) {
  177 + acb->common.cb(acb->common.opaque, -EIO);
  178 + } else {
  179 + acb->common.cb(acb->common.opaque, 0);
  180 + }
  181 +}
  182 +#endif
  183 +
  184 +static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  185 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  186 + BlockDriverCompletionFunc *cb, void *opaque)
  187 +{
  188 + RawAIOCB *acb;
  189 + int64_t offset;
  190 +
  191 + acb = qemu_aio_get(bs, cb, opaque);
  192 + if (acb->hEvent) {
  193 + acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  194 + if (!acb->hEvent) {
  195 + qemu_aio_release(acb);
  196 + return NULL;
  197 + }
  198 + }
  199 + memset(&acb->ov, 0, sizeof(acb->ov));
  200 + offset = sector_num * 512;
  201 + acb->ov.Offset = offset;
  202 + acb->ov.OffsetHigh = offset >> 32;
  203 + acb->ov.hEvent = acb->hEvent;
  204 + acb->count = nb_sectors * 512;
  205 +#ifndef QEMU_IMG
  206 + qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
  207 +#endif
  208 + return acb;
  209 +}
  210 +
  211 +static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
  212 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  213 + BlockDriverCompletionFunc *cb, void *opaque)
  214 +{
  215 + BDRVRawState *s = bs->opaque;
  216 + RawAIOCB *acb;
  217 + int ret;
  218 +
  219 + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  220 + if (!acb)
  221 + return NULL;
  222 + ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
  223 + if (!ret) {
  224 + qemu_aio_release(acb);
  225 + return NULL;
  226 + }
  227 +#ifdef QEMU_IMG
  228 + qemu_aio_release(acb);
  229 +#endif
  230 + return (BlockDriverAIOCB *)acb;
  231 +}
  232 +
  233 +static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
  234 + int64_t sector_num, uint8_t *buf, int nb_sectors,
  235 + BlockDriverCompletionFunc *cb, void *opaque)
  236 +{
  237 + BDRVRawState *s = bs->opaque;
  238 + RawAIOCB *acb;
  239 + int ret;
  240 +
  241 + acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  242 + if (!acb)
  243 + return NULL;
  244 + ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
  245 + if (!ret) {
  246 + qemu_aio_release(acb);
  247 + return NULL;
  248 + }
  249 +#ifdef QEMU_IMG
  250 + qemu_aio_release(acb);
  251 +#endif
  252 + return (BlockDriverAIOCB *)acb;
  253 +}
  254 +
  255 +static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
  256 +{
  257 +#ifndef QEMU_IMG
  258 + RawAIOCB *acb = (RawAIOCB *)blockacb;
  259 + BlockDriverState *bs = acb->common.bs;
  260 + BDRVRawState *s = bs->opaque;
  261 +
  262 + qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
  263 + /* XXX: if more than one async I/O it is not correct */
  264 + CancelIo(s->hfile);
  265 + qemu_aio_release(acb);
  266 +#endif
  267 +}
  268 +#endif /* #if 0 */
  269 +
  270 +static void raw_flush(BlockDriverState *bs)
  271 +{
  272 + BDRVRawState *s = bs->opaque;
  273 + FlushFileBuffers(s->hfile);
  274 +}
  275 +
  276 +static void raw_close(BlockDriverState *bs)
  277 +{
  278 + BDRVRawState *s = bs->opaque;
  279 + CloseHandle(s->hfile);
  280 +}
  281 +
  282 +static int raw_truncate(BlockDriverState *bs, int64_t offset)
  283 +{
  284 + BDRVRawState *s = bs->opaque;
  285 + DWORD low, high;
  286 +
  287 + low = offset;
  288 + high = offset >> 32;
  289 + if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
  290 + return -EIO;
  291 + if (!SetEndOfFile(s->hfile))
  292 + return -EIO;
  293 + return 0;
  294 +}
  295 +
  296 +static int64_t raw_getlength(BlockDriverState *bs)
  297 +{
  298 + BDRVRawState *s = bs->opaque;
  299 + LARGE_INTEGER l;
  300 + ULARGE_INTEGER available, total, total_free;
  301 + DISK_GEOMETRY_EX dg;
  302 + DWORD count;
  303 + BOOL status;
  304 +
  305 + switch(s->type) {
  306 + case FTYPE_FILE:
  307 + l.LowPart = GetFileSize(s->hfile, &l.HighPart);
  308 + if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
  309 + return -EIO;
  310 + break;
  311 + case FTYPE_CD:
  312 + if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
  313 + return -EIO;
  314 + l.QuadPart = total.QuadPart;
  315 + break;
  316 + case FTYPE_HARDDISK:
  317 + status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
  318 + NULL, 0, &dg, sizeof(dg), &count, NULL);
  319 + if (status != 0) {
  320 + l = dg.DiskSize;
  321 + }
  322 + break;
  323 + default:
  324 + return -EIO;
  325 + }
  326 + return l.QuadPart;
  327 +}
  328 +
  329 +static int raw_create(const char *filename, int64_t total_size,
  330 + const char *backing_file, int flags)
  331 +{
  332 + int fd;
  333 +
  334 + if (flags || backing_file)
  335 + return -ENOTSUP;
  336 +
  337 + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
  338 + 0644);
  339 + if (fd < 0)
  340 + return -EIO;
  341 + set_sparse(fd);
  342 + ftruncate(fd, total_size * 512);
  343 + close(fd);
  344 + return 0;
  345 +}
  346 +
  347 +void qemu_aio_init(void)
  348 +{
  349 +}
  350 +
  351 +void qemu_aio_poll(void)
  352 +{
  353 +}
  354 +
  355 +void qemu_aio_flush(void)
  356 +{
  357 +}
  358 +
  359 +void qemu_aio_wait_start(void)
  360 +{
  361 +}
  362 +
  363 +void qemu_aio_wait(void)
  364 +{
  365 +#ifndef QEMU_IMG
  366 + qemu_bh_poll();
  367 +#endif
  368 +}
  369 +
  370 +void qemu_aio_wait_end(void)
  371 +{
  372 +}
  373 +
  374 +BlockDriver bdrv_raw = {
  375 + "raw",
  376 + sizeof(BDRVRawState),
  377 + NULL, /* no probe for protocols */
  378 + raw_open,
  379 + NULL,
  380 + NULL,
  381 + raw_close,
  382 + raw_create,
  383 + raw_flush,
  384 +
  385 +#if 0
  386 + .bdrv_aio_read = raw_aio_read,
  387 + .bdrv_aio_write = raw_aio_write,
  388 + .bdrv_aio_cancel = raw_aio_cancel,
  389 + .aiocb_size = sizeof(RawAIOCB);
  390 +#endif
  391 + .protocol_name = "file",
  392 + .bdrv_pread = raw_pread,
  393 + .bdrv_pwrite = raw_pwrite,
  394 + .bdrv_truncate = raw_truncate,
  395 + .bdrv_getlength = raw_getlength,
  396 +};
  397 +
  398 +/***********************************************/
  399 +/* host device */
  400 +
  401 +static int find_cdrom(char *cdrom_name, int cdrom_name_size)
  402 +{
  403 + char drives[256], *pdrv = drives;
  404 + UINT type;
  405 +
  406 + memset(drives, 0, sizeof(drives));
  407 + GetLogicalDriveStrings(sizeof(drives), drives);
  408 + while(pdrv[0] != '\0') {
  409 + type = GetDriveType(pdrv);
  410 + switch(type) {
  411 + case DRIVE_CDROM:
  412 + snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
  413 + return 0;
  414 + break;
  415 + }
  416 + pdrv += lstrlen(pdrv) + 1;
  417 + }
  418 + return -1;
  419 +}
  420 +
  421 +static int find_device_type(BlockDriverState *bs, const char *filename)
  422 +{
  423 + BDRVRawState *s = bs->opaque;
  424 + UINT type;
  425 + const char *p;
  426 +
  427 + if (strstart(filename, "\\\\.\\", &p) ||
  428 + strstart(filename, "//./", &p)) {
  429 + if (stristart(p, "PhysicalDrive", NULL))
  430 + return FTYPE_HARDDISK;
  431 + snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
  432 + type = GetDriveType(s->drive_path);
  433 + if (type == DRIVE_CDROM)
  434 + return FTYPE_CD;
  435 + else
  436 + return FTYPE_FILE;
  437 + } else {
  438 + return FTYPE_FILE;
  439 + }
  440 +}
  441 +
  442 +static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
  443 +{
  444 + BDRVRawState *s = bs->opaque;
  445 + int access_flags, create_flags;
  446 + DWORD overlapped;
  447 + char device_name[64];
  448 +
  449 + if (strstart(filename, "/dev/cdrom", NULL)) {
  450 + if (find_cdrom(device_name, sizeof(device_name)) < 0)
  451 + return -ENOENT;
  452 + filename = device_name;
  453 + } else {
  454 + /* transform drive letters into device name */
  455 + if (((filename[0] >= 'a' && filename[0] <= 'z') ||
  456 + (filename[0] >= 'A' && filename[0] <= 'Z')) &&
  457 + filename[1] == ':' && filename[2] == '\0') {
  458 + snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
  459 + filename = device_name;
  460 + }
  461 + }
  462 + s->type = find_device_type(bs, filename);
  463 +
  464 + if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  465 + access_flags = GENERIC_READ | GENERIC_WRITE;
  466 + } else {
  467 + access_flags = GENERIC_READ;
  468 + }
  469 + create_flags = OPEN_EXISTING;
  470 +
  471 +#ifdef QEMU_IMG
  472 + overlapped = FILE_ATTRIBUTE_NORMAL;
  473 +#else
  474 + overlapped = FILE_FLAG_OVERLAPPED;
  475 +#endif
  476 + s->hfile = CreateFile(filename, access_flags,
  477 + FILE_SHARE_READ, NULL,
  478 + create_flags, overlapped, NULL);
  479 + if (s->hfile == INVALID_HANDLE_VALUE) {
  480 + int err = GetLastError();
  481 +
  482 + if (err == ERROR_ACCESS_DENIED)
  483 + return -EACCES;
  484 + return -1;
  485 + }
  486 + return 0;
  487 +}
  488 +
  489 +#if 0
  490 +/***********************************************/
  491 +/* removable device additional commands */
  492 +
  493 +static int raw_is_inserted(BlockDriverState *bs)
  494 +{
  495 + return 1;
  496 +}
  497 +
  498 +static int raw_media_changed(BlockDriverState *bs)
  499 +{
  500 + return -ENOTSUP;
  501 +}
  502 +
  503 +static int raw_eject(BlockDriverState *bs, int eject_flag)
  504 +{
  505 + DWORD ret_count;
  506 +
  507 + if (s->type == FTYPE_FILE)
  508 + return -ENOTSUP;
  509 + if (eject_flag) {
  510 + DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,
  511 + NULL, 0, NULL, 0, &lpBytesReturned, NULL);
  512 + } else {
  513 + DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,
  514 + NULL, 0, NULL, 0, &lpBytesReturned, NULL);
  515 + }
  516 +}
  517 +
  518 +static int raw_set_locked(BlockDriverState *bs, int locked)
  519 +{
  520 + return -ENOTSUP;
  521 +}
  522 +#endif
  523 +
  524 +BlockDriver bdrv_host_device = {
  525 + "host_device",
  526 + sizeof(BDRVRawState),
  527 + NULL, /* no probe for protocols */
  528 + hdev_open,
  529 + NULL,
  530 + NULL,
  531 + raw_close,
  532 + NULL,
  533 + raw_flush,
  534 +
  535 +#if 0
  536 + .bdrv_aio_read = raw_aio_read,
  537 + .bdrv_aio_write = raw_aio_write,
  538 + .bdrv_aio_cancel = raw_aio_cancel,
  539 + .aiocb_size = sizeof(RawAIOCB);
  540 +#endif
  541 + .bdrv_pread = raw_pread,
  542 + .bdrv_pwrite = raw_pwrite,
  543 + .bdrv_getlength = raw_getlength,
  544 +};