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/osdep.h" 25 #include "qapi/error.h" 26 #include "qemu/cutils.h" 27 #include "block/block_int.h" 28 #include "qemu/module.h" 29 #include "block/raw-aio.h" 30 #include "trace.h" 31 #include "block/thread-pool.h" 32 #include "qemu/iov.h" 33 #include "qapi/qmp/qstring.h" 34 #include <windows.h> 35 #include <winioctl.h> 36 37 #define FTYPE_FILE 0 38 #define FTYPE_CD 1 39 #define FTYPE_HARDDISK 2 40 41 typedef struct RawWin32AIOData { 42 BlockDriverState *bs; 43 HANDLE hfile; 44 struct iovec *aio_iov; 45 int aio_niov; 46 size_t aio_nbytes; 47 off64_t aio_offset; 48 int aio_type; 49 } RawWin32AIOData; 50 51 typedef struct BDRVRawState { 52 HANDLE hfile; 53 int type; 54 char drive_path[16]; /* format: "d:\" */ 55 QEMUWin32AIOState *aio; 56 } BDRVRawState; 57 58 /* 59 * Read/writes the data to/from a given linear buffer. 60 * 61 * Returns the number of bytes handles or -errno in case of an error. Short 62 * reads are only returned if the end of the file is reached. 63 */ 64 static size_t handle_aiocb_rw(RawWin32AIOData *aiocb) 65 { 66 size_t offset = 0; 67 int i; 68 69 for (i = 0; i < aiocb->aio_niov; i++) { 70 OVERLAPPED ov; 71 DWORD ret, ret_count, len; 72 73 memset(&ov, 0, sizeof(ov)); 74 ov.Offset = (aiocb->aio_offset + offset); 75 ov.OffsetHigh = (aiocb->aio_offset + offset) >> 32; 76 len = aiocb->aio_iov[i].iov_len; 77 if (aiocb->aio_type & QEMU_AIO_WRITE) { 78 ret = WriteFile(aiocb->hfile, aiocb->aio_iov[i].iov_base, 79 len, &ret_count, &ov); 80 } else { 81 ret = ReadFile(aiocb->hfile, aiocb->aio_iov[i].iov_base, 82 len, &ret_count, &ov); 83 } 84 if (!ret) { 85 ret_count = 0; 86 } 87 if (ret_count != len) { 88 offset += ret_count; 89 break; 90 } 91 offset += len; 92 } 93 94 return offset; 95 } 96 97 static int aio_worker(void *arg) 98 { 99 RawWin32AIOData *aiocb = arg; 100 ssize_t ret = 0; 101 size_t count; 102 103 switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) { 104 case QEMU_AIO_READ: 105 count = handle_aiocb_rw(aiocb); 106 if (count < aiocb->aio_nbytes) { 107 /* A short read means that we have reached EOF. Pad the buffer 108 * with zeros for bytes after EOF. */ 109 iov_memset(aiocb->aio_iov, aiocb->aio_niov, count, 110 0, aiocb->aio_nbytes - count); 111 112 count = aiocb->aio_nbytes; 113 } 114 if (count == aiocb->aio_nbytes) { 115 ret = 0; 116 } else { 117 ret = -EINVAL; 118 } 119 break; 120 case QEMU_AIO_WRITE: 121 count = handle_aiocb_rw(aiocb); 122 if (count == aiocb->aio_nbytes) { 123 ret = 0; 124 } else { 125 ret = -EINVAL; 126 } 127 break; 128 case QEMU_AIO_FLUSH: 129 if (!FlushFileBuffers(aiocb->hfile)) { 130 return -EIO; 131 } 132 break; 133 default: 134 fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type); 135 ret = -EINVAL; 136 break; 137 } 138 139 g_free(aiocb); 140 return ret; 141 } 142 143 static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile, 144 int64_t offset, QEMUIOVector *qiov, int count, 145 BlockCompletionFunc *cb, void *opaque, int type) 146 { 147 RawWin32AIOData *acb = g_new(RawWin32AIOData, 1); 148 ThreadPool *pool; 149 150 acb->bs = bs; 151 acb->hfile = hfile; 152 acb->aio_type = type; 153 154 if (qiov) { 155 acb->aio_iov = qiov->iov; 156 acb->aio_niov = qiov->niov; 157 assert(qiov->size == count); 158 } 159 acb->aio_nbytes = count; 160 acb->aio_offset = offset; 161 162 trace_paio_submit(acb, opaque, offset, count, type); 163 pool = aio_get_thread_pool(bdrv_get_aio_context(bs)); 164 return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque); 165 } 166 167 int qemu_ftruncate64(int fd, int64_t length) 168 { 169 LARGE_INTEGER li; 170 DWORD dw; 171 LONG high; 172 HANDLE h; 173 BOOL res; 174 175 if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0) 176 return -1; 177 178 h = (HANDLE)_get_osfhandle(fd); 179 180 /* get current position, ftruncate do not change position */ 181 li.HighPart = 0; 182 li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT); 183 if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { 184 return -1; 185 } 186 187 high = length >> 32; 188 dw = SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN); 189 if (dw == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { 190 return -1; 191 } 192 res = SetEndOfFile(h); 193 194 /* back to old position */ 195 SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN); 196 return res ? 0 : -1; 197 } 198 199 static int set_sparse(int fd) 200 { 201 DWORD returned; 202 return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE, 203 NULL, 0, NULL, 0, &returned, NULL); 204 } 205 206 static void raw_detach_aio_context(BlockDriverState *bs) 207 { 208 BDRVRawState *s = bs->opaque; 209 210 if (s->aio) { 211 win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs)); 212 } 213 } 214 215 static void raw_attach_aio_context(BlockDriverState *bs, 216 AioContext *new_context) 217 { 218 BDRVRawState *s = bs->opaque; 219 220 if (s->aio) { 221 win32_aio_attach_aio_context(s->aio, new_context); 222 } 223 } 224 225 static void raw_probe_alignment(BlockDriverState *bs, Error **errp) 226 { 227 BDRVRawState *s = bs->opaque; 228 DWORD sectorsPerCluster, freeClusters, totalClusters, count; 229 DISK_GEOMETRY_EX dg; 230 BOOL status; 231 232 if (s->type == FTYPE_CD) { 233 bs->bl.request_alignment = 2048; 234 return; 235 } 236 if (s->type == FTYPE_HARDDISK) { 237 status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 238 NULL, 0, &dg, sizeof(dg), &count, NULL); 239 if (status != 0) { 240 bs->bl.request_alignment = dg.Geometry.BytesPerSector; 241 return; 242 } 243 /* try GetDiskFreeSpace too */ 244 } 245 246 if (s->drive_path[0]) { 247 GetDiskFreeSpace(s->drive_path, §orsPerCluster, 248 &dg.Geometry.BytesPerSector, 249 &freeClusters, &totalClusters); 250 bs->bl.request_alignment = dg.Geometry.BytesPerSector; 251 } 252 } 253 254 static void raw_parse_flags(int flags, bool use_aio, int *access_flags, 255 DWORD *overlapped) 256 { 257 assert(access_flags != NULL); 258 assert(overlapped != NULL); 259 260 if (flags & BDRV_O_RDWR) { 261 *access_flags = GENERIC_READ | GENERIC_WRITE; 262 } else { 263 *access_flags = GENERIC_READ; 264 } 265 266 *overlapped = FILE_ATTRIBUTE_NORMAL; 267 if (use_aio) { 268 *overlapped |= FILE_FLAG_OVERLAPPED; 269 } 270 if (flags & BDRV_O_NOCACHE) { 271 *overlapped |= FILE_FLAG_NO_BUFFERING; 272 } 273 } 274 275 static void raw_parse_filename(const char *filename, QDict *options, 276 Error **errp) 277 { 278 bdrv_parse_filename_strip_prefix(filename, "file:", options); 279 } 280 281 static QemuOptsList raw_runtime_opts = { 282 .name = "raw", 283 .head = QTAILQ_HEAD_INITIALIZER(raw_runtime_opts.head), 284 .desc = { 285 { 286 .name = "filename", 287 .type = QEMU_OPT_STRING, 288 .help = "File name of the image", 289 }, 290 { 291 .name = "aio", 292 .type = QEMU_OPT_STRING, 293 .help = "host AIO implementation (threads, native)", 294 }, 295 { /* end of list */ } 296 }, 297 }; 298 299 static bool get_aio_option(QemuOpts *opts, int flags, Error **errp) 300 { 301 BlockdevAioOptions aio, aio_default; 302 303 aio_default = (flags & BDRV_O_NATIVE_AIO) ? BLOCKDEV_AIO_OPTIONS_NATIVE 304 : BLOCKDEV_AIO_OPTIONS_THREADS; 305 aio = qapi_enum_parse(&BlockdevAioOptions_lookup, qemu_opt_get(opts, "aio"), 306 aio_default, errp); 307 308 switch (aio) { 309 case BLOCKDEV_AIO_OPTIONS_NATIVE: 310 return true; 311 case BLOCKDEV_AIO_OPTIONS_THREADS: 312 return false; 313 default: 314 error_setg(errp, "Invalid AIO option"); 315 } 316 return false; 317 } 318 319 static int raw_open(BlockDriverState *bs, QDict *options, int flags, 320 Error **errp) 321 { 322 BDRVRawState *s = bs->opaque; 323 int access_flags; 324 DWORD overlapped; 325 QemuOpts *opts; 326 Error *local_err = NULL; 327 const char *filename; 328 bool use_aio; 329 int ret; 330 331 s->type = FTYPE_FILE; 332 333 opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, &error_abort); 334 qemu_opts_absorb_qdict(opts, options, &local_err); 335 if (local_err) { 336 error_propagate(errp, local_err); 337 ret = -EINVAL; 338 goto fail; 339 } 340 341 if (qdict_get_try_bool(options, "locking", false)) { 342 error_setg(errp, "locking=on is not supported on Windows"); 343 ret = -EINVAL; 344 goto fail; 345 } 346 347 filename = qemu_opt_get(opts, "filename"); 348 349 use_aio = get_aio_option(opts, flags, &local_err); 350 if (local_err) { 351 error_propagate(errp, local_err); 352 ret = -EINVAL; 353 goto fail; 354 } 355 356 raw_parse_flags(flags, use_aio, &access_flags, &overlapped); 357 358 if (filename[0] && filename[1] == ':') { 359 snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", filename[0]); 360 } else if (filename[0] == '\\' && filename[1] == '\\') { 361 s->drive_path[0] = 0; 362 } else { 363 /* Relative path. */ 364 char buf[MAX_PATH]; 365 GetCurrentDirectory(MAX_PATH, buf); 366 snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", buf[0]); 367 } 368 369 s->hfile = CreateFile(filename, access_flags, 370 FILE_SHARE_READ, NULL, 371 OPEN_EXISTING, overlapped, NULL); 372 if (s->hfile == INVALID_HANDLE_VALUE) { 373 int err = GetLastError(); 374 375 error_setg_win32(errp, err, "Could not open '%s'", filename); 376 if (err == ERROR_ACCESS_DENIED) { 377 ret = -EACCES; 378 } else { 379 ret = -EINVAL; 380 } 381 goto fail; 382 } 383 384 if (use_aio) { 385 s->aio = win32_aio_init(); 386 if (s->aio == NULL) { 387 CloseHandle(s->hfile); 388 error_setg(errp, "Could not initialize AIO"); 389 ret = -EINVAL; 390 goto fail; 391 } 392 393 ret = win32_aio_attach(s->aio, s->hfile); 394 if (ret < 0) { 395 win32_aio_cleanup(s->aio); 396 CloseHandle(s->hfile); 397 error_setg_errno(errp, -ret, "Could not enable AIO"); 398 goto fail; 399 } 400 401 win32_aio_attach_aio_context(s->aio, bdrv_get_aio_context(bs)); 402 } 403 404 ret = 0; 405 fail: 406 qemu_opts_del(opts); 407 return ret; 408 } 409 410 static BlockAIOCB *raw_aio_readv(BlockDriverState *bs, 411 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, 412 BlockCompletionFunc *cb, void *opaque) 413 { 414 BDRVRawState *s = bs->opaque; 415 if (s->aio) { 416 return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov, 417 nb_sectors, cb, opaque, QEMU_AIO_READ); 418 } else { 419 return paio_submit(bs, s->hfile, sector_num << BDRV_SECTOR_BITS, qiov, 420 nb_sectors << BDRV_SECTOR_BITS, 421 cb, opaque, QEMU_AIO_READ); 422 } 423 } 424 425 static BlockAIOCB *raw_aio_writev(BlockDriverState *bs, 426 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, 427 BlockCompletionFunc *cb, void *opaque) 428 { 429 BDRVRawState *s = bs->opaque; 430 if (s->aio) { 431 return win32_aio_submit(bs, s->aio, s->hfile, sector_num, qiov, 432 nb_sectors, cb, opaque, QEMU_AIO_WRITE); 433 } else { 434 return paio_submit(bs, s->hfile, sector_num << BDRV_SECTOR_BITS, qiov, 435 nb_sectors << BDRV_SECTOR_BITS, 436 cb, opaque, QEMU_AIO_WRITE); 437 } 438 } 439 440 static BlockAIOCB *raw_aio_flush(BlockDriverState *bs, 441 BlockCompletionFunc *cb, void *opaque) 442 { 443 BDRVRawState *s = bs->opaque; 444 return paio_submit(bs, s->hfile, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH); 445 } 446 447 static void raw_close(BlockDriverState *bs) 448 { 449 BDRVRawState *s = bs->opaque; 450 451 if (s->aio) { 452 win32_aio_detach_aio_context(s->aio, bdrv_get_aio_context(bs)); 453 win32_aio_cleanup(s->aio); 454 s->aio = NULL; 455 } 456 457 CloseHandle(s->hfile); 458 if (bs->open_flags & BDRV_O_TEMPORARY) { 459 unlink(bs->filename); 460 } 461 } 462 463 static int raw_truncate(BlockDriverState *bs, int64_t offset, 464 PreallocMode prealloc, Error **errp) 465 { 466 BDRVRawState *s = bs->opaque; 467 LONG low, high; 468 DWORD dwPtrLow; 469 470 if (prealloc != PREALLOC_MODE_OFF) { 471 error_setg(errp, "Unsupported preallocation mode '%s'", 472 PreallocMode_str(prealloc)); 473 return -ENOTSUP; 474 } 475 476 low = offset; 477 high = offset >> 32; 478 479 /* 480 * An error has occurred if the return value is INVALID_SET_FILE_POINTER 481 * and GetLastError doesn't return NO_ERROR. 482 */ 483 dwPtrLow = SetFilePointer(s->hfile, low, &high, FILE_BEGIN); 484 if (dwPtrLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { 485 error_setg_win32(errp, GetLastError(), "SetFilePointer error"); 486 return -EIO; 487 } 488 if (SetEndOfFile(s->hfile) == 0) { 489 error_setg_win32(errp, GetLastError(), "SetEndOfFile error"); 490 return -EIO; 491 } 492 return 0; 493 } 494 495 static int64_t raw_getlength(BlockDriverState *bs) 496 { 497 BDRVRawState *s = bs->opaque; 498 LARGE_INTEGER l; 499 ULARGE_INTEGER available, total, total_free; 500 DISK_GEOMETRY_EX dg; 501 DWORD count; 502 BOOL status; 503 504 switch(s->type) { 505 case FTYPE_FILE: 506 l.LowPart = GetFileSize(s->hfile, (PDWORD)&l.HighPart); 507 if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR) 508 return -EIO; 509 break; 510 case FTYPE_CD: 511 if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free)) 512 return -EIO; 513 l.QuadPart = total.QuadPart; 514 break; 515 case FTYPE_HARDDISK: 516 status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 517 NULL, 0, &dg, sizeof(dg), &count, NULL); 518 if (status != 0) { 519 l = dg.DiskSize; 520 } 521 break; 522 default: 523 return -EIO; 524 } 525 return l.QuadPart; 526 } 527 528 static int64_t raw_get_allocated_file_size(BlockDriverState *bs) 529 { 530 typedef DWORD (WINAPI * get_compressed_t)(const char *filename, 531 DWORD * high); 532 get_compressed_t get_compressed; 533 struct _stati64 st; 534 const char *filename = bs->filename; 535 /* WinNT support GetCompressedFileSize to determine allocate size */ 536 get_compressed = 537 (get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"), 538 "GetCompressedFileSizeA"); 539 if (get_compressed) { 540 DWORD high, low; 541 low = get_compressed(filename, &high); 542 if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) { 543 return (((int64_t) high) << 32) + low; 544 } 545 } 546 547 if (_stati64(filename, &st) < 0) { 548 return -1; 549 } 550 return st.st_size; 551 } 552 553 static int raw_create(const char *filename, QemuOpts *opts, Error **errp) 554 { 555 int fd; 556 int64_t total_size = 0; 557 558 strstart(filename, "file:", &filename); 559 560 /* Read out options */ 561 total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), 562 BDRV_SECTOR_SIZE); 563 564 fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 565 0644); 566 if (fd < 0) { 567 error_setg_errno(errp, errno, "Could not create file"); 568 return -EIO; 569 } 570 set_sparse(fd); 571 ftruncate(fd, total_size); 572 qemu_close(fd); 573 return 0; 574 } 575 576 577 static QemuOptsList raw_create_opts = { 578 .name = "raw-create-opts", 579 .head = QTAILQ_HEAD_INITIALIZER(raw_create_opts.head), 580 .desc = { 581 { 582 .name = BLOCK_OPT_SIZE, 583 .type = QEMU_OPT_SIZE, 584 .help = "Virtual disk size" 585 }, 586 { /* end of list */ } 587 } 588 }; 589 590 BlockDriver bdrv_file = { 591 .format_name = "file", 592 .protocol_name = "file", 593 .instance_size = sizeof(BDRVRawState), 594 .bdrv_needs_filename = true, 595 .bdrv_parse_filename = raw_parse_filename, 596 .bdrv_file_open = raw_open, 597 .bdrv_refresh_limits = raw_probe_alignment, 598 .bdrv_close = raw_close, 599 .bdrv_create = raw_create, 600 .bdrv_has_zero_init = bdrv_has_zero_init_1, 601 602 .bdrv_aio_readv = raw_aio_readv, 603 .bdrv_aio_writev = raw_aio_writev, 604 .bdrv_aio_flush = raw_aio_flush, 605 606 .bdrv_truncate = raw_truncate, 607 .bdrv_getlength = raw_getlength, 608 .bdrv_get_allocated_file_size 609 = raw_get_allocated_file_size, 610 611 .create_opts = &raw_create_opts, 612 }; 613 614 /***********************************************/ 615 /* host device */ 616 617 static int find_cdrom(char *cdrom_name, int cdrom_name_size) 618 { 619 char drives[256], *pdrv = drives; 620 UINT type; 621 622 memset(drives, 0, sizeof(drives)); 623 GetLogicalDriveStrings(sizeof(drives), drives); 624 while(pdrv[0] != '\0') { 625 type = GetDriveType(pdrv); 626 switch(type) { 627 case DRIVE_CDROM: 628 snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]); 629 return 0; 630 break; 631 } 632 pdrv += lstrlen(pdrv) + 1; 633 } 634 return -1; 635 } 636 637 static int find_device_type(BlockDriverState *bs, const char *filename) 638 { 639 BDRVRawState *s = bs->opaque; 640 UINT type; 641 const char *p; 642 643 if (strstart(filename, "\\\\.\\", &p) || 644 strstart(filename, "//./", &p)) { 645 if (stristart(p, "PhysicalDrive", NULL)) 646 return FTYPE_HARDDISK; 647 snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]); 648 type = GetDriveType(s->drive_path); 649 switch (type) { 650 case DRIVE_REMOVABLE: 651 case DRIVE_FIXED: 652 return FTYPE_HARDDISK; 653 case DRIVE_CDROM: 654 return FTYPE_CD; 655 default: 656 return FTYPE_FILE; 657 } 658 } else { 659 return FTYPE_FILE; 660 } 661 } 662 663 static int hdev_probe_device(const char *filename) 664 { 665 if (strstart(filename, "/dev/cdrom", NULL)) 666 return 100; 667 if (is_windows_drive(filename)) 668 return 100; 669 return 0; 670 } 671 672 static void hdev_parse_filename(const char *filename, QDict *options, 673 Error **errp) 674 { 675 bdrv_parse_filename_strip_prefix(filename, "host_device:", options); 676 } 677 678 static int hdev_open(BlockDriverState *bs, QDict *options, int flags, 679 Error **errp) 680 { 681 BDRVRawState *s = bs->opaque; 682 int access_flags, create_flags; 683 int ret = 0; 684 DWORD overlapped; 685 char device_name[64]; 686 687 Error *local_err = NULL; 688 const char *filename; 689 bool use_aio; 690 691 QemuOpts *opts = qemu_opts_create(&raw_runtime_opts, NULL, 0, 692 &error_abort); 693 qemu_opts_absorb_qdict(opts, options, &local_err); 694 if (local_err) { 695 error_propagate(errp, local_err); 696 ret = -EINVAL; 697 goto done; 698 } 699 700 filename = qemu_opt_get(opts, "filename"); 701 702 use_aio = get_aio_option(opts, flags, &local_err); 703 if (!local_err && use_aio) { 704 error_setg(&local_err, "AIO is not supported on Windows host devices"); 705 } 706 if (local_err) { 707 error_propagate(errp, local_err); 708 ret = -EINVAL; 709 goto done; 710 } 711 712 if (strstart(filename, "/dev/cdrom", NULL)) { 713 if (find_cdrom(device_name, sizeof(device_name)) < 0) { 714 error_setg(errp, "Could not open CD-ROM drive"); 715 ret = -ENOENT; 716 goto done; 717 } 718 filename = device_name; 719 } else { 720 /* transform drive letters into device name */ 721 if (((filename[0] >= 'a' && filename[0] <= 'z') || 722 (filename[0] >= 'A' && filename[0] <= 'Z')) && 723 filename[1] == ':' && filename[2] == '\0') { 724 snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]); 725 filename = device_name; 726 } 727 } 728 s->type = find_device_type(bs, filename); 729 730 raw_parse_flags(flags, use_aio, &access_flags, &overlapped); 731 732 create_flags = OPEN_EXISTING; 733 734 s->hfile = CreateFile(filename, access_flags, 735 FILE_SHARE_READ, NULL, 736 create_flags, overlapped, NULL); 737 if (s->hfile == INVALID_HANDLE_VALUE) { 738 int err = GetLastError(); 739 740 if (err == ERROR_ACCESS_DENIED) { 741 ret = -EACCES; 742 } else { 743 ret = -EINVAL; 744 } 745 error_setg_errno(errp, -ret, "Could not open device"); 746 goto done; 747 } 748 749 done: 750 qemu_opts_del(opts); 751 return ret; 752 } 753 754 static BlockDriver bdrv_host_device = { 755 .format_name = "host_device", 756 .protocol_name = "host_device", 757 .instance_size = sizeof(BDRVRawState), 758 .bdrv_needs_filename = true, 759 .bdrv_parse_filename = hdev_parse_filename, 760 .bdrv_probe_device = hdev_probe_device, 761 .bdrv_file_open = hdev_open, 762 .bdrv_close = raw_close, 763 764 .bdrv_aio_readv = raw_aio_readv, 765 .bdrv_aio_writev = raw_aio_writev, 766 .bdrv_aio_flush = raw_aio_flush, 767 768 .bdrv_detach_aio_context = raw_detach_aio_context, 769 .bdrv_attach_aio_context = raw_attach_aio_context, 770 771 .bdrv_getlength = raw_getlength, 772 .has_variable_length = true, 773 774 .bdrv_get_allocated_file_size 775 = raw_get_allocated_file_size, 776 }; 777 778 static void bdrv_file_init(void) 779 { 780 bdrv_register(&bdrv_file); 781 bdrv_register(&bdrv_host_device); 782 } 783 784 block_init(bdrv_file_init); 785