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

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

unix.superglobalmegacorp.com

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