|
|
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, §orsize) &&
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);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.