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