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