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