Statistics
| Branch: | Revision:

root / block / raw-posix.c @ a6599793

History | View | Annotate | Download (37.2 kB)

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 <signal.h>
47
#include <sys/dkio.h>
48
#endif
49
#ifdef __linux__
50
#include <sys/ioctl.h>
51
#include <sys/param.h>
52
#include <linux/cdrom.h>
53
#include <linux/fd.h>
54
#endif
55
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
56
#include <signal.h>
57
#include <sys/disk.h>
58
#include <sys/cdio.h>
59
#endif
60

    
61
#ifdef __OpenBSD__
62
#include <sys/ioctl.h>
63
#include <sys/disklabel.h>
64
#include <sys/dkio.h>
65
#endif
66

    
67
#ifdef __DragonFly__
68
#include <sys/ioctl.h>
69
#include <sys/diskslice.h>
70
#endif
71

    
72
#ifdef CONFIG_XFS
73
#include <xfs/xfs.h>
74
#endif
75

    
76
//#define DEBUG_FLOPPY
77

    
78
//#define DEBUG_BLOCK
79
#if defined(DEBUG_BLOCK)
80
#define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \
81
    { qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0)
82
#else
83
#define DEBUG_BLOCK_PRINT(formatCstr, ...)
84
#endif
85

    
86
/* OS X does not have O_DSYNC */
87
#ifndef O_DSYNC
88
#ifdef O_SYNC
89
#define O_DSYNC O_SYNC
90
#elif defined(O_FSYNC)
91
#define O_DSYNC O_FSYNC
92
#endif
93
#endif
94

    
95
/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
96
#ifndef O_DIRECT
97
#define O_DIRECT O_DSYNC
98
#endif
99

    
100
#define FTYPE_FILE   0
101
#define FTYPE_CD     1
102
#define FTYPE_FD     2
103

    
104
/* if the FD is not accessed during that time (in ns), we try to
105
   reopen it to see if the disk has been changed */
106
#define FD_OPEN_TIMEOUT (1000000000)
107

    
108
#define MAX_BLOCKSIZE        4096
109

    
110
typedef struct BDRVRawState {
111
    int fd;
112
    int type;
113
    int open_flags;
114
#if defined(__linux__)
115
    /* linux floppy specific */
116
    int64_t fd_open_time;
117
    int64_t fd_error_time;
118
    int fd_got_error;
119
    int fd_media_changed;
120
#endif
121
#ifdef CONFIG_LINUX_AIO
122
    int use_aio;
123
    void *aio_ctx;
124
#endif
125
    uint8_t *aligned_buf;
126
    unsigned aligned_buf_size;
127
#ifdef CONFIG_XFS
128
    bool is_xfs : 1;
129
#endif
130
} BDRVRawState;
131

    
132
static int fd_open(BlockDriverState *bs);
133
static int64_t raw_getlength(BlockDriverState *bs);
134

    
135
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
136
static int cdrom_reopen(BlockDriverState *bs);
137
#endif
138

    
139
static int raw_open_common(BlockDriverState *bs, const char *filename,
140
                           int bdrv_flags, int open_flags)
141
{
142
    BDRVRawState *s = bs->opaque;
143
    int fd, ret;
144

    
145
    s->open_flags = open_flags | O_BINARY;
146
    s->open_flags &= ~O_ACCMODE;
147
    if (bdrv_flags & BDRV_O_RDWR) {
148
        s->open_flags |= O_RDWR;
149
    } else {
150
        s->open_flags |= O_RDONLY;
151
    }
152

    
153
    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
154
     * and O_DIRECT for no caching. */
155
    if ((bdrv_flags & BDRV_O_NOCACHE))
156
        s->open_flags |= O_DIRECT;
157
    if (!(bdrv_flags & BDRV_O_CACHE_WB))
158
        s->open_flags |= O_DSYNC;
159

    
160
    s->fd = -1;
161
    fd = qemu_open(filename, s->open_flags, 0644);
162
    if (fd < 0) {
163
        ret = -errno;
164
        if (ret == -EROFS)
165
            ret = -EACCES;
166
        return ret;
167
    }
168
    s->fd = fd;
169
    s->aligned_buf = NULL;
170

    
171
    if ((bdrv_flags & BDRV_O_NOCACHE)) {
172
        /*
173
         * Allocate a buffer for read/modify/write cycles.  Chose the size
174
         * pessimistically as we don't know the block size yet.
175
         */
176
        s->aligned_buf_size = 32 * MAX_BLOCKSIZE;
177
        s->aligned_buf = qemu_memalign(MAX_BLOCKSIZE, s->aligned_buf_size);
178
        if (s->aligned_buf == NULL) {
179
            goto out_close;
180
        }
181
    }
182

    
183
#ifdef CONFIG_LINUX_AIO
184
    if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
185
                      (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
186

    
187
        /* We're falling back to POSIX AIO in some cases */
188
        paio_init();
189

    
190
        s->aio_ctx = laio_init();
191
        if (!s->aio_ctx) {
192
            goto out_free_buf;
193
        }
194
        s->use_aio = 1;
195
    } else
196
#endif
197
    {
198
        if (paio_init() < 0) {
199
            goto out_free_buf;
200
        }
201
#ifdef CONFIG_LINUX_AIO
202
        s->use_aio = 0;
203
#endif
204
    }
205

    
206
#ifdef CONFIG_XFS
207
    if (platform_test_xfs_fd(s->fd)) {
208
        s->is_xfs = 1;
209
    }
210
#endif
211

    
212
    return 0;
213

    
214
out_free_buf:
215
    qemu_vfree(s->aligned_buf);
216
out_close:
217
    close(fd);
218
    return -errno;
219
}
220

    
221
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
222
{
223
    BDRVRawState *s = bs->opaque;
224

    
225
    s->type = FTYPE_FILE;
226
    return raw_open_common(bs, filename, flags, 0);
227
}
228

    
229
/* XXX: use host sector size if necessary with:
230
#ifdef DIOCGSECTORSIZE
231
        {
232
            unsigned int sectorsize = 512;
233
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
234
                sectorsize > bufsize)
235
                bufsize = sectorsize;
236
        }
237
#endif
238
#ifdef CONFIG_COCOA
239
        uint32_t blockSize = 512;
240
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
241
            bufsize = blockSize;
242
        }
243
#endif
244
*/
245

    
246
/*
247
 * offset and count are in bytes, but must be multiples of 512 for files
248
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
249
 *
250
 * This function may be called without alignment if the caller ensures
251
 * that O_DIRECT is not in effect.
252
 */
253
static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
254
                     uint8_t *buf, int count)
255
{
256
    BDRVRawState *s = bs->opaque;
257
    int ret;
258

    
259
    ret = fd_open(bs);
260
    if (ret < 0)
261
        return ret;
262

    
263
    ret = pread(s->fd, buf, count, offset);
264
    if (ret == count)
265
        return ret;
266

    
267
    /* Allow reads beyond the end (needed for pwrite) */
268
    if ((ret == 0) && bs->growable) {
269
        int64_t size = raw_getlength(bs);
270
        if (offset >= size) {
271
            memset(buf, 0, count);
272
            return count;
273
        }
274
    }
275

    
276
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
277
                      "] read failed %d : %d = %s\n",
278
                      s->fd, bs->filename, offset, buf, count,
279
                      bs->total_sectors, ret, errno, strerror(errno));
280

    
281
    /* Try harder for CDrom. */
282
    if (s->type != FTYPE_FILE) {
283
        ret = pread(s->fd, buf, count, offset);
284
        if (ret == count)
285
            return ret;
286
        ret = pread(s->fd, buf, count, offset);
287
        if (ret == count)
288
            return ret;
289

    
290
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
291
                          "] retry read failed %d : %d = %s\n",
292
                          s->fd, bs->filename, offset, buf, count,
293
                          bs->total_sectors, ret, errno, strerror(errno));
294
    }
295

    
296
    return  (ret < 0) ? -errno : ret;
297
}
298

    
299
/*
300
 * offset and count are in bytes, but must be multiples of the sector size
301
 * for files opened with O_DIRECT. buf must be aligned to sector size bytes
302
 * then.
303
 *
304
 * This function may be called without alignment if the caller ensures
305
 * that O_DIRECT is not in effect.
306
 */
307
static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
308
                      const uint8_t *buf, int count)
309
{
310
    BDRVRawState *s = bs->opaque;
311
    int ret;
312

    
313
    ret = fd_open(bs);
314
    if (ret < 0)
315
        return -errno;
316

    
317
    ret = pwrite(s->fd, buf, count, offset);
318
    if (ret == count)
319
        return ret;
320

    
321
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
322
                      "] write failed %d : %d = %s\n",
323
                      s->fd, bs->filename, offset, buf, count,
324
                      bs->total_sectors, ret, errno, strerror(errno));
325

    
326
    return  (ret < 0) ? -errno : ret;
327
}
328

    
329

    
330
/*
331
 * offset and count are in bytes and possibly not aligned. For files opened
332
 * with O_DIRECT, necessary alignments are ensured before calling
333
 * raw_pread_aligned to do the actual read.
334
 */
335
static int raw_pread(BlockDriverState *bs, int64_t offset,
336
                     uint8_t *buf, int count)
337
{
338
    BDRVRawState *s = bs->opaque;
339
    unsigned sector_mask = bs->buffer_alignment - 1;
340
    int size, ret, shift, sum;
341

    
342
    sum = 0;
343

    
344
    if (s->aligned_buf != NULL)  {
345

    
346
        if (offset & sector_mask) {
347
            /* align offset on a sector size bytes boundary */
348

    
349
            shift = offset & sector_mask;
350
            size = (shift + count + sector_mask) & ~sector_mask;
351
            if (size > s->aligned_buf_size)
352
                size = s->aligned_buf_size;
353
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
354
            if (ret < 0)
355
                return ret;
356

    
357
            size = bs->buffer_alignment - shift;
358
            if (size > count)
359
                size = count;
360
            memcpy(buf, s->aligned_buf + shift, size);
361

    
362
            buf += size;
363
            offset += size;
364
            count -= size;
365
            sum += size;
366

    
367
            if (count == 0)
368
                return sum;
369
        }
370
        if (count & sector_mask || (uintptr_t) buf & sector_mask) {
371

    
372
            /* read on aligned buffer */
373

    
374
            while (count) {
375

    
376
                size = (count + sector_mask) & ~sector_mask;
377
                if (size > s->aligned_buf_size)
378
                    size = s->aligned_buf_size;
379

    
380
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
381
                if (ret < 0) {
382
                    return ret;
383
                } else if (ret == 0) {
384
                    fprintf(stderr, "raw_pread: read beyond end of file\n");
385
                    abort();
386
                }
387

    
388
                size = ret;
389
                if (size > count)
390
                    size = count;
391

    
392
                memcpy(buf, s->aligned_buf, size);
393

    
394
                buf += size;
395
                offset += size;
396
                count -= size;
397
                sum += size;
398
            }
399

    
400
            return sum;
401
        }
402
    }
403

    
404
    return raw_pread_aligned(bs, offset, buf, count) + sum;
405
}
406

    
407
static int raw_read(BlockDriverState *bs, int64_t sector_num,
408
                    uint8_t *buf, int nb_sectors)
409
{
410
    int ret;
411

    
412
    ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
413
                    nb_sectors * BDRV_SECTOR_SIZE);
414
    if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
415
        ret = 0;
416
    return ret;
417
}
418

    
419
/*
420
 * offset and count are in bytes and possibly not aligned. For files opened
421
 * with O_DIRECT, necessary alignments are ensured before calling
422
 * raw_pwrite_aligned to do the actual write.
423
 */
424
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
425
                      const uint8_t *buf, int count)
426
{
427
    BDRVRawState *s = bs->opaque;
428
    unsigned sector_mask = bs->buffer_alignment - 1;
429
    int size, ret, shift, sum;
430

    
431
    sum = 0;
432

    
433
    if (s->aligned_buf != NULL) {
434

    
435
        if (offset & sector_mask) {
436
            /* align offset on a sector size bytes boundary */
437
            shift = offset & sector_mask;
438
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf,
439
                                    bs->buffer_alignment);
440
            if (ret < 0)
441
                return ret;
442

    
443
            size = bs->buffer_alignment - shift;
444
            if (size > count)
445
                size = count;
446
            memcpy(s->aligned_buf + shift, buf, size);
447

    
448
            ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf,
449
                                     bs->buffer_alignment);
450
            if (ret < 0)
451
                return ret;
452

    
453
            buf += size;
454
            offset += size;
455
            count -= size;
456
            sum += size;
457

    
458
            if (count == 0)
459
                return sum;
460
        }
461
        if (count & sector_mask || (uintptr_t) buf & sector_mask) {
462

    
463
            while ((size = (count & ~sector_mask)) != 0) {
464

    
465
                if (size > s->aligned_buf_size)
466
                    size = s->aligned_buf_size;
467

    
468
                memcpy(s->aligned_buf, buf, size);
469

    
470
                ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
471
                if (ret < 0)
472
                    return ret;
473

    
474
                buf += ret;
475
                offset += ret;
476
                count -= ret;
477
                sum += ret;
478
            }
479
            /* here, count < sector_size because (count & ~sector_mask) == 0 */
480
            if (count) {
481
                ret = raw_pread_aligned(bs, offset, s->aligned_buf,
482
                                     bs->buffer_alignment);
483
                if (ret < 0)
484
                    return ret;
485
                 memcpy(s->aligned_buf, buf, count);
486

    
487
                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf,
488
                                     bs->buffer_alignment);
489
                 if (ret < 0)
490
                     return ret;
491
                 if (count < ret)
492
                     ret = count;
493

    
494
                 sum += ret;
495
            }
496
            return sum;
497
        }
498
    }
499
    return raw_pwrite_aligned(bs, offset, buf, count) + sum;
500
}
501

    
502
static int raw_write(BlockDriverState *bs, int64_t sector_num,
503
                     const uint8_t *buf, int nb_sectors)
504
{
505
    int ret;
506
    ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf,
507
                     nb_sectors * BDRV_SECTOR_SIZE);
508
    if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
509
        ret = 0;
510
    return ret;
511
}
512

    
513
/*
514
 * Check if all memory in this vector is sector aligned.
515
 */
516
static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
517
{
518
    int i;
519

    
520
    for (i = 0; i < qiov->niov; i++) {
521
        if ((uintptr_t) qiov->iov[i].iov_base % bs->buffer_alignment) {
522
            return 0;
523
        }
524
    }
525

    
526
    return 1;
527
}
528

    
529
static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
530
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
531
        BlockDriverCompletionFunc *cb, void *opaque, int type)
532
{
533
    BDRVRawState *s = bs->opaque;
534

    
535
    if (fd_open(bs) < 0)
536
        return NULL;
537

    
538
    /*
539
     * If O_DIRECT is used the buffer needs to be aligned on a sector
540
     * boundary.  Check if this is the case or telll the low-level
541
     * driver that it needs to copy the buffer.
542
     */
543
    if (s->aligned_buf) {
544
        if (!qiov_is_aligned(bs, qiov)) {
545
            type |= QEMU_AIO_MISALIGNED;
546
#ifdef CONFIG_LINUX_AIO
547
        } else if (s->use_aio) {
548
            return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
549
                               nb_sectors, cb, opaque, type);
550
#endif
551
        }
552
    }
553

    
554
    return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
555
                       cb, opaque, type);
556
}
557

    
558
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
559
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
560
        BlockDriverCompletionFunc *cb, void *opaque)
561
{
562
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
563
                          cb, opaque, QEMU_AIO_READ);
564
}
565

    
566
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
567
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
568
        BlockDriverCompletionFunc *cb, void *opaque)
569
{
570
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
571
                          cb, opaque, QEMU_AIO_WRITE);
572
}
573

    
574
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
575
        BlockDriverCompletionFunc *cb, void *opaque)
576
{
577
    BDRVRawState *s = bs->opaque;
578

    
579
    if (fd_open(bs) < 0)
580
        return NULL;
581

    
582
    return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
583
}
584

    
585
static void raw_close(BlockDriverState *bs)
586
{
587
    BDRVRawState *s = bs->opaque;
588
    if (s->fd >= 0) {
589
        close(s->fd);
590
        s->fd = -1;
591
        if (s->aligned_buf != NULL)
592
            qemu_vfree(s->aligned_buf);
593
    }
594
}
595

    
596
static int raw_truncate(BlockDriverState *bs, int64_t offset)
597
{
598
    BDRVRawState *s = bs->opaque;
599
    if (s->type != FTYPE_FILE)
600
        return -ENOTSUP;
601
    if (ftruncate(s->fd, offset) < 0)
602
        return -errno;
603
    return 0;
604
}
605

    
606
#ifdef __OpenBSD__
607
static int64_t raw_getlength(BlockDriverState *bs)
608
{
609
    BDRVRawState *s = bs->opaque;
610
    int fd = s->fd;
611
    struct stat st;
612

    
613
    if (fstat(fd, &st))
614
        return -1;
615
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
616
        struct disklabel dl;
617

    
618
        if (ioctl(fd, DIOCGDINFO, &dl))
619
            return -1;
620
        return (uint64_t)dl.d_secsize *
621
            dl.d_partitions[DISKPART(st.st_rdev)].p_size;
622
    } else
623
        return st.st_size;
624
}
625
#elif defined(__sun__)
626
static int64_t raw_getlength(BlockDriverState *bs)
627
{
628
    BDRVRawState *s = bs->opaque;
629
    struct dk_minfo minfo;
630
    int ret;
631

    
632
    ret = fd_open(bs);
633
    if (ret < 0) {
634
        return ret;
635
    }
636

    
637
    /*
638
     * Use the DKIOCGMEDIAINFO ioctl to read the size.
639
     */
640
    ret = ioctl(s->fd, DKIOCGMEDIAINFO, &minfo);
641
    if (ret != -1) {
642
        return minfo.dki_lbsize * minfo.dki_capacity;
643
    }
644

    
645
    /*
646
     * There are reports that lseek on some devices fails, but
647
     * irc discussion said that contingency on contingency was overkill.
648
     */
649
    return lseek(s->fd, 0, SEEK_END);
650
}
651
#elif defined(CONFIG_BSD)
652
static int64_t raw_getlength(BlockDriverState *bs)
653
{
654
    BDRVRawState *s = bs->opaque;
655
    int fd = s->fd;
656
    int64_t size;
657
    struct stat sb;
658
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
659
    int reopened = 0;
660
#endif
661
    int ret;
662

    
663
    ret = fd_open(bs);
664
    if (ret < 0)
665
        return ret;
666

    
667
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
668
again:
669
#endif
670
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
671
#ifdef DIOCGMEDIASIZE
672
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
673
#elif defined(DIOCGPART)
674
        {
675
                struct partinfo pi;
676
                if (ioctl(fd, DIOCGPART, &pi) == 0)
677
                        size = pi.media_size;
678
                else
679
                        size = 0;
680
        }
681
        if (size == 0)
682
#endif
683
#ifdef CONFIG_COCOA
684
        size = LONG_LONG_MAX;
685
#else
686
        size = lseek(fd, 0LL, SEEK_END);
687
#endif
688
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
689
        switch(s->type) {
690
        case FTYPE_CD:
691
            /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
692
            if (size == 2048LL * (unsigned)-1)
693
                size = 0;
694
            /* XXX no disc?  maybe we need to reopen... */
695
            if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
696
                reopened = 1;
697
                goto again;
698
            }
699
        }
700
#endif
701
    } else {
702
        size = lseek(fd, 0, SEEK_END);
703
    }
704
    return size;
705
}
706
#else
707
static int64_t raw_getlength(BlockDriverState *bs)
708
{
709
    BDRVRawState *s = bs->opaque;
710
    int ret;
711

    
712
    ret = fd_open(bs);
713
    if (ret < 0) {
714
        return ret;
715
    }
716

    
717
    return lseek(s->fd, 0, SEEK_END);
718
}
719
#endif
720

    
721
static int raw_create(const char *filename, QEMUOptionParameter *options)
722
{
723
    int fd;
724
    int result = 0;
725
    int64_t total_size = 0;
726

    
727
    /* Read out options */
728
    while (options && options->name) {
729
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
730
            total_size = options->value.n / BDRV_SECTOR_SIZE;
731
        }
732
        options++;
733
    }
734

    
735
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
736
              0644);
737
    if (fd < 0) {
738
        result = -errno;
739
    } else {
740
        if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
741
            result = -errno;
742
        }
743
        if (close(fd) != 0) {
744
            result = -errno;
745
        }
746
    }
747
    return result;
748
}
749

    
750
static int raw_flush(BlockDriverState *bs)
751
{
752
    BDRVRawState *s = bs->opaque;
753
    return qemu_fdatasync(s->fd);
754
}
755

    
756
#ifdef CONFIG_XFS
757
static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
758
{
759
    struct xfs_flock64 fl;
760

    
761
    memset(&fl, 0, sizeof(fl));
762
    fl.l_whence = SEEK_SET;
763
    fl.l_start = sector_num << 9;
764
    fl.l_len = (int64_t)nb_sectors << 9;
765

    
766
    if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
767
        DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
768
        return -errno;
769
    }
770

    
771
    return 0;
772
}
773
#endif
774

    
775
static int raw_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
776
{
777
#ifdef CONFIG_XFS
778
    BDRVRawState *s = bs->opaque;
779

    
780
    if (s->is_xfs) {
781
        return xfs_discard(s, sector_num, nb_sectors);
782
    }
783
#endif
784

    
785
    return 0;
786
}
787

    
788
static QEMUOptionParameter raw_create_options[] = {
789
    {
790
        .name = BLOCK_OPT_SIZE,
791
        .type = OPT_SIZE,
792
        .help = "Virtual disk size"
793
    },
794
    { NULL }
795
};
796

    
797
static BlockDriver bdrv_file = {
798
    .format_name = "file",
799
    .protocol_name = "file",
800
    .instance_size = sizeof(BDRVRawState),
801
    .bdrv_probe = NULL, /* no probe for protocols */
802
    .bdrv_file_open = raw_open,
803
    .bdrv_read = raw_read,
804
    .bdrv_write = raw_write,
805
    .bdrv_close = raw_close,
806
    .bdrv_create = raw_create,
807
    .bdrv_flush = raw_flush,
808
    .bdrv_discard = raw_discard,
809

    
810
    .bdrv_aio_readv = raw_aio_readv,
811
    .bdrv_aio_writev = raw_aio_writev,
812
    .bdrv_aio_flush = raw_aio_flush,
813

    
814
    .bdrv_truncate = raw_truncate,
815
    .bdrv_getlength = raw_getlength,
816

    
817
    .create_options = raw_create_options,
818
};
819

    
820
/***********************************************/
821
/* host device */
822

    
823
#ifdef CONFIG_COCOA
824
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
825
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
826

    
827
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
828
{
829
    kern_return_t       kernResult;
830
    mach_port_t     masterPort;
831
    CFMutableDictionaryRef  classesToMatch;
832

    
833
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
834
    if ( KERN_SUCCESS != kernResult ) {
835
        printf( "IOMasterPort returned %d\n", kernResult );
836
    }
837

    
838
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
839
    if ( classesToMatch == NULL ) {
840
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
841
    } else {
842
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
843
    }
844
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
845
    if ( KERN_SUCCESS != kernResult )
846
    {
847
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
848
    }
849

    
850
    return kernResult;
851
}
852

    
853
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
854
{
855
    io_object_t     nextMedia;
856
    kern_return_t   kernResult = KERN_FAILURE;
857
    *bsdPath = '\0';
858
    nextMedia = IOIteratorNext( mediaIterator );
859
    if ( nextMedia )
860
    {
861
        CFTypeRef   bsdPathAsCFString;
862
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
863
        if ( bsdPathAsCFString ) {
864
            size_t devPathLength;
865
            strcpy( bsdPath, _PATH_DEV );
866
            strcat( bsdPath, "r" );
867
            devPathLength = strlen( bsdPath );
868
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
869
                kernResult = KERN_SUCCESS;
870
            }
871
            CFRelease( bsdPathAsCFString );
872
        }
873
        IOObjectRelease( nextMedia );
874
    }
875

    
876
    return kernResult;
877
}
878

    
879
#endif
880

    
881
static int hdev_probe_device(const char *filename)
882
{
883
    struct stat st;
884

    
885
    /* allow a dedicated CD-ROM driver to match with a higher priority */
886
    if (strstart(filename, "/dev/cdrom", NULL))
887
        return 50;
888

    
889
    if (stat(filename, &st) >= 0 &&
890
            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
891
        return 100;
892
    }
893

    
894
    return 0;
895
}
896

    
897
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
898
{
899
    BDRVRawState *s = bs->opaque;
900

    
901
#ifdef CONFIG_COCOA
902
    if (strstart(filename, "/dev/cdrom", NULL)) {
903
        kern_return_t kernResult;
904
        io_iterator_t mediaIterator;
905
        char bsdPath[ MAXPATHLEN ];
906
        int fd;
907

    
908
        kernResult = FindEjectableCDMedia( &mediaIterator );
909
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
910

    
911
        if ( bsdPath[ 0 ] != '\0' ) {
912
            strcat(bsdPath,"s0");
913
            /* some CDs don't have a partition 0 */
914
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
915
            if (fd < 0) {
916
                bsdPath[strlen(bsdPath)-1] = '1';
917
            } else {
918
                close(fd);
919
            }
920
            filename = bsdPath;
921
        }
922

    
923
        if ( mediaIterator )
924
            IOObjectRelease( mediaIterator );
925
    }
926
#endif
927

    
928
    s->type = FTYPE_FILE;
929
#if defined(__linux__)
930
    {
931
        char resolved_path[ MAXPATHLEN ], *temp;
932

    
933
        temp = realpath(filename, resolved_path);
934
        if (temp && strstart(temp, "/dev/sg", NULL)) {
935
            bs->sg = 1;
936
        }
937
    }
938
#endif
939

    
940
    return raw_open_common(bs, filename, flags, 0);
941
}
942

    
943
#if defined(__linux__)
944
/* Note: we do not have a reliable method to detect if the floppy is
945
   present. The current method is to try to open the floppy at every
946
   I/O and to keep it opened during a few hundreds of ms. */
947
static int fd_open(BlockDriverState *bs)
948
{
949
    BDRVRawState *s = bs->opaque;
950
    int last_media_present;
951

    
952
    if (s->type != FTYPE_FD)
953
        return 0;
954
    last_media_present = (s->fd >= 0);
955
    if (s->fd >= 0 &&
956
        (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
957
        close(s->fd);
958
        s->fd = -1;
959
#ifdef DEBUG_FLOPPY
960
        printf("Floppy closed\n");
961
#endif
962
    }
963
    if (s->fd < 0) {
964
        if (s->fd_got_error &&
965
            (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) {
966
#ifdef DEBUG_FLOPPY
967
            printf("No floppy (open delayed)\n");
968
#endif
969
            return -EIO;
970
        }
971
        s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
972
        if (s->fd < 0) {
973
            s->fd_error_time = get_clock();
974
            s->fd_got_error = 1;
975
            if (last_media_present)
976
                s->fd_media_changed = 1;
977
#ifdef DEBUG_FLOPPY
978
            printf("No floppy\n");
979
#endif
980
            return -EIO;
981
        }
982
#ifdef DEBUG_FLOPPY
983
        printf("Floppy opened\n");
984
#endif
985
    }
986
    if (!last_media_present)
987
        s->fd_media_changed = 1;
988
    s->fd_open_time = get_clock();
989
    s->fd_got_error = 0;
990
    return 0;
991
}
992

    
993
static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
994
{
995
    BDRVRawState *s = bs->opaque;
996

    
997
    return ioctl(s->fd, req, buf);
998
}
999

    
1000
static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
1001
        unsigned long int req, void *buf,
1002
        BlockDriverCompletionFunc *cb, void *opaque)
1003
{
1004
    BDRVRawState *s = bs->opaque;
1005

    
1006
    if (fd_open(bs) < 0)
1007
        return NULL;
1008
    return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
1009
}
1010

    
1011
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1012
static int fd_open(BlockDriverState *bs)
1013
{
1014
    BDRVRawState *s = bs->opaque;
1015

    
1016
    /* this is just to ensure s->fd is sane (its called by io ops) */
1017
    if (s->fd >= 0)
1018
        return 0;
1019
    return -EIO;
1020
}
1021
#else /* !linux && !FreeBSD */
1022

    
1023
static int fd_open(BlockDriverState *bs)
1024
{
1025
    return 0;
1026
}
1027

    
1028
#endif /* !linux && !FreeBSD */
1029

    
1030
static int hdev_create(const char *filename, QEMUOptionParameter *options)
1031
{
1032
    int fd;
1033
    int ret = 0;
1034
    struct stat stat_buf;
1035
    int64_t total_size = 0;
1036

    
1037
    /* Read out options */
1038
    while (options && options->name) {
1039
        if (!strcmp(options->name, "size")) {
1040
            total_size = options->value.n / BDRV_SECTOR_SIZE;
1041
        }
1042
        options++;
1043
    }
1044

    
1045
    fd = open(filename, O_WRONLY | O_BINARY);
1046
    if (fd < 0)
1047
        return -errno;
1048

    
1049
    if (fstat(fd, &stat_buf) < 0)
1050
        ret = -errno;
1051
    else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
1052
        ret = -ENODEV;
1053
    else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
1054
        ret = -ENOSPC;
1055

    
1056
    close(fd);
1057
    return ret;
1058
}
1059

    
1060
static int hdev_has_zero_init(BlockDriverState *bs)
1061
{
1062
    return 0;
1063
}
1064

    
1065
static BlockDriver bdrv_host_device = {
1066
    .format_name        = "host_device",
1067
    .protocol_name        = "host_device",
1068
    .instance_size      = sizeof(BDRVRawState),
1069
    .bdrv_probe_device  = hdev_probe_device,
1070
    .bdrv_file_open     = hdev_open,
1071
    .bdrv_close         = raw_close,
1072
    .bdrv_create        = hdev_create,
1073
    .create_options     = raw_create_options,
1074
    .bdrv_has_zero_init = hdev_has_zero_init,
1075
    .bdrv_flush         = raw_flush,
1076

    
1077
    .bdrv_aio_readv        = raw_aio_readv,
1078
    .bdrv_aio_writev        = raw_aio_writev,
1079
    .bdrv_aio_flush        = raw_aio_flush,
1080

    
1081
    .bdrv_read          = raw_read,
1082
    .bdrv_write         = raw_write,
1083
    .bdrv_getlength        = raw_getlength,
1084

    
1085
    /* generic scsi device */
1086
#ifdef __linux__
1087
    .bdrv_ioctl         = hdev_ioctl,
1088
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1089
#endif
1090
};
1091

    
1092
#ifdef __linux__
1093
static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
1094
{
1095
    BDRVRawState *s = bs->opaque;
1096
    int ret;
1097

    
1098
    s->type = FTYPE_FD;
1099

    
1100
    /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
1101
    ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
1102
    if (ret)
1103
        return ret;
1104

    
1105
    /* close fd so that we can reopen it as needed */
1106
    close(s->fd);
1107
    s->fd = -1;
1108
    s->fd_media_changed = 1;
1109

    
1110
    return 0;
1111
}
1112

    
1113
static int floppy_probe_device(const char *filename)
1114
{
1115
    int fd, ret;
1116
    int prio = 0;
1117
    struct floppy_struct fdparam;
1118

    
1119
    if (strstart(filename, "/dev/fd", NULL))
1120
        prio = 50;
1121

    
1122
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1123
    if (fd < 0) {
1124
        goto out;
1125
    }
1126

    
1127
    /* Attempt to detect via a floppy specific ioctl */
1128
    ret = ioctl(fd, FDGETPRM, &fdparam);
1129
    if (ret >= 0)
1130
        prio = 100;
1131

    
1132
    close(fd);
1133
out:
1134
    return prio;
1135
}
1136

    
1137

    
1138
static int floppy_is_inserted(BlockDriverState *bs)
1139
{
1140
    return fd_open(bs) >= 0;
1141
}
1142

    
1143
static int floppy_media_changed(BlockDriverState *bs)
1144
{
1145
    BDRVRawState *s = bs->opaque;
1146
    int ret;
1147

    
1148
    /*
1149
     * XXX: we do not have a true media changed indication.
1150
     * It does not work if the floppy is changed without trying to read it.
1151
     */
1152
    fd_open(bs);
1153
    ret = s->fd_media_changed;
1154
    s->fd_media_changed = 0;
1155
#ifdef DEBUG_FLOPPY
1156
    printf("Floppy changed=%d\n", ret);
1157
#endif
1158
    return ret;
1159
}
1160

    
1161
static int floppy_eject(BlockDriverState *bs, int eject_flag)
1162
{
1163
    BDRVRawState *s = bs->opaque;
1164
    int fd;
1165

    
1166
    if (s->fd >= 0) {
1167
        close(s->fd);
1168
        s->fd = -1;
1169
    }
1170
    fd = open(bs->filename, s->open_flags | O_NONBLOCK);
1171
    if (fd >= 0) {
1172
        if (ioctl(fd, FDEJECT, 0) < 0)
1173
            perror("FDEJECT");
1174
        close(fd);
1175
    }
1176

    
1177
    return 0;
1178
}
1179

    
1180
static BlockDriver bdrv_host_floppy = {
1181
    .format_name        = "host_floppy",
1182
    .protocol_name      = "host_floppy",
1183
    .instance_size      = sizeof(BDRVRawState),
1184
    .bdrv_probe_device        = floppy_probe_device,
1185
    .bdrv_file_open     = floppy_open,
1186
    .bdrv_close         = raw_close,
1187
    .bdrv_create        = hdev_create,
1188
    .create_options     = raw_create_options,
1189
    .bdrv_has_zero_init = hdev_has_zero_init,
1190
    .bdrv_flush         = raw_flush,
1191

    
1192
    .bdrv_aio_readv     = raw_aio_readv,
1193
    .bdrv_aio_writev    = raw_aio_writev,
1194
    .bdrv_aio_flush        = raw_aio_flush,
1195

    
1196
    .bdrv_read          = raw_read,
1197
    .bdrv_write         = raw_write,
1198
    .bdrv_getlength        = raw_getlength,
1199

    
1200
    /* removable device support */
1201
    .bdrv_is_inserted   = floppy_is_inserted,
1202
    .bdrv_media_changed = floppy_media_changed,
1203
    .bdrv_eject         = floppy_eject,
1204
};
1205

    
1206
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1207
{
1208
    BDRVRawState *s = bs->opaque;
1209

    
1210
    s->type = FTYPE_CD;
1211

    
1212
    /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
1213
    return raw_open_common(bs, filename, flags, O_NONBLOCK);
1214
}
1215

    
1216
static int cdrom_probe_device(const char *filename)
1217
{
1218
    int fd, ret;
1219
    int prio = 0;
1220

    
1221
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1222
    if (fd < 0) {
1223
        goto out;
1224
    }
1225

    
1226
    /* Attempt to detect via a CDROM specific ioctl */
1227
    ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1228
    if (ret >= 0)
1229
        prio = 100;
1230

    
1231
    close(fd);
1232
out:
1233
    return prio;
1234
}
1235

    
1236
static int cdrom_is_inserted(BlockDriverState *bs)
1237
{
1238
    BDRVRawState *s = bs->opaque;
1239
    int ret;
1240

    
1241
    ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1242
    if (ret == CDS_DISC_OK)
1243
        return 1;
1244
    return 0;
1245
}
1246

    
1247
static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1248
{
1249
    BDRVRawState *s = bs->opaque;
1250

    
1251
    if (eject_flag) {
1252
        if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
1253
            perror("CDROMEJECT");
1254
    } else {
1255
        if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
1256
            perror("CDROMEJECT");
1257
    }
1258

    
1259
    return 0;
1260
}
1261

    
1262
static int cdrom_set_locked(BlockDriverState *bs, int locked)
1263
{
1264
    BDRVRawState *s = bs->opaque;
1265

    
1266
    if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
1267
        /*
1268
         * Note: an error can happen if the distribution automatically
1269
         * mounts the CD-ROM
1270
         */
1271
        /* perror("CDROM_LOCKDOOR"); */
1272
    }
1273

    
1274
    return 0;
1275
}
1276

    
1277
static BlockDriver bdrv_host_cdrom = {
1278
    .format_name        = "host_cdrom",
1279
    .protocol_name      = "host_cdrom",
1280
    .instance_size      = sizeof(BDRVRawState),
1281
    .bdrv_probe_device        = cdrom_probe_device,
1282
    .bdrv_file_open     = cdrom_open,
1283
    .bdrv_close         = raw_close,
1284
    .bdrv_create        = hdev_create,
1285
    .create_options     = raw_create_options,
1286
    .bdrv_has_zero_init = hdev_has_zero_init,
1287
    .bdrv_flush         = raw_flush,
1288

    
1289
    .bdrv_aio_readv     = raw_aio_readv,
1290
    .bdrv_aio_writev    = raw_aio_writev,
1291
    .bdrv_aio_flush        = raw_aio_flush,
1292

    
1293
    .bdrv_read          = raw_read,
1294
    .bdrv_write         = raw_write,
1295
    .bdrv_getlength     = raw_getlength,
1296

    
1297
    /* removable device support */
1298
    .bdrv_is_inserted   = cdrom_is_inserted,
1299
    .bdrv_eject         = cdrom_eject,
1300
    .bdrv_set_locked    = cdrom_set_locked,
1301

    
1302
    /* generic scsi device */
1303
    .bdrv_ioctl         = hdev_ioctl,
1304
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1305
};
1306
#endif /* __linux__ */
1307

    
1308
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1309
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1310
{
1311
    BDRVRawState *s = bs->opaque;
1312
    int ret;
1313

    
1314
    s->type = FTYPE_CD;
1315

    
1316
    ret = raw_open_common(bs, filename, flags, 0);
1317
    if (ret)
1318
        return ret;
1319

    
1320
    /* make sure the door isnt locked at this time */
1321
    ioctl(s->fd, CDIOCALLOW);
1322
    return 0;
1323
}
1324

    
1325
static int cdrom_probe_device(const char *filename)
1326
{
1327
    if (strstart(filename, "/dev/cd", NULL) ||
1328
            strstart(filename, "/dev/acd", NULL))
1329
        return 100;
1330
    return 0;
1331
}
1332

    
1333
static int cdrom_reopen(BlockDriverState *bs)
1334
{
1335
    BDRVRawState *s = bs->opaque;
1336
    int fd;
1337

    
1338
    /*
1339
     * Force reread of possibly changed/newly loaded disc,
1340
     * FreeBSD seems to not notice sometimes...
1341
     */
1342
    if (s->fd >= 0)
1343
        close(s->fd);
1344
    fd = open(bs->filename, s->open_flags, 0644);
1345
    if (fd < 0) {
1346
        s->fd = -1;
1347
        return -EIO;
1348
    }
1349
    s->fd = fd;
1350

    
1351
    /* make sure the door isnt locked at this time */
1352
    ioctl(s->fd, CDIOCALLOW);
1353
    return 0;
1354
}
1355

    
1356
static int cdrom_is_inserted(BlockDriverState *bs)
1357
{
1358
    return raw_getlength(bs) > 0;
1359
}
1360

    
1361
static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1362
{
1363
    BDRVRawState *s = bs->opaque;
1364

    
1365
    if (s->fd < 0)
1366
        return -ENOTSUP;
1367

    
1368
    (void) ioctl(s->fd, CDIOCALLOW);
1369

    
1370
    if (eject_flag) {
1371
        if (ioctl(s->fd, CDIOCEJECT) < 0)
1372
            perror("CDIOCEJECT");
1373
    } else {
1374
        if (ioctl(s->fd, CDIOCCLOSE) < 0)
1375
            perror("CDIOCCLOSE");
1376
    }
1377

    
1378
    if (cdrom_reopen(bs) < 0)
1379
        return -ENOTSUP;
1380
    return 0;
1381
}
1382

    
1383
static int cdrom_set_locked(BlockDriverState *bs, int locked)
1384
{
1385
    BDRVRawState *s = bs->opaque;
1386

    
1387
    if (s->fd < 0)
1388
        return -ENOTSUP;
1389
    if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1390
        /*
1391
         * Note: an error can happen if the distribution automatically
1392
         * mounts the CD-ROM
1393
         */
1394
        /* perror("CDROM_LOCKDOOR"); */
1395
    }
1396

    
1397
    return 0;
1398
}
1399

    
1400
static BlockDriver bdrv_host_cdrom = {
1401
    .format_name        = "host_cdrom",
1402
    .protocol_name      = "host_cdrom",
1403
    .instance_size      = sizeof(BDRVRawState),
1404
    .bdrv_probe_device        = cdrom_probe_device,
1405
    .bdrv_file_open     = cdrom_open,
1406
    .bdrv_close         = raw_close,
1407
    .bdrv_create        = hdev_create,
1408
    .create_options     = raw_create_options,
1409
    .bdrv_has_zero_init = hdev_has_zero_init,
1410
    .bdrv_flush         = raw_flush,
1411

    
1412
    .bdrv_aio_readv     = raw_aio_readv,
1413
    .bdrv_aio_writev    = raw_aio_writev,
1414
    .bdrv_aio_flush        = raw_aio_flush,
1415

    
1416
    .bdrv_read          = raw_read,
1417
    .bdrv_write         = raw_write,
1418
    .bdrv_getlength     = raw_getlength,
1419

    
1420
    /* removable device support */
1421
    .bdrv_is_inserted   = cdrom_is_inserted,
1422
    .bdrv_eject         = cdrom_eject,
1423
    .bdrv_set_locked    = cdrom_set_locked,
1424
};
1425
#endif /* __FreeBSD__ */
1426

    
1427
static void bdrv_file_init(void)
1428
{
1429
    /*
1430
     * Register all the drivers.  Note that order is important, the driver
1431
     * registered last will get probed first.
1432
     */
1433
    bdrv_register(&bdrv_file);
1434
    bdrv_register(&bdrv_host_device);
1435
#ifdef __linux__
1436
    bdrv_register(&bdrv_host_floppy);
1437
    bdrv_register(&bdrv_host_cdrom);
1438
#endif
1439
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1440
    bdrv_register(&bdrv_host_cdrom);
1441
#endif
1442
}
1443

    
1444
block_init(bdrv_file_init);