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

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