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

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: #include "qemu-timer.h"
                     26: #include "qemu-char.h"
                     27: #include "qemu-log.h"
                     28: #include "block_int.h"
                     29: #include "module.h"
1.1.1.2 ! root       30: #include "block/raw-posix-aio.h"
1.1       root       31: 
                     32: #ifdef CONFIG_COCOA
                     33: #include <paths.h>
                     34: #include <sys/param.h>
                     35: #include <IOKit/IOKitLib.h>
                     36: #include <IOKit/IOBSD.h>
                     37: #include <IOKit/storage/IOMediaBSDClient.h>
                     38: #include <IOKit/storage/IOMedia.h>
                     39: #include <IOKit/storage/IOCDMedia.h>
                     40: //#include <IOKit/storage/IOCDTypes.h>
                     41: #include <CoreFoundation/CoreFoundation.h>
                     42: #endif
                     43: 
                     44: #ifdef __sun__
                     45: #define _POSIX_PTHREAD_SEMANTICS 1
                     46: #include <signal.h>
                     47: #include <sys/dkio.h>
                     48: #endif
                     49: #ifdef __linux__
                     50: #include <sys/ioctl.h>
                     51: #include <linux/cdrom.h>
                     52: #include <linux/fd.h>
                     53: #endif
1.1.1.2 ! root       54: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root       55: #include <signal.h>
                     56: #include <sys/disk.h>
                     57: #include <sys/cdio.h>
                     58: #endif
                     59: 
                     60: #ifdef __OpenBSD__
                     61: #include <sys/ioctl.h>
                     62: #include <sys/disklabel.h>
                     63: #include <sys/dkio.h>
                     64: #endif
                     65: 
                     66: #ifdef __DragonFly__
                     67: #include <sys/ioctl.h>
                     68: #include <sys/diskslice.h>
                     69: #endif
                     70: 
                     71: //#define DEBUG_FLOPPY
                     72: 
                     73: //#define DEBUG_BLOCK
                     74: #if defined(DEBUG_BLOCK)
                     75: #define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \
                     76:     { qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0)
                     77: #else
                     78: #define DEBUG_BLOCK_PRINT(formatCstr, ...)
                     79: #endif
                     80: 
                     81: /* OS X does not have O_DSYNC */
                     82: #ifndef O_DSYNC
                     83: #ifdef O_SYNC
                     84: #define O_DSYNC O_SYNC
                     85: #elif defined(O_FSYNC)
                     86: #define O_DSYNC O_FSYNC
                     87: #endif
                     88: #endif
                     89: 
                     90: /* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
                     91: #ifndef O_DIRECT
                     92: #define O_DIRECT O_DSYNC
                     93: #endif
                     94: 
                     95: #define FTYPE_FILE   0
                     96: #define FTYPE_CD     1
                     97: #define FTYPE_FD     2
                     98: 
                     99: #define ALIGNED_BUFFER_SIZE (32 * 512)
                    100: 
                    101: /* if the FD is not accessed during that time (in ms), we try to
                    102:    reopen it to see if the disk has been changed */
                    103: #define FD_OPEN_TIMEOUT 1000
                    104: 
                    105: typedef struct BDRVRawState {
                    106:     int fd;
                    107:     int type;
                    108:     unsigned int lseek_err_cnt;
                    109:     int open_flags;
                    110: #if defined(__linux__)
                    111:     /* linux floppy specific */
                    112:     int64_t fd_open_time;
                    113:     int64_t fd_error_time;
                    114:     int fd_got_error;
                    115:     int fd_media_changed;
                    116: #endif
1.1.1.2 ! root      117: #ifdef CONFIG_LINUX_AIO
        !           118:     int use_aio;
        !           119:     void *aio_ctx;
        !           120: #endif
1.1       root      121:     uint8_t* aligned_buf;
                    122: } BDRVRawState;
                    123: 
                    124: static int fd_open(BlockDriverState *bs);
                    125: static int64_t raw_getlength(BlockDriverState *bs);
                    126: 
1.1.1.2 ! root      127: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root      128: static int cdrom_reopen(BlockDriverState *bs);
                    129: #endif
                    130: 
                    131: static int raw_open_common(BlockDriverState *bs, const char *filename,
                    132:                            int bdrv_flags, int open_flags)
                    133: {
                    134:     BDRVRawState *s = bs->opaque;
                    135:     int fd, ret;
                    136: 
                    137:     s->lseek_err_cnt = 0;
                    138: 
                    139:     s->open_flags = open_flags | O_BINARY;
                    140:     s->open_flags &= ~O_ACCMODE;
                    141:     if ((bdrv_flags & BDRV_O_ACCESS) == BDRV_O_RDWR) {
                    142:         s->open_flags |= O_RDWR;
                    143:     } else {
                    144:         s->open_flags |= O_RDONLY;
                    145:         bs->read_only = 1;
                    146:     }
                    147: 
                    148:     /* Use O_DSYNC for write-through caching, no flags for write-back caching,
                    149:      * and O_DIRECT for no caching. */
                    150:     if ((bdrv_flags & BDRV_O_NOCACHE))
                    151:         s->open_flags |= O_DIRECT;
                    152:     else if (!(bdrv_flags & BDRV_O_CACHE_WB))
                    153:         s->open_flags |= O_DSYNC;
                    154: 
                    155:     s->fd = -1;
1.1.1.2 ! root      156:     fd = qemu_open(filename, s->open_flags, 0644);
1.1       root      157:     if (fd < 0) {
                    158:         ret = -errno;
                    159:         if (ret == -EROFS)
                    160:             ret = -EACCES;
                    161:         return ret;
                    162:     }
                    163:     s->fd = fd;
                    164:     s->aligned_buf = NULL;
1.1.1.2 ! root      165: 
1.1       root      166:     if ((bdrv_flags & BDRV_O_NOCACHE)) {
                    167:         s->aligned_buf = qemu_blockalign(bs, ALIGNED_BUFFER_SIZE);
                    168:         if (s->aligned_buf == NULL) {
1.1.1.2 ! root      169:             goto out_close;
1.1       root      170:         }
                    171:     }
1.1.1.2 ! root      172: 
        !           173: #ifdef CONFIG_LINUX_AIO
        !           174:     if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
        !           175:                       (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
        !           176: 
        !           177:         /* We're falling back to POSIX AIO in some cases */
        !           178:         paio_init();
        !           179: 
        !           180:         s->aio_ctx = laio_init();
        !           181:         if (!s->aio_ctx) {
        !           182:             goto out_free_buf;
        !           183:         }
        !           184:         s->use_aio = 1;
        !           185:     } else
        !           186: #endif
        !           187:     {
        !           188:         if (paio_init() < 0) {
        !           189:             goto out_free_buf;
        !           190:         }
        !           191: #ifdef CONFIG_LINUX_AIO
        !           192:         s->use_aio = 0;
        !           193: #endif
        !           194:     }
        !           195: 
1.1       root      196:     return 0;
1.1.1.2 ! root      197: 
        !           198: out_free_buf:
        !           199:     qemu_vfree(s->aligned_buf);
        !           200: out_close:
        !           201:     close(fd);
        !           202:     return -errno;
1.1       root      203: }
                    204: 
                    205: static int raw_open(BlockDriverState *bs, const char *filename, int flags)
                    206: {
                    207:     BDRVRawState *s = bs->opaque;
                    208:     int open_flags = 0;
                    209: 
                    210:     s->type = FTYPE_FILE;
                    211:     if (flags & BDRV_O_CREAT)
                    212:         open_flags = O_CREAT | O_TRUNC;
                    213: 
                    214:     return raw_open_common(bs, filename, flags, open_flags);
                    215: }
                    216: 
                    217: /* XXX: use host sector size if necessary with:
                    218: #ifdef DIOCGSECTORSIZE
                    219:         {
                    220:             unsigned int sectorsize = 512;
                    221:             if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
                    222:                 sectorsize > bufsize)
                    223:                 bufsize = sectorsize;
                    224:         }
                    225: #endif
                    226: #ifdef CONFIG_COCOA
                    227:         u_int32_t   blockSize = 512;
                    228:         if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
                    229:             bufsize = blockSize;
                    230:         }
                    231: #endif
                    232: */
                    233: 
                    234: /*
                    235:  * offset and count are in bytes, but must be multiples of 512 for files
                    236:  * opened with O_DIRECT. buf must be aligned to 512 bytes then.
                    237:  *
                    238:  * This function may be called without alignment if the caller ensures
                    239:  * that O_DIRECT is not in effect.
                    240:  */
                    241: static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
                    242:                      uint8_t *buf, int count)
                    243: {
                    244:     BDRVRawState *s = bs->opaque;
                    245:     int ret;
                    246: 
                    247:     ret = fd_open(bs);
                    248:     if (ret < 0)
                    249:         return ret;
                    250: 
                    251:     if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
                    252:         ++(s->lseek_err_cnt);
                    253:         if(s->lseek_err_cnt <= 10) {
                    254:             DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
                    255:                               "] lseek failed : %d = %s\n",
                    256:                               s->fd, bs->filename, offset, buf, count,
                    257:                               bs->total_sectors, errno, strerror(errno));
                    258:         }
                    259:         return -1;
                    260:     }
                    261:     s->lseek_err_cnt=0;
                    262: 
                    263:     ret = read(s->fd, buf, count);
                    264:     if (ret == count)
                    265:         goto label__raw_read__success;
                    266: 
                    267:     /* Allow reads beyond the end (needed for pwrite) */
                    268:     if ((ret == 0) && bs->growable) {
                    269:         int64_t size = raw_getlength(bs);
                    270:         if (offset >= size) {
                    271:             memset(buf, 0, count);
                    272:             ret = count;
                    273:             goto label__raw_read__success;
                    274:         }
                    275:     }
                    276: 
                    277:     DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
                    278:                       "] read failed %d : %d = %s\n",
                    279:                       s->fd, bs->filename, offset, buf, count,
                    280:                       bs->total_sectors, ret, errno, strerror(errno));
                    281: 
                    282:     /* Try harder for CDrom. */
                    283:     if (bs->type == BDRV_TYPE_CDROM) {
                    284:         lseek(s->fd, offset, SEEK_SET);
                    285:         ret = read(s->fd, buf, count);
                    286:         if (ret == count)
                    287:             goto label__raw_read__success;
                    288:         lseek(s->fd, offset, SEEK_SET);
                    289:         ret = read(s->fd, buf, count);
                    290:         if (ret == count)
                    291:             goto label__raw_read__success;
                    292: 
                    293:         DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
                    294:                           "] retry read failed %d : %d = %s\n",
                    295:                           s->fd, bs->filename, offset, buf, count,
                    296:                           bs->total_sectors, ret, errno, strerror(errno));
                    297:     }
                    298: 
                    299: label__raw_read__success:
                    300: 
                    301:     return  (ret < 0) ? -errno : ret;
                    302: }
                    303: 
                    304: /*
                    305:  * offset and count are in bytes, but must be multiples of 512 for files
                    306:  * opened with O_DIRECT. buf must be aligned to 512 bytes then.
                    307:  *
                    308:  * This function may be called without alignment if the caller ensures
                    309:  * that O_DIRECT is not in effect.
                    310:  */
                    311: static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
                    312:                       const uint8_t *buf, int count)
                    313: {
                    314:     BDRVRawState *s = bs->opaque;
                    315:     int ret;
                    316: 
                    317:     ret = fd_open(bs);
                    318:     if (ret < 0)
                    319:         return -errno;
                    320: 
                    321:     if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
                    322:         ++(s->lseek_err_cnt);
                    323:         if(s->lseek_err_cnt) {
                    324:             DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
                    325:                               PRId64 "] lseek failed : %d = %s\n",
                    326:                               s->fd, bs->filename, offset, buf, count,
                    327:                               bs->total_sectors, errno, strerror(errno));
                    328:         }
                    329:         return -EIO;
                    330:     }
                    331:     s->lseek_err_cnt = 0;
                    332: 
                    333:     ret = write(s->fd, buf, count);
                    334:     if (ret == count)
                    335:         goto label__raw_write__success;
                    336: 
                    337:     DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
                    338:                       "] write failed %d : %d = %s\n",
                    339:                       s->fd, bs->filename, offset, buf, count,
                    340:                       bs->total_sectors, ret, errno, strerror(errno));
                    341: 
                    342: label__raw_write__success:
                    343: 
                    344:     return  (ret < 0) ? -errno : ret;
                    345: }
                    346: 
                    347: 
                    348: /*
                    349:  * offset and count are in bytes and possibly not aligned. For files opened
                    350:  * with O_DIRECT, necessary alignments are ensured before calling
                    351:  * raw_pread_aligned to do the actual read.
                    352:  */
                    353: static int raw_pread(BlockDriverState *bs, int64_t offset,
                    354:                      uint8_t *buf, int count)
                    355: {
                    356:     BDRVRawState *s = bs->opaque;
                    357:     int size, ret, shift, sum;
                    358: 
                    359:     sum = 0;
                    360: 
                    361:     if (s->aligned_buf != NULL)  {
                    362: 
                    363:         if (offset & 0x1ff) {
                    364:             /* align offset on a 512 bytes boundary */
                    365: 
                    366:             shift = offset & 0x1ff;
                    367:             size = (shift + count + 0x1ff) & ~0x1ff;
                    368:             if (size > ALIGNED_BUFFER_SIZE)
                    369:                 size = ALIGNED_BUFFER_SIZE;
                    370:             ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
                    371:             if (ret < 0)
                    372:                 return ret;
                    373: 
                    374:             size = 512 - shift;
                    375:             if (size > count)
                    376:                 size = count;
                    377:             memcpy(buf, s->aligned_buf + shift, size);
                    378: 
                    379:             buf += size;
                    380:             offset += size;
                    381:             count -= size;
                    382:             sum += size;
                    383: 
                    384:             if (count == 0)
                    385:                 return sum;
                    386:         }
                    387:         if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
                    388: 
                    389:             /* read on aligned buffer */
                    390: 
                    391:             while (count) {
                    392: 
                    393:                 size = (count + 0x1ff) & ~0x1ff;
                    394:                 if (size > ALIGNED_BUFFER_SIZE)
                    395:                     size = ALIGNED_BUFFER_SIZE;
                    396: 
                    397:                 ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
                    398:                 if (ret < 0)
                    399:                     return ret;
                    400: 
                    401:                 size = ret;
                    402:                 if (size > count)
                    403:                     size = count;
                    404: 
                    405:                 memcpy(buf, s->aligned_buf, size);
                    406: 
                    407:                 buf += size;
                    408:                 offset += size;
                    409:                 count -= size;
                    410:                 sum += size;
                    411:             }
                    412: 
                    413:             return sum;
                    414:         }
                    415:     }
                    416: 
                    417:     return raw_pread_aligned(bs, offset, buf, count) + sum;
                    418: }
                    419: 
                    420: static int raw_read(BlockDriverState *bs, int64_t sector_num,
                    421:                     uint8_t *buf, int nb_sectors)
                    422: {
                    423:     int ret;
                    424: 
                    425:     ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
                    426:     if (ret == (nb_sectors * 512))
                    427:         ret = 0;
                    428:     return ret;
                    429: }
                    430: 
                    431: /*
                    432:  * offset and count are in bytes and possibly not aligned. For files opened
                    433:  * with O_DIRECT, necessary alignments are ensured before calling
                    434:  * raw_pwrite_aligned to do the actual write.
                    435:  */
                    436: static int raw_pwrite(BlockDriverState *bs, int64_t offset,
                    437:                       const uint8_t *buf, int count)
                    438: {
                    439:     BDRVRawState *s = bs->opaque;
                    440:     int size, ret, shift, sum;
                    441: 
                    442:     sum = 0;
                    443: 
                    444:     if (s->aligned_buf != NULL) {
                    445: 
                    446:         if (offset & 0x1ff) {
                    447:             /* align offset on a 512 bytes boundary */
                    448:             shift = offset & 0x1ff;
                    449:             ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
                    450:             if (ret < 0)
                    451:                 return ret;
                    452: 
                    453:             size = 512 - shift;
                    454:             if (size > count)
                    455:                 size = count;
                    456:             memcpy(s->aligned_buf + shift, buf, size);
                    457: 
                    458:             ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
                    459:             if (ret < 0)
                    460:                 return ret;
                    461: 
                    462:             buf += size;
                    463:             offset += size;
                    464:             count -= size;
                    465:             sum += size;
                    466: 
                    467:             if (count == 0)
                    468:                 return sum;
                    469:         }
                    470:         if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
                    471: 
                    472:             while ((size = (count & ~0x1ff)) != 0) {
                    473: 
                    474:                 if (size > ALIGNED_BUFFER_SIZE)
                    475:                     size = ALIGNED_BUFFER_SIZE;
                    476: 
                    477:                 memcpy(s->aligned_buf, buf, size);
                    478: 
                    479:                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
                    480:                 if (ret < 0)
                    481:                     return ret;
                    482: 
                    483:                 buf += ret;
                    484:                 offset += ret;
                    485:                 count -= ret;
                    486:                 sum += ret;
                    487:             }
                    488:             /* here, count < 512 because (count & ~0x1ff) == 0 */
                    489:             if (count) {
                    490:                 ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
                    491:                 if (ret < 0)
                    492:                     return ret;
                    493:                  memcpy(s->aligned_buf, buf, count);
                    494: 
                    495:                  ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
                    496:                  if (ret < 0)
                    497:                      return ret;
                    498:                  if (count < ret)
                    499:                      ret = count;
                    500: 
                    501:                  sum += ret;
                    502:             }
                    503:             return sum;
                    504:         }
                    505:     }
                    506:     return raw_pwrite_aligned(bs, offset, buf, count) + sum;
                    507: }
                    508: 
                    509: static int raw_write(BlockDriverState *bs, int64_t sector_num,
                    510:                      const uint8_t *buf, int nb_sectors)
                    511: {
                    512:     int ret;
                    513:     ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
                    514:     if (ret == (nb_sectors * 512))
                    515:         ret = 0;
                    516:     return ret;
                    517: }
                    518: 
1.1.1.2 ! root      519: /*
        !           520:  * Check if all memory in this vector is sector aligned.
        !           521:  */
        !           522: static int qiov_is_aligned(QEMUIOVector *qiov)
1.1       root      523: {
1.1.1.2 ! root      524:     int i;
1.1       root      525: 
1.1.1.2 ! root      526:     for (i = 0; i < qiov->niov; i++) {
        !           527:         if ((uintptr_t) qiov->iov[i].iov_base % 512) {
        !           528:             return 0;
1.1       root      529:         }
                    530:     }
                    531: 
1.1.1.2 ! root      532:     return 1;
1.1       root      533: }
                    534: 
1.1.1.2 ! root      535: static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
        !           536:         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
        !           537:         BlockDriverCompletionFunc *cb, void *opaque, int type)
1.1       root      538: {
                    539:     BDRVRawState *s = bs->opaque;
                    540: 
                    541:     if (fd_open(bs) < 0)
                    542:         return NULL;
                    543: 
                    544:     /*
                    545:      * If O_DIRECT is used the buffer needs to be aligned on a sector
1.1.1.2 ! root      546:      * boundary.  Check if this is the case or telll the low-level
        !           547:      * driver that it needs to copy the buffer.
1.1       root      548:      */
1.1.1.2 ! root      549:     if (s->aligned_buf) {
        !           550:         if (!qiov_is_aligned(qiov)) {
        !           551:             type |= QEMU_AIO_MISALIGNED;
        !           552: #ifdef CONFIG_LINUX_AIO
        !           553:         } else if (s->use_aio) {
        !           554:             return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
        !           555:                                nb_sectors, cb, opaque, type);
        !           556: #endif
        !           557:         }
        !           558:     }
1.1       root      559: 
1.1.1.2 ! root      560:     return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
        !           561:                        cb, opaque, type);
1.1       root      562: }
                    563: 
                    564: static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
                    565:         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
                    566:         BlockDriverCompletionFunc *cb, void *opaque)
                    567: {
1.1.1.2 ! root      568:     return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
        !           569:                           cb, opaque, QEMU_AIO_READ);
1.1       root      570: }
                    571: 
                    572: static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
                    573:         int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
                    574:         BlockDriverCompletionFunc *cb, void *opaque)
                    575: {
1.1.1.2 ! root      576:     return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
        !           577:                           cb, opaque, QEMU_AIO_WRITE);
1.1       root      578: }
1.1.1.2 ! root      579: 
        !           580: static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
        !           581:         BlockDriverCompletionFunc *cb, void *opaque)
1.1       root      582: {
1.1.1.2 ! root      583:     BDRVRawState *s = bs->opaque;
        !           584: 
        !           585:     if (fd_open(bs) < 0)
        !           586:         return NULL;
1.1       root      587: 
1.1.1.2 ! root      588:     return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
        !           589: }
1.1       root      590: 
                    591: static void raw_close(BlockDriverState *bs)
                    592: {
                    593:     BDRVRawState *s = bs->opaque;
                    594:     if (s->fd >= 0) {
                    595:         close(s->fd);
                    596:         s->fd = -1;
                    597:         if (s->aligned_buf != NULL)
                    598:             qemu_free(s->aligned_buf);
                    599:     }
                    600: }
                    601: 
                    602: static int raw_truncate(BlockDriverState *bs, int64_t offset)
                    603: {
                    604:     BDRVRawState *s = bs->opaque;
                    605:     if (s->type != FTYPE_FILE)
                    606:         return -ENOTSUP;
                    607:     if (ftruncate(s->fd, offset) < 0)
                    608:         return -errno;
                    609:     return 0;
                    610: }
                    611: 
                    612: #ifdef __OpenBSD__
                    613: static int64_t raw_getlength(BlockDriverState *bs)
                    614: {
                    615:     BDRVRawState *s = bs->opaque;
                    616:     int fd = s->fd;
                    617:     struct stat st;
                    618: 
                    619:     if (fstat(fd, &st))
                    620:         return -1;
                    621:     if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
                    622:         struct disklabel dl;
                    623: 
                    624:         if (ioctl(fd, DIOCGDINFO, &dl))
                    625:             return -1;
                    626:         return (uint64_t)dl.d_secsize *
                    627:             dl.d_partitions[DISKPART(st.st_rdev)].p_size;
                    628:     } else
                    629:         return st.st_size;
                    630: }
                    631: #else /* !__OpenBSD__ */
                    632: static int64_t  raw_getlength(BlockDriverState *bs)
                    633: {
                    634:     BDRVRawState *s = bs->opaque;
                    635:     int fd = s->fd;
                    636:     int64_t size;
1.1.1.2 ! root      637: #ifdef CONFIG_BSD
1.1       root      638:     struct stat sb;
1.1.1.2 ! root      639: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root      640:     int reopened = 0;
                    641: #endif
                    642: #endif
                    643: #ifdef __sun__
                    644:     struct dk_minfo minfo;
                    645:     int rv;
                    646: #endif
                    647:     int ret;
                    648: 
                    649:     ret = fd_open(bs);
                    650:     if (ret < 0)
                    651:         return ret;
                    652: 
1.1.1.2 ! root      653: #ifdef CONFIG_BSD
        !           654: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root      655: again:
                    656: #endif
                    657:     if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
                    658: #ifdef DIOCGMEDIASIZE
                    659:        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
                    660: #elif defined(DIOCGPART)
                    661:         {
                    662:                 struct partinfo pi;
                    663:                 if (ioctl(fd, DIOCGPART, &pi) == 0)
                    664:                         size = pi.media_size;
                    665:                 else
                    666:                         size = 0;
                    667:         }
                    668:         if (size == 0)
                    669: #endif
                    670: #ifdef CONFIG_COCOA
                    671:         size = LONG_LONG_MAX;
                    672: #else
                    673:         size = lseek(fd, 0LL, SEEK_END);
                    674: #endif
1.1.1.2 ! root      675: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root      676:         switch(s->type) {
                    677:         case FTYPE_CD:
                    678:             /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
                    679:             if (size == 2048LL * (unsigned)-1)
                    680:                 size = 0;
                    681:             /* XXX no disc?  maybe we need to reopen... */
                    682:             if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
                    683:                 reopened = 1;
                    684:                 goto again;
                    685:             }
                    686:         }
                    687: #endif
                    688:     } else
                    689: #endif
                    690: #ifdef __sun__
                    691:     /*
                    692:      * use the DKIOCGMEDIAINFO ioctl to read the size.
                    693:      */
                    694:     rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
                    695:     if ( rv != -1 ) {
                    696:         size = minfo.dki_lbsize * minfo.dki_capacity;
                    697:     } else /* there are reports that lseek on some devices
                    698:               fails, but irc discussion said that contingency
                    699:               on contingency was overkill */
                    700: #endif
                    701:     {
                    702:         size = lseek(fd, 0, SEEK_END);
                    703:     }
                    704:     return size;
                    705: }
                    706: #endif
                    707: 
                    708: static int raw_create(const char *filename, QEMUOptionParameter *options)
                    709: {
                    710:     int fd;
                    711:     int result = 0;
                    712:     int64_t total_size = 0;
                    713: 
                    714:     /* Read out options */
                    715:     while (options && options->name) {
                    716:         if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
                    717:             total_size = options->value.n / 512;
                    718:         }
                    719:         options++;
                    720:     }
                    721: 
                    722:     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
                    723:               0644);
                    724:     if (fd < 0) {
                    725:         result = -errno;
                    726:     } else {
                    727:         if (ftruncate(fd, total_size * 512) != 0) {
                    728:             result = -errno;
                    729:         }
                    730:         if (close(fd) != 0) {
                    731:             result = -errno;
                    732:         }
                    733:     }
                    734:     return result;
                    735: }
                    736: 
                    737: static void raw_flush(BlockDriverState *bs)
                    738: {
                    739:     BDRVRawState *s = bs->opaque;
1.1.1.2 ! root      740:     qemu_fdatasync(s->fd);
1.1       root      741: }
                    742: 
                    743: 
                    744: static QEMUOptionParameter raw_create_options[] = {
                    745:     {
                    746:         .name = BLOCK_OPT_SIZE,
                    747:         .type = OPT_SIZE,
                    748:         .help = "Virtual disk size"
                    749:     },
                    750:     { NULL }
                    751: };
                    752: 
                    753: static BlockDriver bdrv_raw = {
                    754:     .format_name = "raw",
                    755:     .instance_size = sizeof(BDRVRawState),
                    756:     .bdrv_probe = NULL, /* no probe for protocols */
                    757:     .bdrv_open = raw_open,
                    758:     .bdrv_read = raw_read,
                    759:     .bdrv_write = raw_write,
                    760:     .bdrv_close = raw_close,
                    761:     .bdrv_create = raw_create,
                    762:     .bdrv_flush = raw_flush,
                    763: 
                    764:     .bdrv_aio_readv = raw_aio_readv,
                    765:     .bdrv_aio_writev = raw_aio_writev,
1.1.1.2 ! root      766:     .bdrv_aio_flush = raw_aio_flush,
1.1       root      767: 
                    768:     .bdrv_truncate = raw_truncate,
                    769:     .bdrv_getlength = raw_getlength,
                    770: 
                    771:     .create_options = raw_create_options,
                    772: };
                    773: 
                    774: /***********************************************/
                    775: /* host device */
                    776: 
                    777: #ifdef CONFIG_COCOA
                    778: static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
                    779: static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
                    780: 
                    781: kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
                    782: {
                    783:     kern_return_t       kernResult;
                    784:     mach_port_t     masterPort;
                    785:     CFMutableDictionaryRef  classesToMatch;
                    786: 
                    787:     kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
                    788:     if ( KERN_SUCCESS != kernResult ) {
                    789:         printf( "IOMasterPort returned %d\n", kernResult );
                    790:     }
                    791: 
                    792:     classesToMatch = IOServiceMatching( kIOCDMediaClass );
                    793:     if ( classesToMatch == NULL ) {
                    794:         printf( "IOServiceMatching returned a NULL dictionary.\n" );
                    795:     } else {
                    796:     CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
                    797:     }
                    798:     kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
                    799:     if ( KERN_SUCCESS != kernResult )
                    800:     {
                    801:         printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
                    802:     }
                    803: 
                    804:     return kernResult;
                    805: }
                    806: 
                    807: kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
                    808: {
                    809:     io_object_t     nextMedia;
                    810:     kern_return_t   kernResult = KERN_FAILURE;
                    811:     *bsdPath = '\0';
                    812:     nextMedia = IOIteratorNext( mediaIterator );
                    813:     if ( nextMedia )
                    814:     {
                    815:         CFTypeRef   bsdPathAsCFString;
                    816:     bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
                    817:         if ( bsdPathAsCFString ) {
                    818:             size_t devPathLength;
                    819:             strcpy( bsdPath, _PATH_DEV );
                    820:             strcat( bsdPath, "r" );
                    821:             devPathLength = strlen( bsdPath );
                    822:             if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
                    823:                 kernResult = KERN_SUCCESS;
                    824:             }
                    825:             CFRelease( bsdPathAsCFString );
                    826:         }
                    827:         IOObjectRelease( nextMedia );
                    828:     }
                    829: 
                    830:     return kernResult;
                    831: }
                    832: 
                    833: #endif
                    834: 
                    835: static int hdev_probe_device(const char *filename)
                    836: {
                    837:     struct stat st;
                    838: 
                    839:     /* allow a dedicated CD-ROM driver to match with a higher priority */
                    840:     if (strstart(filename, "/dev/cdrom", NULL))
                    841:         return 50;
                    842: 
                    843:     if (stat(filename, &st) >= 0 &&
                    844:             (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
                    845:         return 100;
                    846:     }
                    847: 
                    848:     return 0;
                    849: }
                    850: 
                    851: static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
                    852: {
                    853:     BDRVRawState *s = bs->opaque;
                    854: 
                    855: #ifdef CONFIG_COCOA
                    856:     if (strstart(filename, "/dev/cdrom", NULL)) {
                    857:         kern_return_t kernResult;
                    858:         io_iterator_t mediaIterator;
                    859:         char bsdPath[ MAXPATHLEN ];
                    860:         int fd;
                    861: 
                    862:         kernResult = FindEjectableCDMedia( &mediaIterator );
                    863:         kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
                    864: 
                    865:         if ( bsdPath[ 0 ] != '\0' ) {
                    866:             strcat(bsdPath,"s0");
                    867:             /* some CDs don't have a partition 0 */
                    868:             fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
                    869:             if (fd < 0) {
                    870:                 bsdPath[strlen(bsdPath)-1] = '1';
                    871:             } else {
                    872:                 close(fd);
                    873:             }
                    874:             filename = bsdPath;
                    875:         }
                    876: 
                    877:         if ( mediaIterator )
                    878:             IOObjectRelease( mediaIterator );
                    879:     }
                    880: #endif
                    881: 
                    882:     s->type = FTYPE_FILE;
1.1.1.2 ! root      883: #if defined(__linux__)
1.1       root      884:     if (strstart(filename, "/dev/sg", NULL)) {
                    885:         bs->sg = 1;
                    886:     }
                    887: #endif
                    888: 
                    889:     return raw_open_common(bs, filename, flags, 0);
                    890: }
                    891: 
                    892: #if defined(__linux__)
                    893: /* Note: we do not have a reliable method to detect if the floppy is
                    894:    present. The current method is to try to open the floppy at every
                    895:    I/O and to keep it opened during a few hundreds of ms. */
                    896: static int fd_open(BlockDriverState *bs)
                    897: {
                    898:     BDRVRawState *s = bs->opaque;
                    899:     int last_media_present;
                    900: 
                    901:     if (s->type != FTYPE_FD)
                    902:         return 0;
                    903:     last_media_present = (s->fd >= 0);
                    904:     if (s->fd >= 0 &&
                    905:         (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
                    906:         close(s->fd);
                    907:         s->fd = -1;
                    908: #ifdef DEBUG_FLOPPY
                    909:         printf("Floppy closed\n");
                    910: #endif
                    911:     }
                    912:     if (s->fd < 0) {
                    913:         if (s->fd_got_error &&
                    914:             (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
                    915: #ifdef DEBUG_FLOPPY
                    916:             printf("No floppy (open delayed)\n");
                    917: #endif
                    918:             return -EIO;
                    919:         }
                    920:         s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
                    921:         if (s->fd < 0) {
                    922:             s->fd_error_time = qemu_get_clock(rt_clock);
                    923:             s->fd_got_error = 1;
                    924:             if (last_media_present)
                    925:                 s->fd_media_changed = 1;
                    926: #ifdef DEBUG_FLOPPY
                    927:             printf("No floppy\n");
                    928: #endif
                    929:             return -EIO;
                    930:         }
                    931: #ifdef DEBUG_FLOPPY
                    932:         printf("Floppy opened\n");
                    933: #endif
                    934:     }
                    935:     if (!last_media_present)
                    936:         s->fd_media_changed = 1;
                    937:     s->fd_open_time = qemu_get_clock(rt_clock);
                    938:     s->fd_got_error = 0;
                    939:     return 0;
                    940: }
                    941: 
                    942: static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
                    943: {
                    944:     BDRVRawState *s = bs->opaque;
                    945: 
                    946:     return ioctl(s->fd, req, buf);
                    947: }
                    948: 
                    949: static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
                    950:         unsigned long int req, void *buf,
                    951:         BlockDriverCompletionFunc *cb, void *opaque)
                    952: {
                    953:     BDRVRawState *s = bs->opaque;
                    954: 
                    955:     if (fd_open(bs) < 0)
                    956:         return NULL;
1.1.1.2 ! root      957:     return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
1.1       root      958: }
                    959: 
1.1.1.2 ! root      960: #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root      961: static int fd_open(BlockDriverState *bs)
                    962: {
                    963:     BDRVRawState *s = bs->opaque;
                    964: 
                    965:     /* this is just to ensure s->fd is sane (its called by io ops) */
                    966:     if (s->fd >= 0)
                    967:         return 0;
                    968:     return -EIO;
                    969: }
                    970: #else /* !linux && !FreeBSD */
                    971: 
                    972: static int fd_open(BlockDriverState *bs)
                    973: {
                    974:     return 0;
                    975: }
                    976: 
                    977: #endif /* !linux && !FreeBSD */
                    978: 
                    979: static int hdev_create(const char *filename, QEMUOptionParameter *options)
                    980: {
                    981:     int fd;
                    982:     int ret = 0;
                    983:     struct stat stat_buf;
                    984:     int64_t total_size = 0;
                    985: 
                    986:     /* Read out options */
                    987:     while (options && options->name) {
                    988:         if (!strcmp(options->name, "size")) {
                    989:             total_size = options->value.n / 512;
                    990:         }
                    991:         options++;
                    992:     }
                    993: 
                    994:     fd = open(filename, O_WRONLY | O_BINARY);
                    995:     if (fd < 0)
                    996:         return -EIO;
                    997: 
                    998:     if (fstat(fd, &stat_buf) < 0)
                    999:         ret = -EIO;
                   1000:     else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
                   1001:         ret = -EIO;
                   1002:     else if (lseek(fd, 0, SEEK_END) < total_size * 512)
                   1003:         ret = -ENOSPC;
                   1004: 
                   1005:     close(fd);
                   1006:     return ret;
                   1007: }
                   1008: 
                   1009: static BlockDriver bdrv_host_device = {
1.1.1.2 ! root     1010:     .format_name        = "host_device",
        !          1011:     .instance_size      = sizeof(BDRVRawState),
        !          1012:     .bdrv_probe_device  = hdev_probe_device,
        !          1013:     .bdrv_open          = hdev_open,
        !          1014:     .bdrv_close         = raw_close,
1.1       root     1015:     .bdrv_create        = hdev_create,
1.1.1.2 ! root     1016:     .create_options     = raw_create_options,
        !          1017:     .no_zero_init       = 1,
        !          1018:     .bdrv_flush         = raw_flush,
1.1       root     1019: 
                   1020:     .bdrv_aio_readv    = raw_aio_readv,
                   1021:     .bdrv_aio_writev   = raw_aio_writev,
1.1.1.2 ! root     1022:     .bdrv_aio_flush    = raw_aio_flush,
1.1       root     1023: 
                   1024:     .bdrv_read          = raw_read,
                   1025:     .bdrv_write         = raw_write,
                   1026:     .bdrv_getlength    = raw_getlength,
                   1027: 
                   1028:     /* generic scsi device */
                   1029: #ifdef __linux__
                   1030:     .bdrv_ioctl         = hdev_ioctl,
                   1031:     .bdrv_aio_ioctl     = hdev_aio_ioctl,
                   1032: #endif
                   1033: };
                   1034: 
                   1035: #ifdef __linux__
                   1036: static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
                   1037: {
                   1038:     BDRVRawState *s = bs->opaque;
                   1039:     int ret;
                   1040: 
                   1041:     s->type = FTYPE_FD;
                   1042: 
                   1043:     /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
                   1044:     ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
                   1045:     if (ret)
                   1046:         return ret;
                   1047: 
                   1048:     /* close fd so that we can reopen it as needed */
                   1049:     close(s->fd);
                   1050:     s->fd = -1;
                   1051:     s->fd_media_changed = 1;
                   1052: 
                   1053:     return 0;
                   1054: }
                   1055: 
                   1056: static int floppy_probe_device(const char *filename)
                   1057: {
                   1058:     if (strstart(filename, "/dev/fd", NULL))
                   1059:         return 100;
                   1060:     return 0;
                   1061: }
                   1062: 
                   1063: 
                   1064: static int floppy_is_inserted(BlockDriverState *bs)
                   1065: {
                   1066:     return fd_open(bs) >= 0;
                   1067: }
                   1068: 
                   1069: static int floppy_media_changed(BlockDriverState *bs)
                   1070: {
                   1071:     BDRVRawState *s = bs->opaque;
                   1072:     int ret;
                   1073: 
                   1074:     /*
                   1075:      * XXX: we do not have a true media changed indication.
                   1076:      * It does not work if the floppy is changed without trying to read it.
                   1077:      */
                   1078:     fd_open(bs);
                   1079:     ret = s->fd_media_changed;
                   1080:     s->fd_media_changed = 0;
                   1081: #ifdef DEBUG_FLOPPY
                   1082:     printf("Floppy changed=%d\n", ret);
                   1083: #endif
                   1084:     return ret;
                   1085: }
                   1086: 
                   1087: static int floppy_eject(BlockDriverState *bs, int eject_flag)
                   1088: {
                   1089:     BDRVRawState *s = bs->opaque;
                   1090:     int fd;
                   1091: 
                   1092:     if (s->fd >= 0) {
                   1093:         close(s->fd);
                   1094:         s->fd = -1;
                   1095:     }
                   1096:     fd = open(bs->filename, s->open_flags | O_NONBLOCK);
                   1097:     if (fd >= 0) {
                   1098:         if (ioctl(fd, FDEJECT, 0) < 0)
                   1099:             perror("FDEJECT");
                   1100:         close(fd);
                   1101:     }
                   1102: 
                   1103:     return 0;
                   1104: }
                   1105: 
                   1106: static BlockDriver bdrv_host_floppy = {
                   1107:     .format_name        = "host_floppy",
                   1108:     .instance_size      = sizeof(BDRVRawState),
                   1109:     .bdrv_probe_device = floppy_probe_device,
                   1110:     .bdrv_open          = floppy_open,
                   1111:     .bdrv_close         = raw_close,
                   1112:     .bdrv_create        = hdev_create,
1.1.1.2 ! root     1113:     .create_options     = raw_create_options,
        !          1114:     .no_zero_init       = 1,
1.1       root     1115:     .bdrv_flush         = raw_flush,
                   1116: 
                   1117:     .bdrv_aio_readv     = raw_aio_readv,
                   1118:     .bdrv_aio_writev    = raw_aio_writev,
1.1.1.2 ! root     1119:     .bdrv_aio_flush    = raw_aio_flush,
1.1       root     1120: 
                   1121:     .bdrv_read          = raw_read,
                   1122:     .bdrv_write         = raw_write,
                   1123:     .bdrv_getlength    = raw_getlength,
                   1124: 
                   1125:     /* removable device support */
                   1126:     .bdrv_is_inserted   = floppy_is_inserted,
                   1127:     .bdrv_media_changed = floppy_media_changed,
                   1128:     .bdrv_eject         = floppy_eject,
                   1129: };
                   1130: 
                   1131: static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
                   1132: {
                   1133:     BDRVRawState *s = bs->opaque;
                   1134: 
                   1135:     s->type = FTYPE_CD;
                   1136: 
                   1137:     /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
                   1138:     return raw_open_common(bs, filename, flags, O_NONBLOCK);
                   1139: }
                   1140: 
                   1141: static int cdrom_probe_device(const char *filename)
                   1142: {
                   1143:     if (strstart(filename, "/dev/cd", NULL))
                   1144:         return 100;
                   1145:     return 0;
                   1146: }
                   1147: 
                   1148: static int cdrom_is_inserted(BlockDriverState *bs)
                   1149: {
                   1150:     BDRVRawState *s = bs->opaque;
                   1151:     int ret;
                   1152: 
                   1153:     ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
                   1154:     if (ret == CDS_DISC_OK)
                   1155:         return 1;
                   1156:     return 0;
                   1157: }
                   1158: 
                   1159: static int cdrom_eject(BlockDriverState *bs, int eject_flag)
                   1160: {
                   1161:     BDRVRawState *s = bs->opaque;
                   1162: 
                   1163:     if (eject_flag) {
                   1164:         if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
                   1165:             perror("CDROMEJECT");
                   1166:     } else {
                   1167:         if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
                   1168:             perror("CDROMEJECT");
                   1169:     }
                   1170: 
                   1171:     return 0;
                   1172: }
                   1173: 
                   1174: static int cdrom_set_locked(BlockDriverState *bs, int locked)
                   1175: {
                   1176:     BDRVRawState *s = bs->opaque;
                   1177: 
                   1178:     if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
                   1179:         /*
                   1180:          * Note: an error can happen if the distribution automatically
                   1181:          * mounts the CD-ROM
                   1182:          */
                   1183:         /* perror("CDROM_LOCKDOOR"); */
                   1184:     }
                   1185: 
                   1186:     return 0;
                   1187: }
                   1188: 
                   1189: static BlockDriver bdrv_host_cdrom = {
                   1190:     .format_name        = "host_cdrom",
                   1191:     .instance_size      = sizeof(BDRVRawState),
                   1192:     .bdrv_probe_device = cdrom_probe_device,
                   1193:     .bdrv_open          = cdrom_open,
                   1194:     .bdrv_close         = raw_close,
                   1195:     .bdrv_create        = hdev_create,
1.1.1.2 ! root     1196:     .create_options     = raw_create_options,
        !          1197:     .no_zero_init       = 1,
1.1       root     1198:     .bdrv_flush         = raw_flush,
                   1199: 
                   1200:     .bdrv_aio_readv     = raw_aio_readv,
                   1201:     .bdrv_aio_writev    = raw_aio_writev,
1.1.1.2 ! root     1202:     .bdrv_aio_flush    = raw_aio_flush,
1.1       root     1203: 
                   1204:     .bdrv_read          = raw_read,
                   1205:     .bdrv_write         = raw_write,
                   1206:     .bdrv_getlength     = raw_getlength,
                   1207: 
                   1208:     /* removable device support */
                   1209:     .bdrv_is_inserted   = cdrom_is_inserted,
                   1210:     .bdrv_eject         = cdrom_eject,
                   1211:     .bdrv_set_locked    = cdrom_set_locked,
                   1212: 
                   1213:     /* generic scsi device */
                   1214:     .bdrv_ioctl         = hdev_ioctl,
                   1215:     .bdrv_aio_ioctl     = hdev_aio_ioctl,
                   1216: };
                   1217: #endif /* __linux__ */
                   1218: 
1.1.1.2 ! root     1219: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root     1220: static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
                   1221: {
                   1222:     BDRVRawState *s = bs->opaque;
                   1223:     int ret;
                   1224: 
                   1225:     s->type = FTYPE_CD;
                   1226: 
                   1227:     ret = raw_open_common(bs, filename, flags, 0);
                   1228:     if (ret)
                   1229:         return ret;
                   1230: 
                   1231:     /* make sure the door isnt locked at this time */
                   1232:     ioctl(s->fd, CDIOCALLOW);
                   1233:     return 0;
                   1234: }
                   1235: 
                   1236: static int cdrom_probe_device(const char *filename)
                   1237: {
                   1238:     if (strstart(filename, "/dev/cd", NULL) ||
                   1239:             strstart(filename, "/dev/acd", NULL))
                   1240:         return 100;
                   1241:     return 0;
                   1242: }
                   1243: 
                   1244: static int cdrom_reopen(BlockDriverState *bs)
                   1245: {
                   1246:     BDRVRawState *s = bs->opaque;
                   1247:     int fd;
                   1248: 
                   1249:     /*
                   1250:      * Force reread of possibly changed/newly loaded disc,
                   1251:      * FreeBSD seems to not notice sometimes...
                   1252:      */
                   1253:     if (s->fd >= 0)
                   1254:         close(s->fd);
                   1255:     fd = open(bs->filename, s->open_flags, 0644);
                   1256:     if (fd < 0) {
                   1257:         s->fd = -1;
                   1258:         return -EIO;
                   1259:     }
                   1260:     s->fd = fd;
                   1261: 
                   1262:     /* make sure the door isnt locked at this time */
                   1263:     ioctl(s->fd, CDIOCALLOW);
                   1264:     return 0;
                   1265: }
                   1266: 
                   1267: static int cdrom_is_inserted(BlockDriverState *bs)
                   1268: {
                   1269:     return raw_getlength(bs) > 0;
                   1270: }
                   1271: 
                   1272: static int cdrom_eject(BlockDriverState *bs, int eject_flag)
                   1273: {
                   1274:     BDRVRawState *s = bs->opaque;
                   1275: 
                   1276:     if (s->fd < 0)
                   1277:         return -ENOTSUP;
                   1278: 
                   1279:     (void) ioctl(s->fd, CDIOCALLOW);
                   1280: 
                   1281:     if (eject_flag) {
                   1282:         if (ioctl(s->fd, CDIOCEJECT) < 0)
                   1283:             perror("CDIOCEJECT");
                   1284:     } else {
                   1285:         if (ioctl(s->fd, CDIOCCLOSE) < 0)
                   1286:             perror("CDIOCCLOSE");
                   1287:     }
                   1288: 
                   1289:     if (cdrom_reopen(bs) < 0)
                   1290:         return -ENOTSUP;
                   1291:     return 0;
                   1292: }
                   1293: 
                   1294: static int cdrom_set_locked(BlockDriverState *bs, int locked)
                   1295: {
                   1296:     BDRVRawState *s = bs->opaque;
                   1297: 
                   1298:     if (s->fd < 0)
                   1299:         return -ENOTSUP;
                   1300:     if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
                   1301:         /*
                   1302:          * Note: an error can happen if the distribution automatically
                   1303:          * mounts the CD-ROM
                   1304:          */
                   1305:         /* perror("CDROM_LOCKDOOR"); */
                   1306:     }
                   1307: 
                   1308:     return 0;
                   1309: }
                   1310: 
                   1311: static BlockDriver bdrv_host_cdrom = {
                   1312:     .format_name        = "host_cdrom",
                   1313:     .instance_size      = sizeof(BDRVRawState),
                   1314:     .bdrv_probe_device = cdrom_probe_device,
                   1315:     .bdrv_open          = cdrom_open,
                   1316:     .bdrv_close         = raw_close,
                   1317:     .bdrv_create        = hdev_create,
1.1.1.2 ! root     1318:     .create_options     = raw_create_options,
        !          1319:     .no_zero_init       = 1,
1.1       root     1320:     .bdrv_flush         = raw_flush,
                   1321: 
                   1322:     .bdrv_aio_readv     = raw_aio_readv,
                   1323:     .bdrv_aio_writev    = raw_aio_writev,
1.1.1.2 ! root     1324:     .bdrv_aio_flush    = raw_aio_flush,
1.1       root     1325: 
                   1326:     .bdrv_read          = raw_read,
                   1327:     .bdrv_write         = raw_write,
                   1328:     .bdrv_getlength     = raw_getlength,
                   1329: 
                   1330:     /* removable device support */
                   1331:     .bdrv_is_inserted   = cdrom_is_inserted,
                   1332:     .bdrv_eject         = cdrom_eject,
                   1333:     .bdrv_set_locked    = cdrom_set_locked,
                   1334: };
                   1335: #endif /* __FreeBSD__ */
                   1336: 
                   1337: static void bdrv_raw_init(void)
                   1338: {
                   1339:     /*
                   1340:      * Register all the drivers.  Note that order is important, the driver
                   1341:      * registered last will get probed first.
                   1342:      */
                   1343:     bdrv_register(&bdrv_raw);
                   1344:     bdrv_register(&bdrv_host_device);
                   1345: #ifdef __linux__
                   1346:     bdrv_register(&bdrv_host_floppy);
                   1347:     bdrv_register(&bdrv_host_cdrom);
                   1348: #endif
1.1.1.2 ! root     1349: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1.1       root     1350:     bdrv_register(&bdrv_host_cdrom);
                   1351: #endif
                   1352: }
                   1353: 
                   1354: block_init(bdrv_raw_init);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.