Annotation of qemu/block-raw.c, revision 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