Annotation of qemu/block-raw.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com