]> git.proxmox.com Git - mirror_qemu.git/blame - block/raw-posix.c
block: purge s->aligned_buf and s->aligned_buf_size from raw-posix.c
[mirror_qemu.git] / block / raw-posix.c
CommitLineData
83f64091 1/*
223d4670 2 * Block driver for RAW files (posix)
5fafdf24 3 *
83f64091 4 * Copyright (c) 2006 Fabrice Bellard
5fafdf24 5 *
83f64091
FB
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 */
faf07963 24#include "qemu-common.h"
87ecb68b 25#include "qemu-timer.h"
baf35cb9 26#include "qemu-char.h"
0bf9e31a 27#include "qemu-log.h"
83f64091 28#include "block_int.h"
5efa9d5a 29#include "module.h"
9ef91a67 30#include "block/raw-posix-aio.h"
83f64091 31
83affaa6 32#if defined(__APPLE__) && (__MACH__)
83f64091
FB
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__
2e9671da 45#define _POSIX_PTHREAD_SEMANTICS 1
83f64091
FB
46#include <sys/dkio.h>
47#endif
19cb3738 48#ifdef __linux__
343f8568
JS
49#include <sys/types.h>
50#include <sys/stat.h>
19cb3738 51#include <sys/ioctl.h>
05acda4d 52#include <sys/param.h>
19cb3738
FB
53#include <linux/cdrom.h>
54#include <linux/fd.h>
5500316d
PB
55#include <linux/fs.h>
56#endif
57#ifdef CONFIG_FIEMAP
58#include <linux/fiemap.h>
19cb3738 59#endif
a167ba50 60#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1cb6c3fd 61#include <sys/disk.h>
9f23011a 62#include <sys/cdio.h>
1cb6c3fd 63#endif
83f64091 64
128ab2ff
BS
65#ifdef __OpenBSD__
66#include <sys/ioctl.h>
67#include <sys/disklabel.h>
68#include <sys/dkio.h>
69#endif
70
d1f6fd8d
CE
71#ifdef __NetBSD__
72#include <sys/ioctl.h>
73#include <sys/disklabel.h>
74#include <sys/dkio.h>
75#include <sys/disk.h>
76#endif
77
c5e97233
BS
78#ifdef __DragonFly__
79#include <sys/ioctl.h>
80#include <sys/diskslice.h>
81#endif
82
dce512de
CH
83#ifdef CONFIG_XFS
84#include <xfs/xfs.h>
85#endif
86
19cb3738 87//#define DEBUG_FLOPPY
83f64091 88
faf07963 89//#define DEBUG_BLOCK
03ff3ca3 90#if defined(DEBUG_BLOCK)
001faf32
BS
91#define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \
92 { qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0)
8c05dbf9 93#else
001faf32 94#define DEBUG_BLOCK_PRINT(formatCstr, ...)
8c05dbf9
TS
95#endif
96
f6465578
AL
97/* OS X does not have O_DSYNC */
98#ifndef O_DSYNC
1c27a8b3 99#ifdef O_SYNC
7ab064d2 100#define O_DSYNC O_SYNC
1c27a8b3
JA
101#elif defined(O_FSYNC)
102#define O_DSYNC O_FSYNC
103#endif
f6465578
AL
104#endif
105
9f7965c7
AL
106/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
107#ifndef O_DIRECT
108#define O_DIRECT O_DSYNC
109#endif
110
19cb3738
FB
111#define FTYPE_FILE 0
112#define FTYPE_CD 1
113#define FTYPE_FD 2
83f64091 114
c57c846a 115/* if the FD is not accessed during that time (in ns), we try to
19cb3738 116 reopen it to see if the disk has been changed */
c57c846a 117#define FD_OPEN_TIMEOUT (1000000000)
83f64091 118
581b9e29
CH
119#define MAX_BLOCKSIZE 4096
120
19cb3738
FB
121typedef struct BDRVRawState {
122 int fd;
123 int type;
0e1d8f4c 124 int open_flags;
19cb3738
FB
125#if defined(__linux__)
126 /* linux floppy specific */
19cb3738
FB
127 int64_t fd_open_time;
128 int64_t fd_error_time;
129 int fd_got_error;
130 int fd_media_changed;
83f64091 131#endif
e44bd6fc 132#ifdef CONFIG_LINUX_AIO
5c6c3a6c 133 int use_aio;
1e5b9d2f 134 void *aio_ctx;
e44bd6fc 135#endif
dce512de
CH
136#ifdef CONFIG_XFS
137 bool is_xfs : 1;
138#endif
19cb3738
FB
139} BDRVRawState;
140
141static int fd_open(BlockDriverState *bs);
22afa7b5 142static int64_t raw_getlength(BlockDriverState *bs);
83f64091 143
a167ba50 144#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
f3a5d3f8 145static int cdrom_reopen(BlockDriverState *bs);
9f23011a
BS
146#endif
147
1de1ae0a
CE
148#if defined(__NetBSD__)
149static int raw_normalize_devicepath(const char **filename)
150{
151 static char namebuf[PATH_MAX];
152 const char *dp, *fname;
153 struct stat sb;
154
155 fname = *filename;
156 dp = strrchr(fname, '/');
157 if (lstat(fname, &sb) < 0) {
158 fprintf(stderr, "%s: stat failed: %s\n",
159 fname, strerror(errno));
160 return -errno;
161 }
162
163 if (!S_ISBLK(sb.st_mode)) {
164 return 0;
165 }
166
167 if (dp == NULL) {
168 snprintf(namebuf, PATH_MAX, "r%s", fname);
169 } else {
170 snprintf(namebuf, PATH_MAX, "%.*s/r%s",
171 (int)(dp - fname), fname, dp + 1);
172 }
173 fprintf(stderr, "%s is a block device", fname);
174 *filename = namebuf;
175 fprintf(stderr, ", using %s\n", *filename);
176
177 return 0;
178}
179#else
180static int raw_normalize_devicepath(const char **filename)
181{
182 return 0;
183}
184#endif
185
6a8dc042
JC
186static void raw_parse_flags(int bdrv_flags, int *open_flags)
187{
188 assert(open_flags != NULL);
189
190 *open_flags |= O_BINARY;
191 *open_flags &= ~O_ACCMODE;
192 if (bdrv_flags & BDRV_O_RDWR) {
193 *open_flags |= O_RDWR;
194 } else {
195 *open_flags |= O_RDONLY;
196 }
197
198 /* Use O_DSYNC for write-through caching, no flags for write-back caching,
199 * and O_DIRECT for no caching. */
200 if ((bdrv_flags & BDRV_O_NOCACHE)) {
201 *open_flags |= O_DIRECT;
202 }
6a8dc042
JC
203}
204
fc32a72d
JC
205#ifdef CONFIG_LINUX_AIO
206static int raw_set_aio(void **aio_ctx, int *use_aio, int bdrv_flags)
207{
208 int ret = -1;
209 assert(aio_ctx != NULL);
210 assert(use_aio != NULL);
211 /*
212 * Currently Linux do AIO only for files opened with O_DIRECT
213 * specified so check NOCACHE flag too
214 */
215 if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
216 (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
217
218 /* if non-NULL, laio_init() has already been run */
219 if (*aio_ctx == NULL) {
220 *aio_ctx = laio_init();
221 if (!*aio_ctx) {
222 goto error;
223 }
224 }
225 *use_aio = 1;
226 } else {
227 *use_aio = 0;
228 }
229
230 ret = 0;
231
232error:
233 return ret;
234}
235#endif
236
90babde0 237static int raw_open_common(BlockDriverState *bs, const char *filename,
19a3da7f 238 int bdrv_flags, int open_flags)
83f64091
FB
239{
240 BDRVRawState *s = bs->opaque;
0e1d8f4c 241 int fd, ret;
83f64091 242
1de1ae0a
CE
243 ret = raw_normalize_devicepath(&filename);
244 if (ret != 0) {
245 return ret;
246 }
247
6a8dc042
JC
248 s->open_flags = open_flags;
249 raw_parse_flags(bdrv_flags, &s->open_flags);
83f64091 250
90babde0 251 s->fd = -1;
40ff6d7e 252 fd = qemu_open(filename, s->open_flags, 0644);
19cb3738
FB
253 if (fd < 0) {
254 ret = -errno;
255 if (ret == -EROFS)
256 ret = -EACCES;
257 return ret;
258 }
83f64091 259 s->fd = fd;
9ef91a67 260
f6e8ffc2
FZ
261 /* We're falling back to POSIX AIO in some cases so init always */
262 if (paio_init() < 0) {
3d1807ac 263 goto out_close;
f6e8ffc2
FZ
264 }
265
5c6c3a6c 266#ifdef CONFIG_LINUX_AIO
fc32a72d
JC
267 if (raw_set_aio(&s->aio_ctx, &s->use_aio, bdrv_flags)) {
268 goto out_close;
9ef91a67 269 }
fc32a72d 270#endif
9ef91a67 271
dce512de
CH
272#ifdef CONFIG_XFS
273 if (platform_test_xfs_fd(s->fd)) {
274 s->is_xfs = 1;
275 }
276#endif
277
83f64091 278 return 0;
9ef91a67 279
9ef91a67 280out_close:
2e1e79da 281 qemu_close(fd);
9ef91a67 282 return -errno;
83f64091
FB
283}
284
90babde0
CH
285static int raw_open(BlockDriverState *bs, const char *filename, int flags)
286{
287 BDRVRawState *s = bs->opaque;
288
289 s->type = FTYPE_FILE;
9a2d77ad 290 return raw_open_common(bs, filename, flags, 0);
90babde0
CH
291}
292
83f64091
FB
293/* XXX: use host sector size if necessary with:
294#ifdef DIOCGSECTORSIZE
295 {
296 unsigned int sectorsize = 512;
297 if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
298 sectorsize > bufsize)
299 bufsize = sectorsize;
300 }
301#endif
302#ifdef CONFIG_COCOA
2ee9fb48 303 uint32_t blockSize = 512;
83f64091
FB
304 if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
305 bufsize = blockSize;
306 }
307#endif
308*/
309
9ef91a67
CH
310/*
311 * Check if all memory in this vector is sector aligned.
312 */
581b9e29 313static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
a76bab49 314{
9ef91a67 315 int i;
83f64091 316
9ef91a67 317 for (i = 0; i < qiov->niov; i++) {
581b9e29 318 if ((uintptr_t) qiov->iov[i].iov_base % bs->buffer_alignment) {
9ef91a67 319 return 0;
c16b5a2c 320 }
c16b5a2c 321 }
c16b5a2c 322
9ef91a67 323 return 1;
c16b5a2c
CH
324}
325
9ef91a67
CH
326static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
327 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
328 BlockDriverCompletionFunc *cb, void *opaque, int type)
83f64091 329{
ce1a14dc 330 BDRVRawState *s = bs->opaque;
ce1a14dc 331
19cb3738
FB
332 if (fd_open(bs) < 0)
333 return NULL;
334
f141eafe
AL
335 /*
336 * If O_DIRECT is used the buffer needs to be aligned on a sector
c1ee7d56 337 * boundary. Check if this is the case or tell the low-level
9ef91a67 338 * driver that it needs to copy the buffer.
f141eafe 339 */
9acc5a06 340 if ((bs->open_flags & BDRV_O_NOCACHE)) {
581b9e29 341 if (!qiov_is_aligned(bs, qiov)) {
5c6c3a6c 342 type |= QEMU_AIO_MISALIGNED;
e44bd6fc 343#ifdef CONFIG_LINUX_AIO
5c6c3a6c
CH
344 } else if (s->use_aio) {
345 return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
e44bd6fc
SW
346 nb_sectors, cb, opaque, type);
347#endif
5c6c3a6c 348 }
9ef91a67 349 }
f141eafe 350
1e5b9d2f 351 return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
9ef91a67 352 cb, opaque, type);
83f64091
FB
353}
354
f141eafe
AL
355static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
356 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
ce1a14dc 357 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 358{
9ef91a67
CH
359 return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
360 cb, opaque, QEMU_AIO_READ);
83f64091
FB
361}
362
f141eafe
AL
363static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
364 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
ce1a14dc 365 BlockDriverCompletionFunc *cb, void *opaque)
83f64091 366{
9ef91a67
CH
367 return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
368 cb, opaque, QEMU_AIO_WRITE);
83f64091 369}
53538725 370
b2e12bc6
CH
371static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
372 BlockDriverCompletionFunc *cb, void *opaque)
373{
374 BDRVRawState *s = bs->opaque;
375
376 if (fd_open(bs) < 0)
377 return NULL;
378
1e5b9d2f 379 return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
b2e12bc6
CH
380}
381
83f64091
FB
382static void raw_close(BlockDriverState *bs)
383{
384 BDRVRawState *s = bs->opaque;
19cb3738 385 if (s->fd >= 0) {
2e1e79da 386 qemu_close(s->fd);
19cb3738
FB
387 s->fd = -1;
388 }
83f64091
FB
389}
390
391static int raw_truncate(BlockDriverState *bs, int64_t offset)
392{
393 BDRVRawState *s = bs->opaque;
55b949c8
CH
394 struct stat st;
395
396 if (fstat(s->fd, &st)) {
83f64091 397 return -errno;
55b949c8
CH
398 }
399
400 if (S_ISREG(st.st_mode)) {
401 if (ftruncate(s->fd, offset) < 0) {
402 return -errno;
403 }
404 } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
405 if (offset > raw_getlength(bs)) {
406 return -EINVAL;
407 }
408 } else {
409 return -ENOTSUP;
410 }
411
83f64091
FB
412 return 0;
413}
414
128ab2ff
BS
415#ifdef __OpenBSD__
416static int64_t raw_getlength(BlockDriverState *bs)
417{
418 BDRVRawState *s = bs->opaque;
419 int fd = s->fd;
420 struct stat st;
421
422 if (fstat(fd, &st))
423 return -1;
424 if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
425 struct disklabel dl;
426
427 if (ioctl(fd, DIOCGDINFO, &dl))
428 return -1;
429 return (uint64_t)dl.d_secsize *
430 dl.d_partitions[DISKPART(st.st_rdev)].p_size;
431 } else
432 return st.st_size;
433}
d1f6fd8d
CE
434#elif defined(__NetBSD__)
435static int64_t raw_getlength(BlockDriverState *bs)
436{
437 BDRVRawState *s = bs->opaque;
438 int fd = s->fd;
439 struct stat st;
440
441 if (fstat(fd, &st))
442 return -1;
443 if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
444 struct dkwedge_info dkw;
445
446 if (ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
447 return dkw.dkw_size * 512;
448 } else {
449 struct disklabel dl;
450
451 if (ioctl(fd, DIOCGDINFO, &dl))
452 return -1;
453 return (uint64_t)dl.d_secsize *
454 dl.d_partitions[DISKPART(st.st_rdev)].p_size;
455 }
456 } else
457 return st.st_size;
458}
50779cc2
CH
459#elif defined(__sun__)
460static int64_t raw_getlength(BlockDriverState *bs)
461{
462 BDRVRawState *s = bs->opaque;
463 struct dk_minfo minfo;
464 int ret;
465
466 ret = fd_open(bs);
467 if (ret < 0) {
468 return ret;
469 }
470
471 /*
472 * Use the DKIOCGMEDIAINFO ioctl to read the size.
473 */
474 ret = ioctl(s->fd, DKIOCGMEDIAINFO, &minfo);
475 if (ret != -1) {
476 return minfo.dki_lbsize * minfo.dki_capacity;
477 }
478
479 /*
480 * There are reports that lseek on some devices fails, but
481 * irc discussion said that contingency on contingency was overkill.
482 */
483 return lseek(s->fd, 0, SEEK_END);
484}
485#elif defined(CONFIG_BSD)
486static int64_t raw_getlength(BlockDriverState *bs)
83f64091
FB
487{
488 BDRVRawState *s = bs->opaque;
489 int fd = s->fd;
490 int64_t size;
83f64091 491 struct stat sb;
a167ba50 492#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
9f23011a 493 int reopened = 0;
83f64091 494#endif
19cb3738
FB
495 int ret;
496
497 ret = fd_open(bs);
498 if (ret < 0)
499 return ret;
83f64091 500
a167ba50 501#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
9f23011a
BS
502again:
503#endif
83f64091
FB
504 if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
505#ifdef DIOCGMEDIASIZE
506 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
c5e97233
BS
507#elif defined(DIOCGPART)
508 {
509 struct partinfo pi;
510 if (ioctl(fd, DIOCGPART, &pi) == 0)
511 size = pi.media_size;
512 else
513 size = 0;
514 }
515 if (size == 0)
83f64091 516#endif
83affaa6 517#if defined(__APPLE__) && defined(__MACH__)
83f64091
FB
518 size = LONG_LONG_MAX;
519#else
520 size = lseek(fd, 0LL, SEEK_END);
9f23011a 521#endif
a167ba50 522#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
9f23011a
BS
523 switch(s->type) {
524 case FTYPE_CD:
525 /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
526 if (size == 2048LL * (unsigned)-1)
527 size = 0;
528 /* XXX no disc? maybe we need to reopen... */
f3a5d3f8 529 if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
9f23011a
BS
530 reopened = 1;
531 goto again;
532 }
533 }
83f64091 534#endif
50779cc2 535 } else {
83f64091
FB
536 size = lseek(fd, 0, SEEK_END);
537 }
83f64091
FB
538 return size;
539}
50779cc2
CH
540#else
541static int64_t raw_getlength(BlockDriverState *bs)
542{
543 BDRVRawState *s = bs->opaque;
544 int ret;
545
546 ret = fd_open(bs);
547 if (ret < 0) {
548 return ret;
549 }
550
551 return lseek(s->fd, 0, SEEK_END);
552}
128ab2ff 553#endif
83f64091 554
4a1d5e1f
FZ
555static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
556{
557 struct stat st;
558 BDRVRawState *s = bs->opaque;
559
560 if (fstat(s->fd, &st) < 0) {
561 return -errno;
562 }
563 return (int64_t)st.st_blocks * 512;
564}
565
0e7e1989 566static int raw_create(const char *filename, QEMUOptionParameter *options)
83f64091
FB
567{
568 int fd;
1e37d059 569 int result = 0;
0e7e1989 570 int64_t total_size = 0;
83f64091 571
0e7e1989
KW
572 /* Read out options */
573 while (options && options->name) {
574 if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
9040385d 575 total_size = options->value.n / BDRV_SECTOR_SIZE;
0e7e1989
KW
576 }
577 options++;
578 }
83f64091 579
6165f4d8
CB
580 fd = qemu_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
581 0644);
1e37d059
SW
582 if (fd < 0) {
583 result = -errno;
584 } else {
9040385d 585 if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
1e37d059
SW
586 result = -errno;
587 }
2e1e79da 588 if (qemu_close(fd) != 0) {
1e37d059
SW
589 result = -errno;
590 }
591 }
592 return result;
83f64091
FB
593}
594
5500316d
PB
595/*
596 * Returns true iff the specified sector is present in the disk image. Drivers
597 * not implementing the functionality are assumed to not support backing files,
598 * hence all their sectors are reported as allocated.
599 *
600 * If 'sector_num' is beyond the end of the disk image the return value is 0
601 * and 'pnum' is set to 0.
602 *
603 * 'pnum' is set to the number of sectors (including and immediately following
604 * the specified sector) that are known to be in the same
605 * allocated/unallocated state.
606 *
607 * 'nb_sectors' is the max value 'pnum' should be set to. If nb_sectors goes
608 * beyond the end of the disk image it will be clamped.
609 */
610static int coroutine_fn raw_co_is_allocated(BlockDriverState *bs,
611 int64_t sector_num,
612 int nb_sectors, int *pnum)
613{
5500316d
PB
614 off_t start, data, hole;
615 int ret;
616
617 ret = fd_open(bs);
618 if (ret < 0) {
619 return ret;
620 }
621
622 start = sector_num * BDRV_SECTOR_SIZE;
94282e71 623
5500316d 624#ifdef CONFIG_FIEMAP
94282e71
KW
625
626 BDRVRawState *s = bs->opaque;
5500316d
PB
627 struct {
628 struct fiemap fm;
629 struct fiemap_extent fe;
630 } f;
94282e71 631
5500316d
PB
632 f.fm.fm_start = start;
633 f.fm.fm_length = (int64_t)nb_sectors * BDRV_SECTOR_SIZE;
634 f.fm.fm_flags = 0;
635 f.fm.fm_extent_count = 1;
636 f.fm.fm_reserved = 0;
637 if (ioctl(s->fd, FS_IOC_FIEMAP, &f) == -1) {
638 /* Assume everything is allocated. */
639 *pnum = nb_sectors;
640 return 1;
641 }
642
643 if (f.fm.fm_mapped_extents == 0) {
644 /* No extents found, data is beyond f.fm.fm_start + f.fm.fm_length.
645 * f.fm.fm_start + f.fm.fm_length must be clamped to the file size!
646 */
647 off_t length = lseek(s->fd, 0, SEEK_END);
648 hole = f.fm.fm_start;
649 data = MIN(f.fm.fm_start + f.fm.fm_length, length);
650 } else {
651 data = f.fe.fe_logical;
652 hole = f.fe.fe_logical + f.fe.fe_length;
653 }
94282e71 654
5500316d 655#elif defined SEEK_HOLE && defined SEEK_DATA
94282e71
KW
656
657 BDRVRawState *s = bs->opaque;
658
5500316d
PB
659 hole = lseek(s->fd, start, SEEK_HOLE);
660 if (hole == -1) {
661 /* -ENXIO indicates that sector_num was past the end of the file.
662 * There is a virtual hole there. */
663 assert(errno != -ENXIO);
664
665 /* Most likely EINVAL. Assume everything is allocated. */
666 *pnum = nb_sectors;
667 return 1;
668 }
669
670 if (hole > start) {
671 data = start;
672 } else {
673 /* On a hole. We need another syscall to find its end. */
674 data = lseek(s->fd, start, SEEK_DATA);
675 if (data == -1) {
676 data = lseek(s->fd, 0, SEEK_END);
677 }
678 }
679#else
680 *pnum = nb_sectors;
681 return 1;
682#endif
683
684 if (data <= start) {
685 /* On a data extent, compute sectors to the end of the extent. */
686 *pnum = MIN(nb_sectors, (hole - start) / BDRV_SECTOR_SIZE);
687 return 1;
688 } else {
689 /* On a hole, compute sectors to the beginning of the next extent. */
690 *pnum = MIN(nb_sectors, (data - start) / BDRV_SECTOR_SIZE);
691 return 0;
692 }
693}
694
dce512de
CH
695#ifdef CONFIG_XFS
696static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
697{
698 struct xfs_flock64 fl;
699
700 memset(&fl, 0, sizeof(fl));
701 fl.l_whence = SEEK_SET;
702 fl.l_start = sector_num << 9;
703 fl.l_len = (int64_t)nb_sectors << 9;
704
705 if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
706 DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
707 return -errno;
708 }
709
710 return 0;
711}
712#endif
713
6db39ae2
PB
714static coroutine_fn int raw_co_discard(BlockDriverState *bs,
715 int64_t sector_num, int nb_sectors)
dce512de
CH
716{
717#ifdef CONFIG_XFS
718 BDRVRawState *s = bs->opaque;
719
720 if (s->is_xfs) {
721 return xfs_discard(s, sector_num, nb_sectors);
722 }
723#endif
724
725 return 0;
726}
0e7e1989
KW
727
728static QEMUOptionParameter raw_create_options[] = {
db08adf5
KW
729 {
730 .name = BLOCK_OPT_SIZE,
731 .type = OPT_SIZE,
732 .help = "Virtual disk size"
733 },
0e7e1989
KW
734 { NULL }
735};
736
84a12e66
CH
737static BlockDriver bdrv_file = {
738 .format_name = "file",
739 .protocol_name = "file",
856ae5c3
BS
740 .instance_size = sizeof(BDRVRawState),
741 .bdrv_probe = NULL, /* no probe for protocols */
66f82cee 742 .bdrv_file_open = raw_open,
856ae5c3
BS
743 .bdrv_close = raw_close,
744 .bdrv_create = raw_create,
6db39ae2 745 .bdrv_co_discard = raw_co_discard,
5500316d 746 .bdrv_co_is_allocated = raw_co_is_allocated,
3b46e624 747
f141eafe
AL
748 .bdrv_aio_readv = raw_aio_readv,
749 .bdrv_aio_writev = raw_aio_writev,
b2e12bc6 750 .bdrv_aio_flush = raw_aio_flush,
3c529d93 751
83f64091
FB
752 .bdrv_truncate = raw_truncate,
753 .bdrv_getlength = raw_getlength,
4a1d5e1f
FZ
754 .bdrv_get_allocated_file_size
755 = raw_get_allocated_file_size,
0e7e1989
KW
756
757 .create_options = raw_create_options,
83f64091
FB
758};
759
19cb3738
FB
760/***********************************************/
761/* host device */
762
83affaa6 763#if defined(__APPLE__) && defined(__MACH__)
19cb3738
FB
764static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
765static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
766
767kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
768{
5fafdf24 769 kern_return_t kernResult;
19cb3738
FB
770 mach_port_t masterPort;
771 CFMutableDictionaryRef classesToMatch;
772
773 kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
774 if ( KERN_SUCCESS != kernResult ) {
775 printf( "IOMasterPort returned %d\n", kernResult );
776 }
3b46e624 777
5fafdf24 778 classesToMatch = IOServiceMatching( kIOCDMediaClass );
19cb3738
FB
779 if ( classesToMatch == NULL ) {
780 printf( "IOServiceMatching returned a NULL dictionary.\n" );
781 } else {
782 CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
783 }
784 kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
785 if ( KERN_SUCCESS != kernResult )
786 {
787 printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
788 }
3b46e624 789
19cb3738
FB
790 return kernResult;
791}
792
793kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
794{
795 io_object_t nextMedia;
796 kern_return_t kernResult = KERN_FAILURE;
797 *bsdPath = '\0';
798 nextMedia = IOIteratorNext( mediaIterator );
799 if ( nextMedia )
800 {
801 CFTypeRef bsdPathAsCFString;
802 bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
803 if ( bsdPathAsCFString ) {
804 size_t devPathLength;
805 strcpy( bsdPath, _PATH_DEV );
806 strcat( bsdPath, "r" );
807 devPathLength = strlen( bsdPath );
808 if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
809 kernResult = KERN_SUCCESS;
810 }
811 CFRelease( bsdPathAsCFString );
812 }
813 IOObjectRelease( nextMedia );
814 }
3b46e624 815
19cb3738
FB
816 return kernResult;
817}
818
819#endif
820
508c7cb3
CH
821static int hdev_probe_device(const char *filename)
822{
823 struct stat st;
824
825 /* allow a dedicated CD-ROM driver to match with a higher priority */
826 if (strstart(filename, "/dev/cdrom", NULL))
827 return 50;
828
829 if (stat(filename, &st) >= 0 &&
830 (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
831 return 100;
832 }
833
834 return 0;
835}
836
19cb3738
FB
837static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
838{
839 BDRVRawState *s = bs->opaque;
a76bab49 840
83affaa6 841#if defined(__APPLE__) && defined(__MACH__)
19cb3738
FB
842 if (strstart(filename, "/dev/cdrom", NULL)) {
843 kern_return_t kernResult;
844 io_iterator_t mediaIterator;
845 char bsdPath[ MAXPATHLEN ];
846 int fd;
5fafdf24 847
19cb3738
FB
848 kernResult = FindEjectableCDMedia( &mediaIterator );
849 kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
3b46e624 850
19cb3738
FB
851 if ( bsdPath[ 0 ] != '\0' ) {
852 strcat(bsdPath,"s0");
853 /* some CDs don't have a partition 0 */
6165f4d8 854 fd = qemu_open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
19cb3738
FB
855 if (fd < 0) {
856 bsdPath[strlen(bsdPath)-1] = '1';
857 } else {
2e1e79da 858 qemu_close(fd);
19cb3738
FB
859 }
860 filename = bsdPath;
861 }
3b46e624 862
19cb3738
FB
863 if ( mediaIterator )
864 IOObjectRelease( mediaIterator );
865 }
866#endif
19cb3738
FB
867
868 s->type = FTYPE_FILE;
4dd75c70 869#if defined(__linux__)
05acda4d
BK
870 {
871 char resolved_path[ MAXPATHLEN ], *temp;
872
873 temp = realpath(filename, resolved_path);
874 if (temp && strstart(temp, "/dev/sg", NULL)) {
875 bs->sg = 1;
876 }
19cb3738
FB
877 }
878#endif
90babde0 879
19a3da7f 880 return raw_open_common(bs, filename, flags, 0);
19cb3738
FB
881}
882
03ff3ca3 883#if defined(__linux__)
19cb3738
FB
884/* Note: we do not have a reliable method to detect if the floppy is
885 present. The current method is to try to open the floppy at every
886 I/O and to keep it opened during a few hundreds of ms. */
887static int fd_open(BlockDriverState *bs)
888{
889 BDRVRawState *s = bs->opaque;
890 int last_media_present;
891
892 if (s->type != FTYPE_FD)
893 return 0;
894 last_media_present = (s->fd >= 0);
5fafdf24 895 if (s->fd >= 0 &&
c57c846a 896 (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
2e1e79da 897 qemu_close(s->fd);
19cb3738
FB
898 s->fd = -1;
899#ifdef DEBUG_FLOPPY
900 printf("Floppy closed\n");
901#endif
902 }
903 if (s->fd < 0) {
5fafdf24 904 if (s->fd_got_error &&
c57c846a 905 (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) {
19cb3738
FB
906#ifdef DEBUG_FLOPPY
907 printf("No floppy (open delayed)\n");
908#endif
909 return -EIO;
910 }
6165f4d8 911 s->fd = qemu_open(bs->filename, s->open_flags & ~O_NONBLOCK);
19cb3738 912 if (s->fd < 0) {
c57c846a 913 s->fd_error_time = get_clock();
19cb3738
FB
914 s->fd_got_error = 1;
915 if (last_media_present)
916 s->fd_media_changed = 1;
917#ifdef DEBUG_FLOPPY
918 printf("No floppy\n");
919#endif
920 return -EIO;
921 }
922#ifdef DEBUG_FLOPPY
923 printf("Floppy opened\n");
924#endif
925 }
926 if (!last_media_present)
927 s->fd_media_changed = 1;
c57c846a 928 s->fd_open_time = get_clock();
19cb3738
FB
929 s->fd_got_error = 0;
930 return 0;
931}
19cb3738 932
63ec93db 933static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
985a03b0
TS
934{
935 BDRVRawState *s = bs->opaque;
936
937 return ioctl(s->fd, req, buf);
938}
221f715d 939
63ec93db 940static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
221f715d
AL
941 unsigned long int req, void *buf,
942 BlockDriverCompletionFunc *cb, void *opaque)
943{
f141eafe 944 BDRVRawState *s = bs->opaque;
221f715d 945
f141eafe
AL
946 if (fd_open(bs) < 0)
947 return NULL;
9ef91a67 948 return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
221f715d
AL
949}
950
a167ba50 951#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
9f23011a
BS
952static int fd_open(BlockDriverState *bs)
953{
954 BDRVRawState *s = bs->opaque;
955
956 /* this is just to ensure s->fd is sane (its called by io ops) */
957 if (s->fd >= 0)
958 return 0;
959 return -EIO;
960}
9f23011a 961#else /* !linux && !FreeBSD */
19cb3738 962
08af02e2
AL
963static int fd_open(BlockDriverState *bs)
964{
965 return 0;
966}
967
221f715d 968#endif /* !linux && !FreeBSD */
04eeb8b6 969
0e7e1989 970static int hdev_create(const char *filename, QEMUOptionParameter *options)
93c65b47
AL
971{
972 int fd;
973 int ret = 0;
974 struct stat stat_buf;
0e7e1989 975 int64_t total_size = 0;
93c65b47 976
0e7e1989
KW
977 /* Read out options */
978 while (options && options->name) {
979 if (!strcmp(options->name, "size")) {
9040385d 980 total_size = options->value.n / BDRV_SECTOR_SIZE;
0e7e1989
KW
981 }
982 options++;
983 }
93c65b47 984
6165f4d8 985 fd = qemu_open(filename, O_WRONLY | O_BINARY);
93c65b47 986 if (fd < 0)
57e69b7d 987 return -errno;
93c65b47
AL
988
989 if (fstat(fd, &stat_buf) < 0)
57e69b7d 990 ret = -errno;
4099df58 991 else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
57e69b7d 992 ret = -ENODEV;
9040385d 993 else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
93c65b47
AL
994 ret = -ENOSPC;
995
2e1e79da 996 qemu_close(fd);
93c65b47
AL
997 return ret;
998}
999
336c1c12
KW
1000static int hdev_has_zero_init(BlockDriverState *bs)
1001{
1002 return 0;
1003}
1004
5efa9d5a 1005static BlockDriver bdrv_host_device = {
0b4ce02e 1006 .format_name = "host_device",
84a12e66 1007 .protocol_name = "host_device",
0b4ce02e
KW
1008 .instance_size = sizeof(BDRVRawState),
1009 .bdrv_probe_device = hdev_probe_device,
66f82cee 1010 .bdrv_file_open = hdev_open,
0b4ce02e 1011 .bdrv_close = raw_close,
93c65b47 1012 .bdrv_create = hdev_create,
0b4ce02e 1013 .create_options = raw_create_options,
336c1c12 1014 .bdrv_has_zero_init = hdev_has_zero_init,
3b46e624 1015
f141eafe
AL
1016 .bdrv_aio_readv = raw_aio_readv,
1017 .bdrv_aio_writev = raw_aio_writev,
b2e12bc6 1018 .bdrv_aio_flush = raw_aio_flush,
3c529d93 1019
55b949c8 1020 .bdrv_truncate = raw_truncate,
e60f469c 1021 .bdrv_getlength = raw_getlength,
4a1d5e1f
FZ
1022 .bdrv_get_allocated_file_size
1023 = raw_get_allocated_file_size,
19cb3738 1024
f3a5d3f8 1025 /* generic scsi device */
63ec93db
CH
1026#ifdef __linux__
1027 .bdrv_ioctl = hdev_ioctl,
63ec93db
CH
1028 .bdrv_aio_ioctl = hdev_aio_ioctl,
1029#endif
f3a5d3f8
CH
1030};
1031
1032#ifdef __linux__
1033static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
1034{
1035 BDRVRawState *s = bs->opaque;
1036 int ret;
1037
f3a5d3f8 1038 s->type = FTYPE_FD;
f3a5d3f8 1039
19a3da7f
BS
1040 /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
1041 ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
f3a5d3f8
CH
1042 if (ret)
1043 return ret;
1044
1045 /* close fd so that we can reopen it as needed */
2e1e79da 1046 qemu_close(s->fd);
f3a5d3f8
CH
1047 s->fd = -1;
1048 s->fd_media_changed = 1;
1049
1050 return 0;
1051}
1052
508c7cb3
CH
1053static int floppy_probe_device(const char *filename)
1054{
2ebf7c4b
CR
1055 int fd, ret;
1056 int prio = 0;
1057 struct floppy_struct fdparam;
343f8568 1058 struct stat st;
2ebf7c4b 1059
e1740828
CB
1060 if (strstart(filename, "/dev/fd", NULL) &&
1061 !strstart(filename, "/dev/fdset/", NULL)) {
2ebf7c4b 1062 prio = 50;
e1740828 1063 }
2ebf7c4b 1064
6165f4d8 1065 fd = qemu_open(filename, O_RDONLY | O_NONBLOCK);
2ebf7c4b
CR
1066 if (fd < 0) {
1067 goto out;
1068 }
343f8568
JS
1069 ret = fstat(fd, &st);
1070 if (ret == -1 || !S_ISBLK(st.st_mode)) {
1071 goto outc;
1072 }
2ebf7c4b
CR
1073
1074 /* Attempt to detect via a floppy specific ioctl */
1075 ret = ioctl(fd, FDGETPRM, &fdparam);
1076 if (ret >= 0)
1077 prio = 100;
1078
343f8568 1079outc:
2e1e79da 1080 qemu_close(fd);
2ebf7c4b
CR
1081out:
1082 return prio;
508c7cb3
CH
1083}
1084
1085
f3a5d3f8
CH
1086static int floppy_is_inserted(BlockDriverState *bs)
1087{
1088 return fd_open(bs) >= 0;
1089}
1090
1091static int floppy_media_changed(BlockDriverState *bs)
1092{
1093 BDRVRawState *s = bs->opaque;
1094 int ret;
1095
1096 /*
1097 * XXX: we do not have a true media changed indication.
1098 * It does not work if the floppy is changed without trying to read it.
1099 */
1100 fd_open(bs);
1101 ret = s->fd_media_changed;
1102 s->fd_media_changed = 0;
1103#ifdef DEBUG_FLOPPY
1104 printf("Floppy changed=%d\n", ret);
1105#endif
1106 return ret;
1107}
1108
f36f3949 1109static void floppy_eject(BlockDriverState *bs, bool eject_flag)
f3a5d3f8
CH
1110{
1111 BDRVRawState *s = bs->opaque;
1112 int fd;
1113
1114 if (s->fd >= 0) {
2e1e79da 1115 qemu_close(s->fd);
f3a5d3f8
CH
1116 s->fd = -1;
1117 }
6165f4d8 1118 fd = qemu_open(bs->filename, s->open_flags | O_NONBLOCK);
f3a5d3f8
CH
1119 if (fd >= 0) {
1120 if (ioctl(fd, FDEJECT, 0) < 0)
1121 perror("FDEJECT");
2e1e79da 1122 qemu_close(fd);
f3a5d3f8 1123 }
f3a5d3f8
CH
1124}
1125
1126static BlockDriver bdrv_host_floppy = {
1127 .format_name = "host_floppy",
84a12e66 1128 .protocol_name = "host_floppy",
f3a5d3f8 1129 .instance_size = sizeof(BDRVRawState),
508c7cb3 1130 .bdrv_probe_device = floppy_probe_device,
66f82cee 1131 .bdrv_file_open = floppy_open,
f3a5d3f8
CH
1132 .bdrv_close = raw_close,
1133 .bdrv_create = hdev_create,
0b4ce02e 1134 .create_options = raw_create_options,
336c1c12 1135 .bdrv_has_zero_init = hdev_has_zero_init,
f3a5d3f8 1136
f3a5d3f8
CH
1137 .bdrv_aio_readv = raw_aio_readv,
1138 .bdrv_aio_writev = raw_aio_writev,
b2e12bc6 1139 .bdrv_aio_flush = raw_aio_flush,
f3a5d3f8 1140
55b949c8 1141 .bdrv_truncate = raw_truncate,
f3a5d3f8 1142 .bdrv_getlength = raw_getlength,
4a1d5e1f
FZ
1143 .bdrv_get_allocated_file_size
1144 = raw_get_allocated_file_size,
f3a5d3f8
CH
1145
1146 /* removable device support */
1147 .bdrv_is_inserted = floppy_is_inserted,
1148 .bdrv_media_changed = floppy_media_changed,
1149 .bdrv_eject = floppy_eject,
f3a5d3f8
CH
1150};
1151
1152static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1153{
1154 BDRVRawState *s = bs->opaque;
1155
f3a5d3f8
CH
1156 s->type = FTYPE_CD;
1157
19a3da7f
BS
1158 /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
1159 return raw_open_common(bs, filename, flags, O_NONBLOCK);
f3a5d3f8
CH
1160}
1161
508c7cb3
CH
1162static int cdrom_probe_device(const char *filename)
1163{
3baf720e
CR
1164 int fd, ret;
1165 int prio = 0;
343f8568 1166 struct stat st;
3baf720e 1167
6165f4d8 1168 fd = qemu_open(filename, O_RDONLY | O_NONBLOCK);
3baf720e
CR
1169 if (fd < 0) {
1170 goto out;
1171 }
343f8568
JS
1172 ret = fstat(fd, &st);
1173 if (ret == -1 || !S_ISBLK(st.st_mode)) {
1174 goto outc;
1175 }
3baf720e
CR
1176
1177 /* Attempt to detect via a CDROM specific ioctl */
1178 ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1179 if (ret >= 0)
1180 prio = 100;
1181
343f8568 1182outc:
2e1e79da 1183 qemu_close(fd);
3baf720e
CR
1184out:
1185 return prio;
508c7cb3
CH
1186}
1187
f3a5d3f8
CH
1188static int cdrom_is_inserted(BlockDriverState *bs)
1189{
1190 BDRVRawState *s = bs->opaque;
1191 int ret;
1192
1193 ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1194 if (ret == CDS_DISC_OK)
1195 return 1;
1196 return 0;
1197}
1198
f36f3949 1199static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
f3a5d3f8
CH
1200{
1201 BDRVRawState *s = bs->opaque;
1202
1203 if (eject_flag) {
1204 if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
1205 perror("CDROMEJECT");
1206 } else {
1207 if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
1208 perror("CDROMEJECT");
1209 }
f3a5d3f8
CH
1210}
1211
025e849a 1212static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
f3a5d3f8
CH
1213{
1214 BDRVRawState *s = bs->opaque;
1215
1216 if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
1217 /*
1218 * Note: an error can happen if the distribution automatically
1219 * mounts the CD-ROM
1220 */
1221 /* perror("CDROM_LOCKDOOR"); */
1222 }
f3a5d3f8
CH
1223}
1224
1225static BlockDriver bdrv_host_cdrom = {
1226 .format_name = "host_cdrom",
84a12e66 1227 .protocol_name = "host_cdrom",
f3a5d3f8 1228 .instance_size = sizeof(BDRVRawState),
508c7cb3 1229 .bdrv_probe_device = cdrom_probe_device,
66f82cee 1230 .bdrv_file_open = cdrom_open,
f3a5d3f8
CH
1231 .bdrv_close = raw_close,
1232 .bdrv_create = hdev_create,
0b4ce02e 1233 .create_options = raw_create_options,
336c1c12 1234 .bdrv_has_zero_init = hdev_has_zero_init,
f3a5d3f8 1235
f3a5d3f8
CH
1236 .bdrv_aio_readv = raw_aio_readv,
1237 .bdrv_aio_writev = raw_aio_writev,
b2e12bc6 1238 .bdrv_aio_flush = raw_aio_flush,
f3a5d3f8 1239
55b949c8 1240 .bdrv_truncate = raw_truncate,
f3a5d3f8 1241 .bdrv_getlength = raw_getlength,
4a1d5e1f
FZ
1242 .bdrv_get_allocated_file_size
1243 = raw_get_allocated_file_size,
f3a5d3f8
CH
1244
1245 /* removable device support */
1246 .bdrv_is_inserted = cdrom_is_inserted,
1247 .bdrv_eject = cdrom_eject,
025e849a 1248 .bdrv_lock_medium = cdrom_lock_medium,
f3a5d3f8
CH
1249
1250 /* generic scsi device */
63ec93db 1251 .bdrv_ioctl = hdev_ioctl,
63ec93db 1252 .bdrv_aio_ioctl = hdev_aio_ioctl,
f3a5d3f8
CH
1253};
1254#endif /* __linux__ */
1255
a167ba50 1256#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
f3a5d3f8
CH
1257static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1258{
1259 BDRVRawState *s = bs->opaque;
1260 int ret;
1261
1262 s->type = FTYPE_CD;
1263
19a3da7f 1264 ret = raw_open_common(bs, filename, flags, 0);
f3a5d3f8
CH
1265 if (ret)
1266 return ret;
1267
9b2260cb 1268 /* make sure the door isn't locked at this time */
f3a5d3f8
CH
1269 ioctl(s->fd, CDIOCALLOW);
1270 return 0;
1271}
1272
508c7cb3
CH
1273static int cdrom_probe_device(const char *filename)
1274{
1275 if (strstart(filename, "/dev/cd", NULL) ||
1276 strstart(filename, "/dev/acd", NULL))
1277 return 100;
1278 return 0;
1279}
1280
f3a5d3f8
CH
1281static int cdrom_reopen(BlockDriverState *bs)
1282{
1283 BDRVRawState *s = bs->opaque;
1284 int fd;
1285
1286 /*
1287 * Force reread of possibly changed/newly loaded disc,
1288 * FreeBSD seems to not notice sometimes...
1289 */
1290 if (s->fd >= 0)
2e1e79da 1291 qemu_close(s->fd);
6165f4d8 1292 fd = qemu_open(bs->filename, s->open_flags, 0644);
f3a5d3f8
CH
1293 if (fd < 0) {
1294 s->fd = -1;
1295 return -EIO;
1296 }
1297 s->fd = fd;
1298
9b2260cb 1299 /* make sure the door isn't locked at this time */
f3a5d3f8
CH
1300 ioctl(s->fd, CDIOCALLOW);
1301 return 0;
1302}
1303
1304static int cdrom_is_inserted(BlockDriverState *bs)
1305{
1306 return raw_getlength(bs) > 0;
1307}
1308
f36f3949 1309static void cdrom_eject(BlockDriverState *bs, bool eject_flag)
f3a5d3f8
CH
1310{
1311 BDRVRawState *s = bs->opaque;
1312
1313 if (s->fd < 0)
822e1cd1 1314 return;
f3a5d3f8
CH
1315
1316 (void) ioctl(s->fd, CDIOCALLOW);
1317
1318 if (eject_flag) {
1319 if (ioctl(s->fd, CDIOCEJECT) < 0)
1320 perror("CDIOCEJECT");
1321 } else {
1322 if (ioctl(s->fd, CDIOCCLOSE) < 0)
1323 perror("CDIOCCLOSE");
1324 }
1325
822e1cd1 1326 cdrom_reopen(bs);
f3a5d3f8
CH
1327}
1328
025e849a 1329static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
f3a5d3f8
CH
1330{
1331 BDRVRawState *s = bs->opaque;
1332
1333 if (s->fd < 0)
7bf37fed 1334 return;
f3a5d3f8
CH
1335 if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1336 /*
1337 * Note: an error can happen if the distribution automatically
1338 * mounts the CD-ROM
1339 */
1340 /* perror("CDROM_LOCKDOOR"); */
1341 }
f3a5d3f8
CH
1342}
1343
1344static BlockDriver bdrv_host_cdrom = {
1345 .format_name = "host_cdrom",
84a12e66 1346 .protocol_name = "host_cdrom",
f3a5d3f8 1347 .instance_size = sizeof(BDRVRawState),
508c7cb3 1348 .bdrv_probe_device = cdrom_probe_device,
66f82cee 1349 .bdrv_file_open = cdrom_open,
f3a5d3f8
CH
1350 .bdrv_close = raw_close,
1351 .bdrv_create = hdev_create,
0b4ce02e 1352 .create_options = raw_create_options,
336c1c12 1353 .bdrv_has_zero_init = hdev_has_zero_init,
f3a5d3f8 1354
f3a5d3f8
CH
1355 .bdrv_aio_readv = raw_aio_readv,
1356 .bdrv_aio_writev = raw_aio_writev,
b2e12bc6 1357 .bdrv_aio_flush = raw_aio_flush,
f3a5d3f8 1358
55b949c8 1359 .bdrv_truncate = raw_truncate,
f3a5d3f8 1360 .bdrv_getlength = raw_getlength,
4a1d5e1f
FZ
1361 .bdrv_get_allocated_file_size
1362 = raw_get_allocated_file_size,
f3a5d3f8 1363
19cb3738 1364 /* removable device support */
f3a5d3f8
CH
1365 .bdrv_is_inserted = cdrom_is_inserted,
1366 .bdrv_eject = cdrom_eject,
025e849a 1367 .bdrv_lock_medium = cdrom_lock_medium,
19cb3738 1368};
f3a5d3f8 1369#endif /* __FreeBSD__ */
5efa9d5a 1370
84a12e66 1371static void bdrv_file_init(void)
5efa9d5a 1372{
508c7cb3
CH
1373 /*
1374 * Register all the drivers. Note that order is important, the driver
1375 * registered last will get probed first.
1376 */
84a12e66 1377 bdrv_register(&bdrv_file);
5efa9d5a 1378 bdrv_register(&bdrv_host_device);
f3a5d3f8
CH
1379#ifdef __linux__
1380 bdrv_register(&bdrv_host_floppy);
1381 bdrv_register(&bdrv_host_cdrom);
1382#endif
a167ba50 1383#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
f3a5d3f8
CH
1384 bdrv_register(&bdrv_host_cdrom);
1385#endif
5efa9d5a
AL
1386}
1387
84a12e66 1388block_init(bdrv_file_init);