File:  [Qemu by Fabrice Bellard] / qemu / block-raw-posix.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:47:26 2018 UTC (2 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0091, HEAD
qemu 0.9.1

    1: /*
    2:  * Block driver for RAW files (posix)
    3:  *
    4:  * Copyright (c) 2006 Fabrice Bellard
    5:  *
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: #include "qemu-common.h"
   25: #ifndef QEMU_IMG
   26: #include "qemu-timer.h"
   27: #include "exec-all.h"
   28: #endif
   29: #include "block_int.h"
   30: #include <assert.h>
   31: #include <aio.h>
   32: 
   33: #ifdef CONFIG_COCOA
   34: #include <paths.h>
   35: #include <sys/param.h>
   36: #include <IOKit/IOKitLib.h>
   37: #include <IOKit/IOBSD.h>
   38: #include <IOKit/storage/IOMediaBSDClient.h>
   39: #include <IOKit/storage/IOMedia.h>
   40: #include <IOKit/storage/IOCDMedia.h>
   41: //#include <IOKit/storage/IOCDTypes.h>
   42: #include <CoreFoundation/CoreFoundation.h>
   43: #endif
   44: 
   45: #ifdef __sun__
   46: #define _POSIX_PTHREAD_SEMANTICS 1
   47: #include <signal.h>
   48: #include <sys/dkio.h>
   49: #endif
   50: #ifdef __linux__
   51: #include <sys/ioctl.h>
   52: #include <linux/cdrom.h>
   53: #include <linux/fd.h>
   54: #endif
   55: #ifdef __FreeBSD__
   56: #include <sys/disk.h>
   57: #endif
   58: 
   59: //#define DEBUG_FLOPPY
   60: 
   61: //#define DEBUG_BLOCK
   62: #if defined(DEBUG_BLOCK) && !defined(QEMU_IMG)
   63: #define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)	\
   64:     { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
   65: #else
   66: #define DEBUG_BLOCK_PRINT(formatCstr, args...)
   67: #endif
   68: 
   69: #define FTYPE_FILE   0
   70: #define FTYPE_CD     1
   71: #define FTYPE_FD     2
   72: 
   73: /* if the FD is not accessed during that time (in ms), we try to
   74:    reopen it to see if the disk has been changed */
   75: #define FD_OPEN_TIMEOUT 1000
   76: 
   77: typedef struct BDRVRawState {
   78:     int fd;
   79:     int type;
   80:     unsigned int lseek_err_cnt;
   81: #if defined(__linux__)
   82:     /* linux floppy specific */
   83:     int fd_open_flags;
   84:     int64_t fd_open_time;
   85:     int64_t fd_error_time;
   86:     int fd_got_error;
   87:     int fd_media_changed;
   88: #endif
   89: } BDRVRawState;
   90: 
   91: static int fd_open(BlockDriverState *bs);
   92: 
   93: static int raw_open(BlockDriverState *bs, const char *filename, int flags)
   94: {
   95:     BDRVRawState *s = bs->opaque;
   96:     int fd, open_flags, ret;
   97: 
   98:     s->lseek_err_cnt = 0;
   99: 
  100:     open_flags = O_BINARY;
  101:     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  102:         open_flags |= O_RDWR;
  103:     } else {
  104:         open_flags |= O_RDONLY;
  105:         bs->read_only = 1;
  106:     }
  107:     if (flags & BDRV_O_CREAT)
  108:         open_flags |= O_CREAT | O_TRUNC;
  109: #ifdef O_DIRECT
  110:     if (flags & BDRV_O_DIRECT)
  111:         open_flags |= O_DIRECT;
  112: #endif
  113: 
  114:     s->type = FTYPE_FILE;
  115: 
  116:     fd = open(filename, open_flags, 0644);
  117:     if (fd < 0) {
  118:         ret = -errno;
  119:         if (ret == -EROFS)
  120:             ret = -EACCES;
  121:         return ret;
  122:     }
  123:     s->fd = fd;
  124:     return 0;
  125: }
  126: 
  127: /* XXX: use host sector size if necessary with:
  128: #ifdef DIOCGSECTORSIZE
  129:         {
  130:             unsigned int sectorsize = 512;
  131:             if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  132:                 sectorsize > bufsize)
  133:                 bufsize = sectorsize;
  134:         }
  135: #endif
  136: #ifdef CONFIG_COCOA
  137:         u_int32_t   blockSize = 512;
  138:         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
  139:             bufsize = blockSize;
  140:         }
  141: #endif
  142: */
  143: 
  144: static int raw_pread(BlockDriverState *bs, int64_t offset,
  145:                      uint8_t *buf, int count)
  146: {
  147:     BDRVRawState *s = bs->opaque;
  148:     int ret;
  149: 
  150:     ret = fd_open(bs);
  151:     if (ret < 0)
  152:         return ret;
  153: 
  154:     if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
  155:         ++(s->lseek_err_cnt);
  156:         if(s->lseek_err_cnt <= 10) {
  157:             DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
  158:                               "] lseek failed : %d = %s\n",
  159:                               s->fd, bs->filename, offset, buf, count,
  160:                               bs->total_sectors, errno, strerror(errno));
  161:         }
  162:         return -1;
  163:     }
  164:     s->lseek_err_cnt=0;
  165: 
  166:     ret = read(s->fd, buf, count);
  167:     if (ret == count)
  168:         goto label__raw_read__success;
  169: 
  170:     DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
  171:                       "] read failed %d : %d = %s\n",
  172:                       s->fd, bs->filename, offset, buf, count,
  173:                       bs->total_sectors, ret, errno, strerror(errno));
  174: 
  175:     /* Try harder for CDrom. */
  176:     if (bs->type == BDRV_TYPE_CDROM) {
  177:         lseek(s->fd, offset, SEEK_SET);
  178:         ret = read(s->fd, buf, count);
  179:         if (ret == count)
  180:             goto label__raw_read__success;
  181:         lseek(s->fd, offset, SEEK_SET);
  182:         ret = read(s->fd, buf, count);
  183:         if (ret == count)
  184:             goto label__raw_read__success;
  185: 
  186:         DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
  187:                           "] retry read failed %d : %d = %s\n",
  188:                           s->fd, bs->filename, offset, buf, count,
  189:                           bs->total_sectors, ret, errno, strerror(errno));
  190:     }
  191: 
  192: label__raw_read__success:
  193: 
  194:     return ret;
  195: }
  196: 
  197: static int raw_pwrite(BlockDriverState *bs, int64_t offset,
  198:                       const uint8_t *buf, int count)
  199: {
  200:     BDRVRawState *s = bs->opaque;
  201:     int ret;
  202: 
  203:     ret = fd_open(bs);
  204:     if (ret < 0)
  205:         return ret;
  206: 
  207:     if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
  208:         ++(s->lseek_err_cnt);
  209:         if(s->lseek_err_cnt) {
  210:             DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
  211:                               PRId64 "] lseek failed : %d = %s\n",
  212:                               s->fd, bs->filename, offset, buf, count,
  213:                               bs->total_sectors, errno, strerror(errno));
  214:         }
  215:         return -1;
  216:     }
  217:     s->lseek_err_cnt = 0;
  218: 
  219:     ret = write(s->fd, buf, count);
  220:     if (ret == count)
  221:         goto label__raw_write__success;
  222: 
  223:     DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
  224:                       "] write failed %d : %d = %s\n",
  225:                       s->fd, bs->filename, offset, buf, count,
  226:                       bs->total_sectors, ret, errno, strerror(errno));
  227: 
  228: label__raw_write__success:
  229: 
  230:     return ret;
  231: }
  232: 
  233: /***********************************************************/
  234: /* Unix AIO using POSIX AIO */
  235: 
  236: typedef struct RawAIOCB {
  237:     BlockDriverAIOCB common;
  238:     struct aiocb aiocb;
  239:     struct RawAIOCB *next;
  240: } RawAIOCB;
  241: 
  242: static int aio_sig_num = SIGUSR2;
  243: static RawAIOCB *first_aio; /* AIO issued */
  244: static int aio_initialized = 0;
  245: 
  246: static void aio_signal_handler(int signum)
  247: {
  248: #ifndef QEMU_IMG
  249:     CPUState *env = cpu_single_env;
  250:     if (env) {
  251:         /* stop the currently executing cpu because a timer occured */
  252:         cpu_interrupt(env, CPU_INTERRUPT_EXIT);
  253: #ifdef USE_KQEMU
  254:         if (env->kqemu_enabled) {
  255:             kqemu_cpu_interrupt(env);
  256:         }
  257: #endif
  258:     }
  259: #endif
  260: }
  261: 
  262: void qemu_aio_init(void)
  263: {
  264:     struct sigaction act;
  265: 
  266:     aio_initialized = 1;
  267: 
  268:     sigfillset(&act.sa_mask);
  269:     act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
  270:     act.sa_handler = aio_signal_handler;
  271:     sigaction(aio_sig_num, &act, NULL);
  272: 
  273: #if defined(__GLIBC__) && defined(__linux__)
  274:     {
  275:         /* XXX: aio thread exit seems to hang on RedHat 9 and this init
  276:            seems to fix the problem. */
  277:         struct aioinit ai;
  278:         memset(&ai, 0, sizeof(ai));
  279:         ai.aio_threads = 1;
  280:         ai.aio_num = 1;
  281:         ai.aio_idle_time = 365 * 100000;
  282:         aio_init(&ai);
  283:     }
  284: #endif
  285: }
  286: 
  287: void qemu_aio_poll(void)
  288: {
  289:     RawAIOCB *acb, **pacb;
  290:     int ret;
  291: 
  292:     for(;;) {
  293:         pacb = &first_aio;
  294:         for(;;) {
  295:             acb = *pacb;
  296:             if (!acb)
  297:                 goto the_end;
  298:             ret = aio_error(&acb->aiocb);
  299:             if (ret == ECANCELED) {
  300:                 /* remove the request */
  301:                 *pacb = acb->next;
  302:                 qemu_aio_release(acb);
  303:             } else if (ret != EINPROGRESS) {
  304:                 /* end of aio */
  305:                 if (ret == 0) {
  306:                     ret = aio_return(&acb->aiocb);
  307:                     if (ret == acb->aiocb.aio_nbytes)
  308:                         ret = 0;
  309:                     else
  310:                         ret = -EINVAL;
  311:                 } else {
  312:                     ret = -ret;
  313:                 }
  314:                 /* remove the request */
  315:                 *pacb = acb->next;
  316:                 /* call the callback */
  317:                 acb->common.cb(acb->common.opaque, ret);
  318:                 qemu_aio_release(acb);
  319:                 break;
  320:             } else {
  321:                 pacb = &acb->next;
  322:             }
  323:         }
  324:     }
  325:  the_end: ;
  326: }
  327: 
  328: /* Wait for all IO requests to complete.  */
  329: void qemu_aio_flush(void)
  330: {
  331:     qemu_aio_wait_start();
  332:     qemu_aio_poll();
  333:     while (first_aio) {
  334:         qemu_aio_wait();
  335:     }
  336:     qemu_aio_wait_end();
  337: }
  338: 
  339: /* wait until at least one AIO was handled */
  340: static sigset_t wait_oset;
  341: 
  342: void qemu_aio_wait_start(void)
  343: {
  344:     sigset_t set;
  345: 
  346:     if (!aio_initialized)
  347:         qemu_aio_init();
  348:     sigemptyset(&set);
  349:     sigaddset(&set, aio_sig_num);
  350:     sigprocmask(SIG_BLOCK, &set, &wait_oset);
  351: }
  352: 
  353: void qemu_aio_wait(void)
  354: {
  355:     sigset_t set;
  356:     int nb_sigs;
  357: 
  358: #ifndef QEMU_IMG
  359:     if (qemu_bh_poll())
  360:         return;
  361: #endif
  362:     sigemptyset(&set);
  363:     sigaddset(&set, aio_sig_num);
  364:     sigwait(&set, &nb_sigs);
  365:     qemu_aio_poll();
  366: }
  367: 
  368: void qemu_aio_wait_end(void)
  369: {
  370:     sigprocmask(SIG_SETMASK, &wait_oset, NULL);
  371: }
  372: 
  373: static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  374:         int64_t sector_num, uint8_t *buf, int nb_sectors,
  375:         BlockDriverCompletionFunc *cb, void *opaque)
  376: {
  377:     BDRVRawState *s = bs->opaque;
  378:     RawAIOCB *acb;
  379: 
  380:     if (fd_open(bs) < 0)
  381:         return NULL;
  382: 
  383:     acb = qemu_aio_get(bs, cb, opaque);
  384:     if (!acb)
  385:         return NULL;
  386:     acb->aiocb.aio_fildes = s->fd;
  387:     acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
  388:     acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  389:     acb->aiocb.aio_buf = buf;
  390:     if (nb_sectors < 0)
  391:         acb->aiocb.aio_nbytes = -nb_sectors;
  392:     else
  393:         acb->aiocb.aio_nbytes = nb_sectors * 512;
  394:     acb->aiocb.aio_offset = sector_num * 512;
  395:     acb->next = first_aio;
  396:     first_aio = acb;
  397:     return acb;
  398: }
  399: 
  400: static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
  401:         int64_t sector_num, uint8_t *buf, int nb_sectors,
  402:         BlockDriverCompletionFunc *cb, void *opaque)
  403: {
  404:     RawAIOCB *acb;
  405: 
  406:     acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  407:     if (!acb)
  408:         return NULL;
  409:     if (aio_read(&acb->aiocb) < 0) {
  410:         qemu_aio_release(acb);
  411:         return NULL;
  412:     }
  413:     return &acb->common;
  414: }
  415: 
  416: static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
  417:         int64_t sector_num, const uint8_t *buf, int nb_sectors,
  418:         BlockDriverCompletionFunc *cb, void *opaque)
  419: {
  420:     RawAIOCB *acb;
  421: 
  422:     acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
  423:     if (!acb)
  424:         return NULL;
  425:     if (aio_write(&acb->aiocb) < 0) {
  426:         qemu_aio_release(acb);
  427:         return NULL;
  428:     }
  429:     return &acb->common;
  430: }
  431: 
  432: static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
  433: {
  434:     int ret;
  435:     RawAIOCB *acb = (RawAIOCB *)blockacb;
  436:     RawAIOCB **pacb;
  437: 
  438:     ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
  439:     if (ret == AIO_NOTCANCELED) {
  440:         /* fail safe: if the aio could not be canceled, we wait for
  441:            it */
  442:         while (aio_error(&acb->aiocb) == EINPROGRESS);
  443:     }
  444: 
  445:     /* remove the callback from the queue */
  446:     pacb = &first_aio;
  447:     for(;;) {
  448:         if (*pacb == NULL) {
  449:             break;
  450:         } else if (*pacb == acb) {
  451:             *pacb = acb->next;
  452:             qemu_aio_release(acb);
  453:             break;
  454:         }
  455:         pacb = &acb->next;
  456:     }
  457: }
  458: 
  459: static void raw_close(BlockDriverState *bs)
  460: {
  461:     BDRVRawState *s = bs->opaque;
  462:     if (s->fd >= 0) {
  463:         close(s->fd);
  464:         s->fd = -1;
  465:     }
  466: }
  467: 
  468: static int raw_truncate(BlockDriverState *bs, int64_t offset)
  469: {
  470:     BDRVRawState *s = bs->opaque;
  471:     if (s->type != FTYPE_FILE)
  472:         return -ENOTSUP;
  473:     if (ftruncate(s->fd, offset) < 0)
  474:         return -errno;
  475:     return 0;
  476: }
  477: 
  478: static int64_t  raw_getlength(BlockDriverState *bs)
  479: {
  480:     BDRVRawState *s = bs->opaque;
  481:     int fd = s->fd;
  482:     int64_t size;
  483: #ifdef _BSD
  484:     struct stat sb;
  485: #endif
  486: #ifdef __sun__
  487:     struct dk_minfo minfo;
  488:     int rv;
  489: #endif
  490:     int ret;
  491: 
  492:     ret = fd_open(bs);
  493:     if (ret < 0)
  494:         return ret;
  495: 
  496: #ifdef _BSD
  497:     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
  498: #ifdef DIOCGMEDIASIZE
  499: 	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
  500: #endif
  501: #ifdef CONFIG_COCOA
  502:         size = LONG_LONG_MAX;
  503: #else
  504:         size = lseek(fd, 0LL, SEEK_END);
  505: #endif
  506:     } else
  507: #endif
  508: #ifdef __sun__
  509:     /*
  510:      * use the DKIOCGMEDIAINFO ioctl to read the size.
  511:      */
  512:     rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
  513:     if ( rv != -1 ) {
  514:         size = minfo.dki_lbsize * minfo.dki_capacity;
  515:     } else /* there are reports that lseek on some devices
  516:               fails, but irc discussion said that contingency
  517:               on contingency was overkill */
  518: #endif
  519:     {
  520:         size = lseek(fd, 0, SEEK_END);
  521:     }
  522:     return size;
  523: }
  524: 
  525: static int raw_create(const char *filename, int64_t total_size,
  526:                       const char *backing_file, int flags)
  527: {
  528:     int fd;
  529: 
  530:     if (flags || backing_file)
  531:         return -ENOTSUP;
  532: 
  533:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
  534:               0644);
  535:     if (fd < 0)
  536:         return -EIO;
  537:     ftruncate(fd, total_size * 512);
  538:     close(fd);
  539:     return 0;
  540: }
  541: 
  542: static void raw_flush(BlockDriverState *bs)
  543: {
  544:     BDRVRawState *s = bs->opaque;
  545:     fsync(s->fd);
  546: }
  547: 
  548: BlockDriver bdrv_raw = {
  549:     "raw",
  550:     sizeof(BDRVRawState),
  551:     NULL, /* no probe for protocols */
  552:     raw_open,
  553:     NULL,
  554:     NULL,
  555:     raw_close,
  556:     raw_create,
  557:     raw_flush,
  558: 
  559:     .bdrv_aio_read = raw_aio_read,
  560:     .bdrv_aio_write = raw_aio_write,
  561:     .bdrv_aio_cancel = raw_aio_cancel,
  562:     .aiocb_size = sizeof(RawAIOCB),
  563:     .protocol_name = "file",
  564:     .bdrv_pread = raw_pread,
  565:     .bdrv_pwrite = raw_pwrite,
  566:     .bdrv_truncate = raw_truncate,
  567:     .bdrv_getlength = raw_getlength,
  568: };
  569: 
  570: /***********************************************/
  571: /* host device */
  572: 
  573: #ifdef CONFIG_COCOA
  574: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
  575: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
  576: 
  577: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
  578: {
  579:     kern_return_t       kernResult;
  580:     mach_port_t     masterPort;
  581:     CFMutableDictionaryRef  classesToMatch;
  582: 
  583:     kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
  584:     if ( KERN_SUCCESS != kernResult ) {
  585:         printf( "IOMasterPort returned %d\n", kernResult );
  586:     }
  587: 
  588:     classesToMatch = IOServiceMatching( kIOCDMediaClass );
  589:     if ( classesToMatch == NULL ) {
  590:         printf( "IOServiceMatching returned a NULL dictionary.\n" );
  591:     } else {
  592:     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
  593:     }
  594:     kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
  595:     if ( KERN_SUCCESS != kernResult )
  596:     {
  597:         printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
  598:     }
  599: 
  600:     return kernResult;
  601: }
  602: 
  603: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
  604: {
  605:     io_object_t     nextMedia;
  606:     kern_return_t   kernResult = KERN_FAILURE;
  607:     *bsdPath = '\0';
  608:     nextMedia = IOIteratorNext( mediaIterator );
  609:     if ( nextMedia )
  610:     {
  611:         CFTypeRef   bsdPathAsCFString;
  612:     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
  613:         if ( bsdPathAsCFString ) {
  614:             size_t devPathLength;
  615:             strcpy( bsdPath, _PATH_DEV );
  616:             strcat( bsdPath, "r" );
  617:             devPathLength = strlen( bsdPath );
  618:             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
  619:                 kernResult = KERN_SUCCESS;
  620:             }
  621:             CFRelease( bsdPathAsCFString );
  622:         }
  623:         IOObjectRelease( nextMedia );
  624:     }
  625: 
  626:     return kernResult;
  627: }
  628: 
  629: #endif
  630: 
  631: static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
  632: {
  633:     BDRVRawState *s = bs->opaque;
  634:     int fd, open_flags, ret;
  635: 
  636: #ifdef CONFIG_COCOA
  637:     if (strstart(filename, "/dev/cdrom", NULL)) {
  638:         kern_return_t kernResult;
  639:         io_iterator_t mediaIterator;
  640:         char bsdPath[ MAXPATHLEN ];
  641:         int fd;
  642: 
  643:         kernResult = FindEjectableCDMedia( &mediaIterator );
  644:         kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
  645: 
  646:         if ( bsdPath[ 0 ] != '\0' ) {
  647:             strcat(bsdPath,"s0");
  648:             /* some CDs don't have a partition 0 */
  649:             fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
  650:             if (fd < 0) {
  651:                 bsdPath[strlen(bsdPath)-1] = '1';
  652:             } else {
  653:                 close(fd);
  654:             }
  655:             filename = bsdPath;
  656:         }
  657: 
  658:         if ( mediaIterator )
  659:             IOObjectRelease( mediaIterator );
  660:     }
  661: #endif
  662:     open_flags = O_BINARY;
  663:     if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  664:         open_flags |= O_RDWR;
  665:     } else {
  666:         open_flags |= O_RDONLY;
  667:         bs->read_only = 1;
  668:     }
  669: #ifdef O_DIRECT
  670:     if (flags & BDRV_O_DIRECT)
  671:         open_flags |= O_DIRECT;
  672: #endif
  673: 
  674:     s->type = FTYPE_FILE;
  675: #if defined(__linux__)
  676:     if (strstart(filename, "/dev/cd", NULL)) {
  677:         /* open will not fail even if no CD is inserted */
  678:         open_flags |= O_NONBLOCK;
  679:         s->type = FTYPE_CD;
  680:     } else if (strstart(filename, "/dev/fd", NULL)) {
  681:         s->type = FTYPE_FD;
  682:         s->fd_open_flags = open_flags;
  683:         /* open will not fail even if no floppy is inserted */
  684:         open_flags |= O_NONBLOCK;
  685:     } else if (strstart(filename, "/dev/sg", NULL)) {
  686:         bs->sg = 1;
  687:     }
  688: #endif
  689:     fd = open(filename, open_flags, 0644);
  690:     if (fd < 0) {
  691:         ret = -errno;
  692:         if (ret == -EROFS)
  693:             ret = -EACCES;
  694:         return ret;
  695:     }
  696:     s->fd = fd;
  697: #if defined(__linux__)
  698:     /* close fd so that we can reopen it as needed */
  699:     if (s->type == FTYPE_FD) {
  700:         close(s->fd);
  701:         s->fd = -1;
  702:         s->fd_media_changed = 1;
  703:     }
  704: #endif
  705:     return 0;
  706: }
  707: 
  708: #if defined(__linux__) && !defined(QEMU_IMG)
  709: 
  710: /* Note: we do not have a reliable method to detect if the floppy is
  711:    present. The current method is to try to open the floppy at every
  712:    I/O and to keep it opened during a few hundreds of ms. */
  713: static int fd_open(BlockDriverState *bs)
  714: {
  715:     BDRVRawState *s = bs->opaque;
  716:     int last_media_present;
  717: 
  718:     if (s->type != FTYPE_FD)
  719:         return 0;
  720:     last_media_present = (s->fd >= 0);
  721:     if (s->fd >= 0 &&
  722:         (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
  723:         close(s->fd);
  724:         s->fd = -1;
  725: #ifdef DEBUG_FLOPPY
  726:         printf("Floppy closed\n");
  727: #endif
  728:     }
  729:     if (s->fd < 0) {
  730:         if (s->fd_got_error &&
  731:             (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
  732: #ifdef DEBUG_FLOPPY
  733:             printf("No floppy (open delayed)\n");
  734: #endif
  735:             return -EIO;
  736:         }
  737:         s->fd = open(bs->filename, s->fd_open_flags);
  738:         if (s->fd < 0) {
  739:             s->fd_error_time = qemu_get_clock(rt_clock);
  740:             s->fd_got_error = 1;
  741:             if (last_media_present)
  742:                 s->fd_media_changed = 1;
  743: #ifdef DEBUG_FLOPPY
  744:             printf("No floppy\n");
  745: #endif
  746:             return -EIO;
  747:         }
  748: #ifdef DEBUG_FLOPPY
  749:         printf("Floppy opened\n");
  750: #endif
  751:     }
  752:     if (!last_media_present)
  753:         s->fd_media_changed = 1;
  754:     s->fd_open_time = qemu_get_clock(rt_clock);
  755:     s->fd_got_error = 0;
  756:     return 0;
  757: }
  758: #else
  759: static int fd_open(BlockDriverState *bs)
  760: {
  761:     return 0;
  762: }
  763: #endif
  764: 
  765: #if defined(__linux__)
  766: 
  767: static int raw_is_inserted(BlockDriverState *bs)
  768: {
  769:     BDRVRawState *s = bs->opaque;
  770:     int ret;
  771: 
  772:     switch(s->type) {
  773:     case FTYPE_CD:
  774:         ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
  775:         if (ret == CDS_DISC_OK)
  776:             return 1;
  777:         else
  778:             return 0;
  779:         break;
  780:     case FTYPE_FD:
  781:         ret = fd_open(bs);
  782:         return (ret >= 0);
  783:     default:
  784:         return 1;
  785:     }
  786: }
  787: 
  788: /* currently only used by fdc.c, but a CD version would be good too */
  789: static int raw_media_changed(BlockDriverState *bs)
  790: {
  791:     BDRVRawState *s = bs->opaque;
  792: 
  793:     switch(s->type) {
  794:     case FTYPE_FD:
  795:         {
  796:             int ret;
  797:             /* XXX: we do not have a true media changed indication. It
  798:                does not work if the floppy is changed without trying
  799:                to read it */
  800:             fd_open(bs);
  801:             ret = s->fd_media_changed;
  802:             s->fd_media_changed = 0;
  803: #ifdef DEBUG_FLOPPY
  804:             printf("Floppy changed=%d\n", ret);
  805: #endif
  806:             return ret;
  807:         }
  808:     default:
  809:         return -ENOTSUP;
  810:     }
  811: }
  812: 
  813: static int raw_eject(BlockDriverState *bs, int eject_flag)
  814: {
  815:     BDRVRawState *s = bs->opaque;
  816: 
  817:     switch(s->type) {
  818:     case FTYPE_CD:
  819:         if (eject_flag) {
  820:             if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
  821:                 perror("CDROMEJECT");
  822:         } else {
  823:             if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
  824:                 perror("CDROMEJECT");
  825:         }
  826:         break;
  827:     case FTYPE_FD:
  828:         {
  829:             int fd;
  830:             if (s->fd >= 0) {
  831:                 close(s->fd);
  832:                 s->fd = -1;
  833:             }
  834:             fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
  835:             if (fd >= 0) {
  836:                 if (ioctl(fd, FDEJECT, 0) < 0)
  837:                     perror("FDEJECT");
  838:                 close(fd);
  839:             }
  840:         }
  841:         break;
  842:     default:
  843:         return -ENOTSUP;
  844:     }
  845:     return 0;
  846: }
  847: 
  848: static int raw_set_locked(BlockDriverState *bs, int locked)
  849: {
  850:     BDRVRawState *s = bs->opaque;
  851: 
  852:     switch(s->type) {
  853:     case FTYPE_CD:
  854:         if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
  855:             /* Note: an error can happen if the distribution automatically
  856:                mounts the CD-ROM */
  857:             //        perror("CDROM_LOCKDOOR");
  858:         }
  859:         break;
  860:     default:
  861:         return -ENOTSUP;
  862:     }
  863:     return 0;
  864: }
  865: 
  866: static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
  867: {
  868:     BDRVRawState *s = bs->opaque;
  869: 
  870:     return ioctl(s->fd, req, buf);
  871: }
  872: #else
  873: 
  874: static int raw_is_inserted(BlockDriverState *bs)
  875: {
  876:     return 1;
  877: }
  878: 
  879: static int raw_media_changed(BlockDriverState *bs)
  880: {
  881:     return -ENOTSUP;
  882: }
  883: 
  884: static int raw_eject(BlockDriverState *bs, int eject_flag)
  885: {
  886:     return -ENOTSUP;
  887: }
  888: 
  889: static int raw_set_locked(BlockDriverState *bs, int locked)
  890: {
  891:     return -ENOTSUP;
  892: }
  893: 
  894: static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
  895: {
  896:     return -ENOTSUP;
  897: }
  898: #endif /* !linux */
  899: 
  900: BlockDriver bdrv_host_device = {
  901:     "host_device",
  902:     sizeof(BDRVRawState),
  903:     NULL, /* no probe for protocols */
  904:     hdev_open,
  905:     NULL,
  906:     NULL,
  907:     raw_close,
  908:     NULL,
  909:     raw_flush,
  910: 
  911:     .bdrv_aio_read = raw_aio_read,
  912:     .bdrv_aio_write = raw_aio_write,
  913:     .bdrv_aio_cancel = raw_aio_cancel,
  914:     .aiocb_size = sizeof(RawAIOCB),
  915:     .bdrv_pread = raw_pread,
  916:     .bdrv_pwrite = raw_pwrite,
  917:     .bdrv_getlength = raw_getlength,
  918: 
  919:     /* removable device support */
  920:     .bdrv_is_inserted = raw_is_inserted,
  921:     .bdrv_media_changed = raw_media_changed,
  922:     .bdrv_eject = raw_eject,
  923:     .bdrv_set_locked = raw_set_locked,
  924:     /* generic scsi device */
  925:     .bdrv_ioctl = raw_ioctl,
  926: };

unix.superglobalmegacorp.com