]> git.proxmox.com Git - mirror_qemu.git/blame - block-raw.c
More PowerPC definitions, from POWER 2.04 specifications and misc sources.
[mirror_qemu.git] / block-raw.c
CommitLineData
83f64091
FB
1/*
2 * Block driver for RAW files
5fafdf24 3 *
83f64091 4 * Copyright (c) 2006 Fabrice Bellard
5fafdf24 5 *
83f64091
FB
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 "vl.h"
25#include "block_int.h"
26#include <assert.h>
27#ifndef _WIN32
28#include <aio.h>
29
30#ifndef QEMU_TOOL
31#include "exec-all.h"
32#endif
33
34#ifdef CONFIG_COCOA
35#include <paths.h>
36#include <sys/param.h>
37#include <IOKit/IOKitLib.h>
38#include <IOKit/IOBSD.h>
39#include <IOKit/storage/IOMediaBSDClient.h>
40#include <IOKit/storage/IOMedia.h>
41#include <IOKit/storage/IOCDMedia.h>
42//#include <IOKit/storage/IOCDTypes.h>
43#include <CoreFoundation/CoreFoundation.h>
44#endif
45
46#ifdef __sun__
2e9671da
TS
47#define _POSIX_PTHREAD_SEMANTICS 1
48#include <signal.h>
83f64091
FB
49#include <sys/dkio.h>
50#endif
19cb3738
FB
51#ifdef __linux__
52#include <sys/ioctl.h>
53#include <linux/cdrom.h>
54#include <linux/fd.h>
55#endif
1cb6c3fd
TS
56#ifdef __FreeBSD__
57#include <sys/disk.h>
58#endif
83f64091 59
19cb3738 60//#define DEBUG_FLOPPY
83f64091 61
8c05dbf9
TS
62#define DEBUG_BLOCK
63#if defined(DEBUG_BLOCK) && !defined(QEMU_TOOL)
a50a6282 64#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0) \
2e03286b 65 { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
8c05dbf9
TS
66#else
67#define DEBUG_BLOCK_PRINT(formatCstr, args...)
68#endif
69
19cb3738
FB
70#define FTYPE_FILE 0
71#define FTYPE_CD 1
72#define FTYPE_FD 2
83f64091 73
19cb3738
FB
74/* if the FD is not accessed during that time (in ms), we try to
75 reopen it to see if the disk has been changed */
76#define FD_OPEN_TIMEOUT 1000
83f64091 77
19cb3738
FB
78typedef struct BDRVRawState {
79 int fd;
80 int type;
8c05dbf9 81 unsigned int lseek_err_cnt;
19cb3738
FB
82#if defined(__linux__)
83 /* linux floppy specific */
84 int fd_open_flags;
85 int64_t fd_open_time;
86 int64_t fd_error_time;
87 int fd_got_error;
88 int fd_media_changed;
83f64091 89#endif
19cb3738
FB
90} BDRVRawState;
91
92static int fd_open(BlockDriverState *bs);
83f64091
FB
93
94static int raw_open(BlockDriverState *bs, const char *filename, int flags)
95{
96 BDRVRawState *s = bs->opaque;
19cb3738 97 int fd, open_flags, ret;
83f64091 98
8c05dbf9
TS
99 s->lseek_err_cnt = 0;
100
83f64091
FB
101 open_flags = O_BINARY;
102 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
103 open_flags |= O_RDWR;
104 } else {
105 open_flags |= O_RDONLY;
106 bs->read_only = 1;
107 }
108 if (flags & BDRV_O_CREAT)
109 open_flags |= O_CREAT | O_TRUNC;
110
19cb3738
FB
111 s->type = FTYPE_FILE;
112
83f64091 113 fd = open(filename, open_flags, 0644);
19cb3738
FB
114 if (fd < 0) {
115 ret = -errno;
116 if (ret == -EROFS)
117 ret = -EACCES;
118 return ret;
119 }
83f64091
FB
120 s->fd = fd;
121 return 0;
122}
123
124/* XXX: use host sector size if necessary with:
125#ifdef DIOCGSECTORSIZE
126 {
127 unsigned int sectorsize = 512;
128 if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
129 sectorsize > bufsize)
130 bufsize = sectorsize;
131 }
132#endif
133#ifdef CONFIG_COCOA
134 u_int32_t blockSize = 512;
135 if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
136 bufsize = blockSize;
137 }
138#endif
139*/
140
5fafdf24 141static int raw_pread(BlockDriverState *bs, int64_t offset,
83f64091
FB
142 uint8_t *buf, int count)
143{
144 BDRVRawState *s = bs->opaque;
145 int ret;
3b46e624 146
19cb3738
FB
147 ret = fd_open(bs);
148 if (ret < 0)
149 return ret;
150
8c05dbf9
TS
151 if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
152 ++(s->lseek_err_cnt);
153 if(s->lseek_err_cnt <= 10) {
154 DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
155 s->fd, bs->filename, offset, buf, count,
156 bs->total_sectors, errno, strerror(errno));
157 }
158 return -1;
159 }
160 s->lseek_err_cnt=0;
161
83f64091 162 ret = read(s->fd, buf, count);
8c05dbf9
TS
163 if (ret == count)
164 goto label__raw_read__success;
165
a50a6282 166 DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] read failed %d : %d = %s\n",
8c05dbf9
TS
167 s->fd, bs->filename, offset, buf, count,
168 bs->total_sectors, ret, errno, strerror(errno));
169
170 /* Try harder for CDrom. */
171 if (bs->type == BDRV_TYPE_CDROM) {
172 lseek(s->fd, offset, SEEK_SET);
173 ret = read(s->fd, buf, count);
174 if (ret == count)
175 goto label__raw_read__success;
176 lseek(s->fd, offset, SEEK_SET);
177 ret = read(s->fd, buf, count);
178 if (ret == count)
179 goto label__raw_read__success;
180
a50a6282 181 DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %lld, %p, %d) [%lld] retry read failed %d : %d = %s\n",
8c05dbf9
TS
182 s->fd, bs->filename, offset, buf, count,
183 bs->total_sectors, ret, errno, strerror(errno));
184 }
185
8c05dbf9
TS
186label__raw_read__success:
187
83f64091
FB
188 return ret;
189}
190
5fafdf24 191static int raw_pwrite(BlockDriverState *bs, int64_t offset,
83f64091
FB
192 const uint8_t *buf, int count)
193{
194 BDRVRawState *s = bs->opaque;
195 int ret;
3b46e624 196
19cb3738
FB
197 ret = fd_open(bs);
198 if (ret < 0)
199 return ret;
200
8c05dbf9
TS
201 if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
202 ++(s->lseek_err_cnt);
203 if(s->lseek_err_cnt) {
a50a6282 204 DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] lseek failed : %d = %s\n",
8c05dbf9
TS
205 s->fd, bs->filename, offset, buf, count,
206 bs->total_sectors, errno, strerror(errno));
207 }
208 return -1;
209 }
210 s->lseek_err_cnt = 0;
211
83f64091 212 ret = write(s->fd, buf, count);
8c05dbf9
TS
213 if (ret == count)
214 goto label__raw_write__success;
215
a50a6282 216 DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %lld, %p, %d) [%lld] write failed %d : %d = %s\n",
8c05dbf9
TS
217 s->fd, bs->filename, offset, buf, count,
218 bs->total_sectors, ret, errno, strerror(errno));
219
8c05dbf9
TS
220label__raw_write__success:
221
83f64091
FB
222 return ret;
223}
224
225/***********************************************************/
19cb3738 226/* Unix AIO using POSIX AIO */
83f64091
FB
227
228typedef struct RawAIOCB {
ce1a14dc 229 BlockDriverAIOCB common;
83f64091 230 struct aiocb aiocb;
ce1a14dc 231 struct RawAIOCB *next;
83f64091
FB
232} RawAIOCB;
233
234static int aio_sig_num = SIGUSR2;
ce1a14dc 235static RawAIOCB *first_aio; /* AIO issued */
979b67ad 236static int aio_initialized = 0;
83f64091 237
83f64091
FB
238static void aio_signal_handler(int signum)
239{
979b67ad 240#ifndef QEMU_TOOL
83f64091
FB
241 CPUState *env = cpu_single_env;
242 if (env) {
243 /* stop the currently executing cpu because a timer occured */
244 cpu_interrupt(env, CPU_INTERRUPT_EXIT);
245#ifdef USE_KQEMU
246 if (env->kqemu_enabled) {
247 kqemu_cpu_interrupt(env);
248 }
249#endif
250 }
979b67ad 251#endif
83f64091
FB
252}
253
254void qemu_aio_init(void)
255{
256 struct sigaction act;
979b67ad
FB
257
258 aio_initialized = 1;
3b46e624 259
83f64091
FB
260 sigfillset(&act.sa_mask);
261 act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
262 act.sa_handler = aio_signal_handler;
263 sigaction(aio_sig_num, &act, NULL);
264
19cb3738 265#if defined(__GLIBC__) && defined(__linux__)
83f64091 266 {
19cb3738
FB
267 /* XXX: aio thread exit seems to hang on RedHat 9 and this init
268 seems to fix the problem. */
83f64091
FB
269 struct aioinit ai;
270 memset(&ai, 0, sizeof(ai));
19cb3738 271 ai.aio_threads = 1;
83f64091
FB
272 ai.aio_num = 1;
273 ai.aio_idle_time = 365 * 100000;
274 aio_init(&ai);
275 }
19cb3738 276#endif
83f64091 277}
83f64091
FB
278
279void qemu_aio_poll(void)
280{
ce1a14dc 281 RawAIOCB *acb, **pacb;
83f64091
FB
282 int ret;
283
284 for(;;) {
285 pacb = &first_aio;
286 for(;;) {
287 acb = *pacb;
288 if (!acb)
289 goto the_end;
ce1a14dc 290 ret = aio_error(&acb->aiocb);
83f64091
FB
291 if (ret == ECANCELED) {
292 /* remove the request */
ce1a14dc
PB
293 *pacb = acb->next;
294 qemu_aio_release(acb);
83f64091
FB
295 } else if (ret != EINPROGRESS) {
296 /* end of aio */
297 if (ret == 0) {
ce1a14dc
PB
298 ret = aio_return(&acb->aiocb);
299 if (ret == acb->aiocb.aio_nbytes)
83f64091
FB
300 ret = 0;
301 else
19cb3738 302 ret = -EINVAL;
83f64091
FB
303 } else {
304 ret = -ret;
305 }
306 /* remove the request */
ce1a14dc 307 *pacb = acb->next;
83f64091 308 /* call the callback */
ce1a14dc
PB
309 acb->common.cb(acb->common.opaque, ret);
310 qemu_aio_release(acb);
83f64091
FB
311 break;
312 } else {
ce1a14dc 313 pacb = &acb->next;
83f64091
FB
314 }
315 }
316 }
317 the_end: ;
318}
319
6192bc37
PB
320/* Wait for all IO requests to complete. */
321void qemu_aio_flush(void)
322{
323 qemu_aio_wait_start();
324 qemu_aio_poll();
325 while (first_aio) {
326 qemu_aio_wait();
327 }
328 qemu_aio_wait_end();
329}
330
83f64091
FB
331/* wait until at least one AIO was handled */
332static sigset_t wait_oset;
333
334void qemu_aio_wait_start(void)
335{
336 sigset_t set;
979b67ad
FB
337
338 if (!aio_initialized)
339 qemu_aio_init();
83f64091
FB
340 sigemptyset(&set);
341 sigaddset(&set, aio_sig_num);
342 sigprocmask(SIG_BLOCK, &set, &wait_oset);
343}
344
345void qemu_aio_wait(void)
346{
347 sigset_t set;
348 int nb_sigs;
6eb5733a
FB
349
350#ifndef QEMU_TOOL
351 if (qemu_bh_poll())
352 return;
353#endif
83f64091
FB
354 sigemptyset(&set);
355 sigaddset(&set, aio_sig_num);
356 sigwait(&set, &nb_sigs);
357 qemu_aio_poll();
358}
359
360void qemu_aio_wait_end(void)
361{
362 sigprocmask(SIG_SETMASK, &wait_oset, NULL);
363}
364
ce1a14dc
PB
365static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
366 int64_t sector_num, uint8_t *buf, int nb_sectors,
367 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 368{
ce1a14dc
PB
369 BDRVRawState *s = bs->opaque;
370 RawAIOCB *acb;
371
19cb3738
FB
372 if (fd_open(bs) < 0)
373 return NULL;
374
ce1a14dc
PB
375 acb = qemu_aio_get(bs, cb, opaque);
376 if (!acb)
377 return NULL;
378 acb->aiocb.aio_fildes = s->fd;
379 acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
380 acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
381 acb->aiocb.aio_buf = buf;
382 acb->aiocb.aio_nbytes = nb_sectors * 512;
383 acb->aiocb.aio_offset = sector_num * 512;
384 acb->next = first_aio;
385 first_aio = acb;
386 return acb;
83f64091
FB
387}
388
ce1a14dc
PB
389static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
390 int64_t sector_num, uint8_t *buf, int nb_sectors,
391 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 392{
ce1a14dc 393 RawAIOCB *acb;
83f64091 394
ce1a14dc
PB
395 acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
396 if (!acb)
397 return NULL;
398 if (aio_read(&acb->aiocb) < 0) {
399 qemu_aio_release(acb);
400 return NULL;
5fafdf24 401 }
ce1a14dc 402 return &acb->common;
83f64091
FB
403}
404
ce1a14dc
PB
405static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
406 int64_t sector_num, const uint8_t *buf, int nb_sectors,
407 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 408{
ce1a14dc 409 RawAIOCB *acb;
83f64091 410
ce1a14dc
PB
411 acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
412 if (!acb)
413 return NULL;
414 if (aio_write(&acb->aiocb) < 0) {
415 qemu_aio_release(acb);
416 return NULL;
5fafdf24 417 }
ce1a14dc 418 return &acb->common;
83f64091
FB
419}
420
ce1a14dc 421static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
83f64091 422{
83f64091 423 int ret;
ce1a14dc
PB
424 RawAIOCB *acb = (RawAIOCB *)blockacb;
425 RawAIOCB **pacb;
83f64091 426
ce1a14dc 427 ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
83f64091
FB
428 if (ret == AIO_NOTCANCELED) {
429 /* fail safe: if the aio could not be canceled, we wait for
430 it */
ce1a14dc 431 while (aio_error(&acb->aiocb) == EINPROGRESS);
83f64091
FB
432 }
433
434 /* remove the callback from the queue */
435 pacb = &first_aio;
436 for(;;) {
437 if (*pacb == NULL) {
438 break;
439 } else if (*pacb == acb) {
ce1a14dc
PB
440 *pacb = acb->next;
441 qemu_aio_release(acb);
83f64091
FB
442 break;
443 }
ce1a14dc 444 pacb = &acb->next;
83f64091
FB
445 }
446}
447
83f64091
FB
448static void raw_close(BlockDriverState *bs)
449{
450 BDRVRawState *s = bs->opaque;
19cb3738
FB
451 if (s->fd >= 0) {
452 close(s->fd);
453 s->fd = -1;
454 }
83f64091
FB
455}
456
457static int raw_truncate(BlockDriverState *bs, int64_t offset)
458{
459 BDRVRawState *s = bs->opaque;
19cb3738
FB
460 if (s->type != FTYPE_FILE)
461 return -ENOTSUP;
83f64091
FB
462 if (ftruncate(s->fd, offset) < 0)
463 return -errno;
464 return 0;
465}
466
467static int64_t raw_getlength(BlockDriverState *bs)
468{
469 BDRVRawState *s = bs->opaque;
470 int fd = s->fd;
471 int64_t size;
472#ifdef _BSD
473 struct stat sb;
474#endif
475#ifdef __sun__
476 struct dk_minfo minfo;
477 int rv;
478#endif
19cb3738
FB
479 int ret;
480
481 ret = fd_open(bs);
482 if (ret < 0)
483 return ret;
83f64091
FB
484
485#ifdef _BSD
486 if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
487#ifdef DIOCGMEDIASIZE
488 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
489#endif
490#ifdef CONFIG_COCOA
491 size = LONG_LONG_MAX;
492#else
493 size = lseek(fd, 0LL, SEEK_END);
494#endif
495 } else
496#endif
497#ifdef __sun__
498 /*
499 * use the DKIOCGMEDIAINFO ioctl to read the size.
500 */
501 rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
502 if ( rv != -1 ) {
503 size = minfo.dki_lbsize * minfo.dki_capacity;
504 } else /* there are reports that lseek on some devices
505 fails, but irc discussion said that contingency
506 on contingency was overkill */
507#endif
508 {
509 size = lseek(fd, 0, SEEK_END);
510 }
83f64091
FB
511 return size;
512}
513
514static int raw_create(const char *filename, int64_t total_size,
515 const char *backing_file, int flags)
516{
517 int fd;
518
519 if (flags || backing_file)
520 return -ENOTSUP;
521
5fafdf24 522 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
83f64091
FB
523 0644);
524 if (fd < 0)
525 return -EIO;
526 ftruncate(fd, total_size * 512);
527 close(fd);
528 return 0;
529}
530
531static void raw_flush(BlockDriverState *bs)
532{
533 BDRVRawState *s = bs->opaque;
534 fsync(s->fd);
535}
536
537BlockDriver bdrv_raw = {
538 "raw",
539 sizeof(BDRVRawState),
540 NULL, /* no probe for protocols */
541 raw_open,
542 NULL,
543 NULL,
544 raw_close,
545 raw_create,
546 raw_flush,
3b46e624 547
83f64091
FB
548 .bdrv_aio_read = raw_aio_read,
549 .bdrv_aio_write = raw_aio_write,
550 .bdrv_aio_cancel = raw_aio_cancel,
ce1a14dc 551 .aiocb_size = sizeof(RawAIOCB),
83f64091
FB
552 .protocol_name = "file",
553 .bdrv_pread = raw_pread,
554 .bdrv_pwrite = raw_pwrite,
555 .bdrv_truncate = raw_truncate,
556 .bdrv_getlength = raw_getlength,
557};
558
19cb3738
FB
559/***********************************************/
560/* host device */
561
562#ifdef CONFIG_COCOA
563static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
564static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
565
566kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
567{
5fafdf24 568 kern_return_t kernResult;
19cb3738
FB
569 mach_port_t masterPort;
570 CFMutableDictionaryRef classesToMatch;
571
572 kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
573 if ( KERN_SUCCESS != kernResult ) {
574 printf( "IOMasterPort returned %d\n", kernResult );
575 }
3b46e624 576
5fafdf24 577 classesToMatch = IOServiceMatching( kIOCDMediaClass );
19cb3738
FB
578 if ( classesToMatch == NULL ) {
579 printf( "IOServiceMatching returned a NULL dictionary.\n" );
580 } else {
581 CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
582 }
583 kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
584 if ( KERN_SUCCESS != kernResult )
585 {
586 printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
587 }
3b46e624 588
19cb3738
FB
589 return kernResult;
590}
591
592kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
593{
594 io_object_t nextMedia;
595 kern_return_t kernResult = KERN_FAILURE;
596 *bsdPath = '\0';
597 nextMedia = IOIteratorNext( mediaIterator );
598 if ( nextMedia )
599 {
600 CFTypeRef bsdPathAsCFString;
601 bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
602 if ( bsdPathAsCFString ) {
603 size_t devPathLength;
604 strcpy( bsdPath, _PATH_DEV );
605 strcat( bsdPath, "r" );
606 devPathLength = strlen( bsdPath );
607 if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
608 kernResult = KERN_SUCCESS;
609 }
610 CFRelease( bsdPathAsCFString );
611 }
612 IOObjectRelease( nextMedia );
613 }
3b46e624 614
19cb3738
FB
615 return kernResult;
616}
617
618#endif
619
620static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
621{
622 BDRVRawState *s = bs->opaque;
623 int fd, open_flags, ret;
624
625#ifdef CONFIG_COCOA
626 if (strstart(filename, "/dev/cdrom", NULL)) {
627 kern_return_t kernResult;
628 io_iterator_t mediaIterator;
629 char bsdPath[ MAXPATHLEN ];
630 int fd;
5fafdf24 631
19cb3738
FB
632 kernResult = FindEjectableCDMedia( &mediaIterator );
633 kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
3b46e624 634
19cb3738
FB
635 if ( bsdPath[ 0 ] != '\0' ) {
636 strcat(bsdPath,"s0");
637 /* some CDs don't have a partition 0 */
638 fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
639 if (fd < 0) {
640 bsdPath[strlen(bsdPath)-1] = '1';
641 } else {
642 close(fd);
643 }
644 filename = bsdPath;
645 }
3b46e624 646
19cb3738
FB
647 if ( mediaIterator )
648 IOObjectRelease( mediaIterator );
649 }
650#endif
651 open_flags = O_BINARY;
652 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
653 open_flags |= O_RDWR;
654 } else {
655 open_flags |= O_RDONLY;
656 bs->read_only = 1;
657 }
658
659 s->type = FTYPE_FILE;
660#if defined(__linux__)
661 if (strstart(filename, "/dev/cd", NULL)) {
662 /* open will not fail even if no CD is inserted */
663 open_flags |= O_NONBLOCK;
664 s->type = FTYPE_CD;
665 } else if (strstart(filename, "/dev/fd", NULL)) {
666 s->type = FTYPE_FD;
667 s->fd_open_flags = open_flags;
668 /* open will not fail even if no floppy is inserted */
669 open_flags |= O_NONBLOCK;
670 }
671#endif
672 fd = open(filename, open_flags, 0644);
673 if (fd < 0) {
674 ret = -errno;
675 if (ret == -EROFS)
676 ret = -EACCES;
677 return ret;
678 }
679 s->fd = fd;
680#if defined(__linux__)
681 /* close fd so that we can reopen it as needed */
682 if (s->type == FTYPE_FD) {
683 close(s->fd);
684 s->fd = -1;
685 s->fd_media_changed = 1;
686 }
687#endif
688 return 0;
689}
690
691#if defined(__linux__) && !defined(QEMU_TOOL)
692
693/* Note: we do not have a reliable method to detect if the floppy is
694 present. The current method is to try to open the floppy at every
695 I/O and to keep it opened during a few hundreds of ms. */
696static int fd_open(BlockDriverState *bs)
697{
698 BDRVRawState *s = bs->opaque;
699 int last_media_present;
700
701 if (s->type != FTYPE_FD)
702 return 0;
703 last_media_present = (s->fd >= 0);
5fafdf24 704 if (s->fd >= 0 &&
19cb3738
FB
705 (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
706 close(s->fd);
707 s->fd = -1;
708#ifdef DEBUG_FLOPPY
709 printf("Floppy closed\n");
710#endif
711 }
712 if (s->fd < 0) {
5fafdf24 713 if (s->fd_got_error &&
19cb3738
FB
714 (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
715#ifdef DEBUG_FLOPPY
716 printf("No floppy (open delayed)\n");
717#endif
718 return -EIO;
719 }
720 s->fd = open(bs->filename, s->fd_open_flags);
721 if (s->fd < 0) {
722 s->fd_error_time = qemu_get_clock(rt_clock);
723 s->fd_got_error = 1;
724 if (last_media_present)
725 s->fd_media_changed = 1;
726#ifdef DEBUG_FLOPPY
727 printf("No floppy\n");
728#endif
729 return -EIO;
730 }
731#ifdef DEBUG_FLOPPY
732 printf("Floppy opened\n");
733#endif
734 }
735 if (!last_media_present)
736 s->fd_media_changed = 1;
737 s->fd_open_time = qemu_get_clock(rt_clock);
738 s->fd_got_error = 0;
739 return 0;
740}
741#else
742static int fd_open(BlockDriverState *bs)
743{
744 return 0;
745}
746#endif
747
748#if defined(__linux__)
749
750static int raw_is_inserted(BlockDriverState *bs)
751{
752 BDRVRawState *s = bs->opaque;
753 int ret;
754
755 switch(s->type) {
756 case FTYPE_CD:
757 ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
758 if (ret == CDS_DISC_OK)
759 return 1;
760 else
761 return 0;
762 break;
763 case FTYPE_FD:
764 ret = fd_open(bs);
765 return (ret >= 0);
766 default:
767 return 1;
768 }
769}
770
771/* currently only used by fdc.c, but a CD version would be good too */
772static int raw_media_changed(BlockDriverState *bs)
773{
774 BDRVRawState *s = bs->opaque;
775
776 switch(s->type) {
777 case FTYPE_FD:
778 {
779 int ret;
780 /* XXX: we do not have a true media changed indication. It
781 does not work if the floppy is changed without trying
782 to read it */
783 fd_open(bs);
784 ret = s->fd_media_changed;
785 s->fd_media_changed = 0;
786#ifdef DEBUG_FLOPPY
787 printf("Floppy changed=%d\n", ret);
788#endif
789 return ret;
790 }
791 default:
792 return -ENOTSUP;
793 }
794}
795
796static int raw_eject(BlockDriverState *bs, int eject_flag)
797{
798 BDRVRawState *s = bs->opaque;
799
800 switch(s->type) {
801 case FTYPE_CD:
802 if (eject_flag) {
803 if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
804 perror("CDROMEJECT");
805 } else {
806 if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
807 perror("CDROMEJECT");
808 }
809 break;
810 case FTYPE_FD:
811 {
812 int fd;
813 if (s->fd >= 0) {
814 close(s->fd);
815 s->fd = -1;
816 }
817 fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
818 if (fd >= 0) {
819 if (ioctl(fd, FDEJECT, 0) < 0)
820 perror("FDEJECT");
821 close(fd);
822 }
823 }
824 break;
825 default:
826 return -ENOTSUP;
827 }
828 return 0;
829}
830
831static int raw_set_locked(BlockDriverState *bs, int locked)
832{
833 BDRVRawState *s = bs->opaque;
834
835 switch(s->type) {
836 case FTYPE_CD:
837 if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
838 /* Note: an error can happen if the distribution automatically
839 mounts the CD-ROM */
840 // perror("CDROM_LOCKDOOR");
841 }
842 break;
843 default:
844 return -ENOTSUP;
845 }
846 return 0;
847}
848
849#else
850
851static int raw_is_inserted(BlockDriverState *bs)
852{
853 return 1;
854}
855
856static int raw_media_changed(BlockDriverState *bs)
857{
858 return -ENOTSUP;
859}
860
861static int raw_eject(BlockDriverState *bs, int eject_flag)
862{
863 return -ENOTSUP;
864}
865
866static int raw_set_locked(BlockDriverState *bs, int locked)
867{
868 return -ENOTSUP;
869}
870
871#endif /* !linux */
872
873BlockDriver bdrv_host_device = {
874 "host_device",
875 sizeof(BDRVRawState),
876 NULL, /* no probe for protocols */
877 hdev_open,
878 NULL,
879 NULL,
880 raw_close,
881 NULL,
882 raw_flush,
3b46e624 883
19cb3738
FB
884 .bdrv_aio_read = raw_aio_read,
885 .bdrv_aio_write = raw_aio_write,
886 .bdrv_aio_cancel = raw_aio_cancel,
887 .aiocb_size = sizeof(RawAIOCB),
888 .bdrv_pread = raw_pread,
889 .bdrv_pwrite = raw_pwrite,
890 .bdrv_getlength = raw_getlength,
891
892 /* removable device support */
893 .bdrv_is_inserted = raw_is_inserted,
894 .bdrv_media_changed = raw_media_changed,
895 .bdrv_eject = raw_eject,
896 .bdrv_set_locked = raw_set_locked,
897};
898
83f64091
FB
899#else /* _WIN32 */
900
901/* XXX: use another file ? */
83f64091
FB
902#include <winioctl.h>
903
19cb3738
FB
904#define FTYPE_FILE 0
905#define FTYPE_CD 1
01781963 906#define FTYPE_HARDDISK 2
19cb3738 907
83f64091
FB
908typedef struct BDRVRawState {
909 HANDLE hfile;
19cb3738 910 int type;
f45512fe 911 char drive_path[16]; /* format: "d:\" */
83f64091
FB
912} BDRVRawState;
913
914typedef struct RawAIOCB {
ce1a14dc 915 BlockDriverAIOCB common;
83f64091
FB
916 HANDLE hEvent;
917 OVERLAPPED ov;
918 int count;
919} RawAIOCB;
920
921int qemu_ftruncate64(int fd, int64_t length)
922{
923 LARGE_INTEGER li;
924 LONG high;
925 HANDLE h;
926 BOOL res;
927
928 if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
929 return -1;
930
931 h = (HANDLE)_get_osfhandle(fd);
932
933 /* get current position, ftruncate do not change position */
934 li.HighPart = 0;
935 li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
936 if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
937 return -1;
938
939 high = length >> 32;
940 if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
941 return -1;
942 res = SetEndOfFile(h);
943
944 /* back to old position */
945 SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
946 return res ? 0 : -1;
947}
948
949static int set_sparse(int fd)
950{
951 DWORD returned;
952 return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
953 NULL, 0, NULL, 0, &returned, NULL);
954}
955
956static int raw_open(BlockDriverState *bs, const char *filename, int flags)
957{
958 BDRVRawState *s = bs->opaque;
959 int access_flags, create_flags;
ce1a14dc 960 DWORD overlapped;
19cb3738 961
f45512fe 962 s->type = FTYPE_FILE;
83f64091
FB
963
964 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
965 access_flags = GENERIC_READ | GENERIC_WRITE;
966 } else {
967 access_flags = GENERIC_READ;
968 }
979b67ad 969 if (flags & BDRV_O_CREAT) {
83f64091
FB
970 create_flags = CREATE_ALWAYS;
971 } else {
972 create_flags = OPEN_EXISTING;
973 }
ce1a14dc 974#ifdef QEMU_TOOL
3b9f94e1 975 overlapped = FILE_ATTRIBUTE_NORMAL;
ce1a14dc
PB
976#else
977 overlapped = FILE_FLAG_OVERLAPPED;
978#endif
5fafdf24 979 s->hfile = CreateFile(filename, access_flags,
83f64091 980 FILE_SHARE_READ, NULL,
3b9f94e1 981 create_flags, overlapped, NULL);
54421cb1
TS
982 if (s->hfile == INVALID_HANDLE_VALUE) {
983 int err = GetLastError();
984
985 if (err == ERROR_ACCESS_DENIED)
986 return -EACCES;
83f64091 987 return -1;
54421cb1 988 }
83f64091
FB
989 return 0;
990}
991
5fafdf24 992static int raw_pread(BlockDriverState *bs, int64_t offset,
83f64091
FB
993 uint8_t *buf, int count)
994{
995 BDRVRawState *s = bs->opaque;
996 OVERLAPPED ov;
997 DWORD ret_count;
998 int ret;
3b46e624 999
83f64091
FB
1000 memset(&ov, 0, sizeof(ov));
1001 ov.Offset = offset;
1002 ov.OffsetHigh = offset >> 32;
436e15b8
FB
1003 ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
1004 if (!ret) {
1005 ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
1006 if (!ret)
1007 return -EIO;
1008 else
1009 return ret_count;
1010 }
83f64091
FB
1011 return ret_count;
1012}
1013
5fafdf24 1014static int raw_pwrite(BlockDriverState *bs, int64_t offset,
83f64091
FB
1015 const uint8_t *buf, int count)
1016{
1017 BDRVRawState *s = bs->opaque;
1018 OVERLAPPED ov;
1019 DWORD ret_count;
1020 int ret;
3b46e624 1021
83f64091
FB
1022 memset(&ov, 0, sizeof(ov));
1023 ov.Offset = offset;
1024 ov.OffsetHigh = offset >> 32;
436e15b8
FB
1025 ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
1026 if (!ret) {
1027 ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
1028 if (!ret)
1029 return -EIO;
1030 else
1031 return ret_count;
1032 }
83f64091
FB
1033 return ret_count;
1034}
1035
3b9f94e1 1036#if 0
436e15b8 1037#ifndef QEMU_TOOL
83f64091
FB
1038static void raw_aio_cb(void *opaque)
1039{
ce1a14dc
PB
1040 RawAIOCB *acb = opaque;
1041 BlockDriverState *bs = acb->common.bs;
979b67ad 1042 BDRVRawState *s = bs->opaque;
83f64091
FB
1043 DWORD ret_count;
1044 int ret;
1045
ce1a14dc
PB
1046 ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
1047 if (!ret || ret_count != acb->count) {
1048 acb->common.cb(acb->common.opaque, -EIO);
83f64091 1049 } else {
ce1a14dc 1050 acb->common.cb(acb->common.opaque, 0);
83f64091
FB
1051 }
1052}
436e15b8 1053#endif
ce1a14dc
PB
1054
1055static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
1056 int64_t sector_num, uint8_t *buf, int nb_sectors,
1057 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 1058{
ce1a14dc 1059 RawAIOCB *acb;
83f64091
FB
1060 int64_t offset;
1061
ce1a14dc
PB
1062 acb = qemu_aio_get(bs, cb, opaque);
1063 if (acb->hEvent) {
1064 acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1065 if (!acb->hEvent) {
1066 qemu_aio_release(acb);
1067 return NULL;
1068 }
1069 }
1070 memset(&acb->ov, 0, sizeof(acb->ov));
83f64091 1071 offset = sector_num * 512;
ce1a14dc
PB
1072 acb->ov.Offset = offset;
1073 acb->ov.OffsetHigh = offset >> 32;
1074 acb->ov.hEvent = acb->hEvent;
1075 acb->count = nb_sectors * 512;
436e15b8 1076#ifndef QEMU_TOOL
ce1a14dc 1077 qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
436e15b8 1078#endif
ce1a14dc 1079 return acb;
83f64091
FB
1080}
1081
ce1a14dc
PB
1082static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
1083 int64_t sector_num, uint8_t *buf, int nb_sectors,
1084 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 1085{
83f64091 1086 BDRVRawState *s = bs->opaque;
ce1a14dc 1087 RawAIOCB *acb;
83f64091 1088 int ret;
83f64091 1089
ce1a14dc
PB
1090 acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
1091 if (!acb)
1092 return NULL;
1093 ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
1094 if (!ret) {
1095 qemu_aio_release(acb);
1096 return NULL;
1097 }
1098#ifdef QEMU_TOOL
1099 qemu_aio_release(acb);
436e15b8 1100#endif
ce1a14dc 1101 return (BlockDriverAIOCB *)acb;
83f64091
FB
1102}
1103
ce1a14dc
PB
1104static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
1105 int64_t sector_num, uint8_t *buf, int nb_sectors,
1106 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 1107{
83f64091 1108 BDRVRawState *s = bs->opaque;
ce1a14dc
PB
1109 RawAIOCB *acb;
1110 int ret;
83f64091 1111
ce1a14dc
PB
1112 acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
1113 if (!acb)
1114 return NULL;
1115 ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
1116 if (!ret) {
1117 qemu_aio_release(acb);
1118 return NULL;
1119 }
1120#ifdef QEMU_TOOL
1121 qemu_aio_release(acb);
436e15b8 1122#endif
ce1a14dc 1123 return (BlockDriverAIOCB *)acb;
83f64091
FB
1124}
1125
ce1a14dc 1126static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
83f64091 1127{
ce1a14dc
PB
1128#ifndef QEMU_TOOL
1129 RawAIOCB *acb = (RawAIOCB *)blockacb;
1130 BlockDriverState *bs = acb->common.bs;
1131 BDRVRawState *s = bs->opaque;
1132
1133 qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
1134 /* XXX: if more than one async I/O it is not correct */
1135 CancelIo(s->hfile);
1136 qemu_aio_release(acb);
1137#endif
83f64091 1138}
3b9f94e1 1139#endif /* #if 0 */
83f64091
FB
1140
1141static void raw_flush(BlockDriverState *bs)
1142{
3b9f94e1
FB
1143 BDRVRawState *s = bs->opaque;
1144 FlushFileBuffers(s->hfile);
83f64091
FB
1145}
1146
1147static void raw_close(BlockDriverState *bs)
1148{
1149 BDRVRawState *s = bs->opaque;
1150 CloseHandle(s->hfile);
1151}
1152
1153static int raw_truncate(BlockDriverState *bs, int64_t offset)
1154{
1155 BDRVRawState *s = bs->opaque;
1156 DWORD low, high;
1157
979b67ad
FB
1158 low = offset;
1159 high = offset >> 32;
83f64091
FB
1160 if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
1161 return -EIO;
1162 if (!SetEndOfFile(s->hfile))
1163 return -EIO;
1164 return 0;
1165}
1166
f45512fe 1167static int64_t raw_getlength(BlockDriverState *bs)
83f64091
FB
1168{
1169 BDRVRawState *s = bs->opaque;
1170 LARGE_INTEGER l;
5fafdf24 1171 ULARGE_INTEGER available, total, total_free;
01781963
FB
1172 DISK_GEOMETRY dg;
1173 DWORD count;
1174 BOOL status;
436e15b8 1175
f45512fe 1176 switch(s->type) {
19cb3738
FB
1177 case FTYPE_FILE:
1178 l.LowPart = GetFileSize(s->hfile, &l.HighPart);
1179 if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
1180 return -EIO;
1181 break;
1182 case FTYPE_CD:
f45512fe 1183 if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
19cb3738 1184 return -EIO;
f45512fe 1185 l.QuadPart = total.QuadPart;
19cb3738 1186 break;
01781963
FB
1187 case FTYPE_HARDDISK:
1188 status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
1189 NULL, 0, &dg, sizeof(dg), &count, NULL);
1190 if (status != FALSE) {
1191 l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
1192 * dg.SectorsPerTrack * dg.BytesPerSector;
1193 }
1194 break;
19cb3738
FB
1195 default:
1196 return -EIO;
1197 }
83f64091
FB
1198 return l.QuadPart;
1199}
1200
1201static int raw_create(const char *filename, int64_t total_size,
1202 const char *backing_file, int flags)
1203{
1204 int fd;
1205
1206 if (flags || backing_file)
1207 return -ENOTSUP;
1208
5fafdf24 1209 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
83f64091
FB
1210 0644);
1211 if (fd < 0)
1212 return -EIO;
1213 set_sparse(fd);
1214 ftruncate(fd, total_size * 512);
1215 close(fd);
1216 return 0;
1217}
1218
1219void qemu_aio_init(void)
1220{
1221}
1222
1223void qemu_aio_poll(void)
1224{
1225}
1226
62ee0211
TS
1227void qemu_aio_flush(void)
1228{
1229}
1230
83f64091
FB
1231void qemu_aio_wait_start(void)
1232{
1233}
1234
1235void qemu_aio_wait(void)
1236{
fd44d818
FB
1237#ifndef QEMU_TOOL
1238 qemu_bh_poll();
1239#endif
83f64091
FB
1240}
1241
1242void qemu_aio_wait_end(void)
1243{
1244}
1245
1246BlockDriver bdrv_raw = {
1247 "raw",
1248 sizeof(BDRVRawState),
1249 NULL, /* no probe for protocols */
1250 raw_open,
1251 NULL,
1252 NULL,
1253 raw_close,
1254 raw_create,
1255 raw_flush,
3b46e624 1256
83f64091 1257#if 0
83f64091
FB
1258 .bdrv_aio_read = raw_aio_read,
1259 .bdrv_aio_write = raw_aio_write,
1260 .bdrv_aio_cancel = raw_aio_cancel,
ce1a14dc 1261 .aiocb_size = sizeof(RawAIOCB);
83f64091
FB
1262#endif
1263 .protocol_name = "file",
1264 .bdrv_pread = raw_pread,
1265 .bdrv_pwrite = raw_pwrite,
1266 .bdrv_truncate = raw_truncate,
1267 .bdrv_getlength = raw_getlength,
1268};
19cb3738
FB
1269
1270/***********************************************/
1271/* host device */
1272
1273static int find_cdrom(char *cdrom_name, int cdrom_name_size)
1274{
1275 char drives[256], *pdrv = drives;
1276 UINT type;
1277
f45512fe 1278 memset(drives, 0, sizeof(drives));
19cb3738
FB
1279 GetLogicalDriveStrings(sizeof(drives), drives);
1280 while(pdrv[0] != '\0') {
1281 type = GetDriveType(pdrv);
1282 switch(type) {
1283 case DRIVE_CDROM:
1284 snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
1285 return 0;
1286 break;
1287 }
1288 pdrv += lstrlen(pdrv) + 1;
1289 }
1290 return -1;
1291}
1292
f45512fe 1293static int find_device_type(BlockDriverState *bs, const char *filename)
19cb3738 1294{
f45512fe 1295 BDRVRawState *s = bs->opaque;
19cb3738
FB
1296 UINT type;
1297 const char *p;
1298
1299 if (strstart(filename, "\\\\.\\", &p) ||
1300 strstart(filename, "//./", &p)) {
01781963
FB
1301 if (stristart(p, "PhysicalDrive", NULL))
1302 return FTYPE_HARDDISK;
f45512fe
FB
1303 snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
1304 type = GetDriveType(s->drive_path);
19cb3738
FB
1305 if (type == DRIVE_CDROM)
1306 return FTYPE_CD;
1307 else
1308 return FTYPE_FILE;
1309 } else {
1310 return FTYPE_FILE;
1311 }
1312}
1313
1314static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
1315{
1316 BDRVRawState *s = bs->opaque;
1317 int access_flags, create_flags;
1318 DWORD overlapped;
1319 char device_name[64];
19cb3738
FB
1320
1321 if (strstart(filename, "/dev/cdrom", NULL)) {
1322 if (find_cdrom(device_name, sizeof(device_name)) < 0)
1323 return -ENOENT;
1324 filename = device_name;
1325 } else {
1326 /* transform drive letters into device name */
1327 if (((filename[0] >= 'a' && filename[0] <= 'z') ||
1328 (filename[0] >= 'A' && filename[0] <= 'Z')) &&
1329 filename[1] == ':' && filename[2] == '\0') {
1330 snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
1331 filename = device_name;
1332 }
1333 }
f45512fe 1334 s->type = find_device_type(bs, filename);
3b46e624 1335
19cb3738
FB
1336 if ((flags & BDRV_O_ACCESS) == O_RDWR) {
1337 access_flags = GENERIC_READ | GENERIC_WRITE;
1338 } else {
1339 access_flags = GENERIC_READ;
1340 }
1341 create_flags = OPEN_EXISTING;
1342
1343#ifdef QEMU_TOOL
3b9f94e1 1344 overlapped = FILE_ATTRIBUTE_NORMAL;
19cb3738
FB
1345#else
1346 overlapped = FILE_FLAG_OVERLAPPED;
1347#endif
5fafdf24 1348 s->hfile = CreateFile(filename, access_flags,
19cb3738 1349 FILE_SHARE_READ, NULL,
3b9f94e1 1350 create_flags, overlapped, NULL);
54421cb1
TS
1351 if (s->hfile == INVALID_HANDLE_VALUE) {
1352 int err = GetLastError();
1353
1354 if (err == ERROR_ACCESS_DENIED)
1355 return -EACCES;
19cb3738 1356 return -1;
54421cb1 1357 }
19cb3738
FB
1358 return 0;
1359}
1360
1361#if 0
1362/***********************************************/
aa1f17c1 1363/* removable device additional commands */
19cb3738
FB
1364
1365static int raw_is_inserted(BlockDriverState *bs)
1366{
1367 return 1;
1368}
1369
1370static int raw_media_changed(BlockDriverState *bs)
1371{
1372 return -ENOTSUP;
1373}
1374
1375static int raw_eject(BlockDriverState *bs, int eject_flag)
1376{
1377 DWORD ret_count;
1378
1379 if (s->type == FTYPE_FILE)
1380 return -ENOTSUP;
1381 if (eject_flag) {
5fafdf24 1382 DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,
19cb3738
FB
1383 NULL, 0, NULL, 0, &lpBytesReturned, NULL);
1384 } else {
5fafdf24 1385 DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,
19cb3738
FB
1386 NULL, 0, NULL, 0, &lpBytesReturned, NULL);
1387 }
1388}
1389
1390static int raw_set_locked(BlockDriverState *bs, int locked)
1391{
1392 return -ENOTSUP;
1393}
1394#endif
1395
1396BlockDriver bdrv_host_device = {
1397 "host_device",
1398 sizeof(BDRVRawState),
1399 NULL, /* no probe for protocols */
1400 hdev_open,
1401 NULL,
1402 NULL,
1403 raw_close,
1404 NULL,
1405 raw_flush,
3b46e624 1406
19cb3738
FB
1407#if 0
1408 .bdrv_aio_read = raw_aio_read,
1409 .bdrv_aio_write = raw_aio_write,
1410 .bdrv_aio_cancel = raw_aio_cancel,
1411 .aiocb_size = sizeof(RawAIOCB);
1412#endif
1413 .bdrv_pread = raw_pread,
1414 .bdrv_pwrite = raw_pwrite,
1415 .bdrv_getlength = raw_getlength,
1416};
83f64091 1417#endif /* _WIN32 */