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

1.1       root        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