static int64_t raw_getlength(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; int fd = s->fd; int64_t size; struct stat sb; #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) int reopened = 0; #endif int ret; ret = fd_open(bs); if (ret < 0) return ret; #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) again: #endif if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { #ifdef DIOCGMEDIASIZE if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) #elif defined(DIOCGPART) { struct partinfo pi; if (ioctl(fd, DIOCGPART, &pi) == 0) size = pi.media_size; else size = 0; } if (size == 0) #endif #ifdef CONFIG_COCOA size = LONG_LONG_MAX; #else size = lseek(fd, 0LL, SEEK_END); #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) switch(s->type) { case FTYPE_CD: /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */ if (size == 2048LL * (unsigned)-1) size = 0; /* XXX no disc? maybe we need to reopen... */ if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) { reopened = 1; goto again; } } #endif } else { size = lseek(fd, 0, SEEK_END); } return size; }
static void cdrom_eject(BlockDriverState *bs, bool eject_flag) { BDRVRawState *s = bs->opaque; if (s->fd < 0) return; (void) ioctl(s->fd, CDIOCALLOW); if (eject_flag) { if (ioctl(s->fd, CDIOCEJECT) < 0) perror("CDIOCEJECT"); } else { if (ioctl(s->fd, CDIOCCLOSE) < 0) perror("CDIOCCLOSE"); } cdrom_reopen(bs); }
static int cdrom_eject(BlockDriverState *bs, int eject_flag) { BDRVRawState *s = bs->opaque; if (s->fd < 0) return -ENOTSUP; (void) ioctl(s->fd, CDIOCALLOW); if (eject_flag) { if (ioctl(s->fd, CDIOCEJECT) < 0) perror("CDIOCEJECT"); } else { if (ioctl(s->fd, CDIOCCLOSE) < 0) perror("CDIOCCLOSE"); } if (cdrom_reopen(bs) < 0) return -ENOTSUP; return 0; }
/* * If O_DIRECT is used the buffer needs to be aligned on a sector * boundary. Check if this is the case or telll the low-level * driver that it needs to copy the buffer. */ if (s->aligned_buf) { if (!qiov_is_aligned(qiov)) { type |= QEMU_AIO_MISALIGNED; #ifdef CONFIG_LINUX_AIO } else if (s->use_aio) { return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov, nb_sectors, cb, opaque, type); #endif } } return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors, cb, opaque, type); } static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { return raw_aio_submit(bs, sector_num, qiov, nb_sectors, cb, opaque, QEMU_AIO_READ); } static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { return raw_aio_submit(bs, sector_num, qiov, nb_sectors, cb, opaque, QEMU_AIO_WRITE); } static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs, BlockDriverCompletionFunc *cb, void *opaque) { BDRVRawState *s = bs->opaque; if (fd_open(bs) < 0) return NULL; return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH); } static void raw_close(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; if (s->fd >= 0) { close(s->fd); s->fd = -1; if (s->aligned_buf != NULL) qemu_free(s->aligned_buf); } } static int raw_truncate(BlockDriverState *bs, int64_t offset) { BDRVRawState *s = bs->opaque; if (s->type != FTYPE_FILE) return -ENOTSUP; if (ftruncate(s->fd, offset) < 0) return -errno; return 0; } #ifdef __OpenBSD__ static int64_t raw_getlength(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; int fd = s->fd; struct stat st; if (fstat(fd, &st)) return -1; if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { struct disklabel dl; if (ioctl(fd, DIOCGDINFO, &dl)) return -1; return (uint64_t)dl.d_secsize * dl.d_partitions[DISKPART(st.st_rdev)].p_size; } else return st.st_size; } #else /* !__OpenBSD__ */ static int64_t raw_getlength(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; int fd = s->fd; int64_t size; #ifdef CONFIG_BSD struct stat sb; #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) int reopened = 0; #endif #endif #ifdef __sun__ struct dk_minfo minfo; int rv; #endif int ret; ret = fd_open(bs); if (ret < 0) return ret; #ifdef CONFIG_BSD #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) again: #endif if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { #ifdef DIOCGMEDIASIZE if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) #elif defined(DIOCGPART) { struct partinfo pi; if (ioctl(fd, DIOCGPART, &pi) == 0) size = pi.media_size; else size = 0; } if (size == 0) #endif #ifdef CONFIG_COCOA size = LONG_LONG_MAX; #else size = lseek(fd, 0LL, SEEK_END); #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) switch(s->type) { case FTYPE_CD: /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */ if (size == 2048LL * (unsigned)-1) size = 0; /* XXX no disc? maybe we need to reopen... */ if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) { reopened = 1; goto again; } } #endif } else #endif #ifdef __sun__ /* * use the DKIOCGMEDIAINFO ioctl to read the size. */ rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo ); if ( rv != -1 ) { size = minfo.dki_lbsize * minfo.dki_capacity; } else /* there are reports that lseek on some devices fails, but irc discussion said that contingency on contingency was overkill */ #endif { size = lseek(fd, 0, SEEK_END); } return size; }