Statistics
| Branch: | Revision:

root / block / raw-posix.c @ 4a1d5e1f

History | View | Annotate | Download (39.8 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 <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
#ifdef CONFIG_LINUX_AIO
234
    if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
235
                      (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
236

    
237
        /* We're falling back to POSIX AIO in some cases */
238
        paio_init();
239

    
240
        s->aio_ctx = laio_init();
241
        if (!s->aio_ctx) {
242
            goto out_free_buf;
243
        }
244
        s->use_aio = 1;
245
    } else
246
#endif
247
    {
248
        if (paio_init() < 0) {
249
            goto out_free_buf;
250
        }
251
#ifdef CONFIG_LINUX_AIO
252
        s->use_aio = 0;
253
#endif
254
    }
255

    
256
#ifdef CONFIG_XFS
257
    if (platform_test_xfs_fd(s->fd)) {
258
        s->is_xfs = 1;
259
    }
260
#endif
261

    
262
    return 0;
263

    
264
out_free_buf:
265
    qemu_vfree(s->aligned_buf);
266
out_close:
267
    close(fd);
268
    return -errno;
269
}
270

    
271
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
272
{
273
    BDRVRawState *s = bs->opaque;
274

    
275
    s->type = FTYPE_FILE;
276
    return raw_open_common(bs, filename, flags, 0);
277
}
278

    
279
/* XXX: use host sector size if necessary with:
280
#ifdef DIOCGSECTORSIZE
281
        {
282
            unsigned int sectorsize = 512;
283
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
284
                sectorsize > bufsize)
285
                bufsize = sectorsize;
286
        }
287
#endif
288
#ifdef CONFIG_COCOA
289
        uint32_t blockSize = 512;
290
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
291
            bufsize = blockSize;
292
        }
293
#endif
294
*/
295

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

    
309
    ret = fd_open(bs);
310
    if (ret < 0)
311
        return ret;
312

    
313
    ret = pread(s->fd, buf, count, offset);
314
    if (ret == count)
315
        return ret;
316

    
317
    /* Allow reads beyond the end (needed for pwrite) */
318
    if ((ret == 0) && bs->growable) {
319
        int64_t size = raw_getlength(bs);
320
        if (offset >= size) {
321
            memset(buf, 0, count);
322
            return count;
323
        }
324
    }
325

    
326
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
327
                      "] read failed %d : %d = %s\n",
328
                      s->fd, bs->filename, offset, buf, count,
329
                      bs->total_sectors, ret, errno, strerror(errno));
330

    
331
    /* Try harder for CDrom. */
332
    if (s->type != FTYPE_FILE) {
333
        ret = pread(s->fd, buf, count, offset);
334
        if (ret == count)
335
            return ret;
336
        ret = pread(s->fd, buf, count, offset);
337
        if (ret == count)
338
            return ret;
339

    
340
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
341
                          "] retry read failed %d : %d = %s\n",
342
                          s->fd, bs->filename, offset, buf, count,
343
                          bs->total_sectors, ret, errno, strerror(errno));
344
    }
345

    
346
    return  (ret < 0) ? -errno : ret;
347
}
348

    
349
/*
350
 * offset and count are in bytes, but must be multiples of the sector size
351
 * for files opened with O_DIRECT. buf must be aligned to sector size bytes
352
 * then.
353
 *
354
 * This function may be called without alignment if the caller ensures
355
 * that O_DIRECT is not in effect.
356
 */
357
static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
358
                      const uint8_t *buf, int count)
359
{
360
    BDRVRawState *s = bs->opaque;
361
    int ret;
362

    
363
    ret = fd_open(bs);
364
    if (ret < 0)
365
        return -errno;
366

    
367
    ret = pwrite(s->fd, buf, count, offset);
368
    if (ret == count)
369
        return ret;
370

    
371
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
372
                      "] write failed %d : %d = %s\n",
373
                      s->fd, bs->filename, offset, buf, count,
374
                      bs->total_sectors, ret, errno, strerror(errno));
375

    
376
    return  (ret < 0) ? -errno : ret;
377
}
378

    
379

    
380
/*
381
 * offset and count are in bytes and possibly not aligned. For files opened
382
 * with O_DIRECT, necessary alignments are ensured before calling
383
 * raw_pread_aligned to do the actual read.
384
 */
385
static int raw_pread(BlockDriverState *bs, int64_t offset,
386
                     uint8_t *buf, int count)
387
{
388
    BDRVRawState *s = bs->opaque;
389
    unsigned sector_mask = bs->buffer_alignment - 1;
390
    int size, ret, shift, sum;
391

    
392
    sum = 0;
393

    
394
    if (s->aligned_buf != NULL)  {
395

    
396
        if (offset & sector_mask) {
397
            /* align offset on a sector size bytes boundary */
398

    
399
            shift = offset & sector_mask;
400
            size = (shift + count + sector_mask) & ~sector_mask;
401
            if (size > s->aligned_buf_size)
402
                size = s->aligned_buf_size;
403
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
404
            if (ret < 0)
405
                return ret;
406

    
407
            size = bs->buffer_alignment - shift;
408
            if (size > count)
409
                size = count;
410
            memcpy(buf, s->aligned_buf + shift, size);
411

    
412
            buf += size;
413
            offset += size;
414
            count -= size;
415
            sum += size;
416

    
417
            if (count == 0)
418
                return sum;
419
        }
420
        if (count & sector_mask || (uintptr_t) buf & sector_mask) {
421

    
422
            /* read on aligned buffer */
423

    
424
            while (count) {
425

    
426
                size = (count + sector_mask) & ~sector_mask;
427
                if (size > s->aligned_buf_size)
428
                    size = s->aligned_buf_size;
429

    
430
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
431
                if (ret < 0) {
432
                    return ret;
433
                } else if (ret == 0) {
434
                    fprintf(stderr, "raw_pread: read beyond end of file\n");
435
                    abort();
436
                }
437

    
438
                size = ret;
439
                if (size > count)
440
                    size = count;
441

    
442
                memcpy(buf, s->aligned_buf, size);
443

    
444
                buf += size;
445
                offset += size;
446
                count -= size;
447
                sum += size;
448
            }
449

    
450
            return sum;
451
        }
452
    }
453

    
454
    return raw_pread_aligned(bs, offset, buf, count) + sum;
455
}
456

    
457
static int raw_read(BlockDriverState *bs, int64_t sector_num,
458
                    uint8_t *buf, int nb_sectors)
459
{
460
    int ret;
461

    
462
    ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
463
                    nb_sectors * BDRV_SECTOR_SIZE);
464
    if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
465
        ret = 0;
466
    return ret;
467
}
468

    
469
/*
470
 * offset and count are in bytes and possibly not aligned. For files opened
471
 * with O_DIRECT, necessary alignments are ensured before calling
472
 * raw_pwrite_aligned to do the actual write.
473
 */
474
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
475
                      const uint8_t *buf, int count)
476
{
477
    BDRVRawState *s = bs->opaque;
478
    unsigned sector_mask = bs->buffer_alignment - 1;
479
    int size, ret, shift, sum;
480

    
481
    sum = 0;
482

    
483
    if (s->aligned_buf != NULL) {
484

    
485
        if (offset & sector_mask) {
486
            /* align offset on a sector size bytes boundary */
487
            shift = offset & sector_mask;
488
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf,
489
                                    bs->buffer_alignment);
490
            if (ret < 0)
491
                return ret;
492

    
493
            size = bs->buffer_alignment - shift;
494
            if (size > count)
495
                size = count;
496
            memcpy(s->aligned_buf + shift, buf, size);
497

    
498
            ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf,
499
                                     bs->buffer_alignment);
500
            if (ret < 0)
501
                return ret;
502

    
503
            buf += size;
504
            offset += size;
505
            count -= size;
506
            sum += size;
507

    
508
            if (count == 0)
509
                return sum;
510
        }
511
        if (count & sector_mask || (uintptr_t) buf & sector_mask) {
512

    
513
            while ((size = (count & ~sector_mask)) != 0) {
514

    
515
                if (size > s->aligned_buf_size)
516
                    size = s->aligned_buf_size;
517

    
518
                memcpy(s->aligned_buf, buf, size);
519

    
520
                ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
521
                if (ret < 0)
522
                    return ret;
523

    
524
                buf += ret;
525
                offset += ret;
526
                count -= ret;
527
                sum += ret;
528
            }
529
            /* here, count < sector_size because (count & ~sector_mask) == 0 */
530
            if (count) {
531
                ret = raw_pread_aligned(bs, offset, s->aligned_buf,
532
                                     bs->buffer_alignment);
533
                if (ret < 0)
534
                    return ret;
535
                 memcpy(s->aligned_buf, buf, count);
536

    
537
                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf,
538
                                     bs->buffer_alignment);
539
                 if (ret < 0)
540
                     return ret;
541
                 if (count < ret)
542
                     ret = count;
543

    
544
                 sum += ret;
545
            }
546
            return sum;
547
        }
548
    }
549
    return raw_pwrite_aligned(bs, offset, buf, count) + sum;
550
}
551

    
552
static int raw_write(BlockDriverState *bs, int64_t sector_num,
553
                     const uint8_t *buf, int nb_sectors)
554
{
555
    int ret;
556
    ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf,
557
                     nb_sectors * BDRV_SECTOR_SIZE);
558
    if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
559
        ret = 0;
560
    return ret;
561
}
562

    
563
/*
564
 * Check if all memory in this vector is sector aligned.
565
 */
566
static int qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
567
{
568
    int i;
569

    
570
    for (i = 0; i < qiov->niov; i++) {
571
        if ((uintptr_t) qiov->iov[i].iov_base % bs->buffer_alignment) {
572
            return 0;
573
        }
574
    }
575

    
576
    return 1;
577
}
578

    
579
static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
580
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
581
        BlockDriverCompletionFunc *cb, void *opaque, int type)
582
{
583
    BDRVRawState *s = bs->opaque;
584

    
585
    if (fd_open(bs) < 0)
586
        return NULL;
587

    
588
    /*
589
     * If O_DIRECT is used the buffer needs to be aligned on a sector
590
     * boundary.  Check if this is the case or telll the low-level
591
     * driver that it needs to copy the buffer.
592
     */
593
    if (s->aligned_buf) {
594
        if (!qiov_is_aligned(bs, qiov)) {
595
            type |= QEMU_AIO_MISALIGNED;
596
#ifdef CONFIG_LINUX_AIO
597
        } else if (s->use_aio) {
598
            return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
599
                               nb_sectors, cb, opaque, type);
600
#endif
601
        }
602
    }
603

    
604
    return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
605
                       cb, opaque, type);
606
}
607

    
608
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
609
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
610
        BlockDriverCompletionFunc *cb, void *opaque)
611
{
612
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
613
                          cb, opaque, QEMU_AIO_READ);
614
}
615

    
616
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
617
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
618
        BlockDriverCompletionFunc *cb, void *opaque)
619
{
620
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
621
                          cb, opaque, QEMU_AIO_WRITE);
622
}
623

    
624
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
625
        BlockDriverCompletionFunc *cb, void *opaque)
626
{
627
    BDRVRawState *s = bs->opaque;
628

    
629
    if (fd_open(bs) < 0)
630
        return NULL;
631

    
632
    return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
633
}
634

    
635
static void raw_close(BlockDriverState *bs)
636
{
637
    BDRVRawState *s = bs->opaque;
638
    if (s->fd >= 0) {
639
        close(s->fd);
640
        s->fd = -1;
641
        if (s->aligned_buf != NULL)
642
            qemu_vfree(s->aligned_buf);
643
    }
644
}
645

    
646
static int raw_truncate(BlockDriverState *bs, int64_t offset)
647
{
648
    BDRVRawState *s = bs->opaque;
649
    if (s->type != FTYPE_FILE)
650
        return -ENOTSUP;
651
    if (ftruncate(s->fd, offset) < 0)
652
        return -errno;
653
    return 0;
654
}
655

    
656
#ifdef __OpenBSD__
657
static int64_t raw_getlength(BlockDriverState *bs)
658
{
659
    BDRVRawState *s = bs->opaque;
660
    int fd = s->fd;
661
    struct stat st;
662

    
663
    if (fstat(fd, &st))
664
        return -1;
665
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
666
        struct disklabel dl;
667

    
668
        if (ioctl(fd, DIOCGDINFO, &dl))
669
            return -1;
670
        return (uint64_t)dl.d_secsize *
671
            dl.d_partitions[DISKPART(st.st_rdev)].p_size;
672
    } else
673
        return st.st_size;
674
}
675
#elif defined(__NetBSD__)
676
static int64_t raw_getlength(BlockDriverState *bs)
677
{
678
    BDRVRawState *s = bs->opaque;
679
    int fd = s->fd;
680
    struct stat st;
681

    
682
    if (fstat(fd, &st))
683
        return -1;
684
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
685
        struct dkwedge_info dkw;
686

    
687
        if (ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
688
            return dkw.dkw_size * 512;
689
        } else {
690
            struct disklabel dl;
691

    
692
            if (ioctl(fd, DIOCGDINFO, &dl))
693
                return -1;
694
            return (uint64_t)dl.d_secsize *
695
                dl.d_partitions[DISKPART(st.st_rdev)].p_size;
696
        }
697
    } else
698
        return st.st_size;
699
}
700
#elif defined(__sun__)
701
static int64_t raw_getlength(BlockDriverState *bs)
702
{
703
    BDRVRawState *s = bs->opaque;
704
    struct dk_minfo minfo;
705
    int ret;
706

    
707
    ret = fd_open(bs);
708
    if (ret < 0) {
709
        return ret;
710
    }
711

    
712
    /*
713
     * Use the DKIOCGMEDIAINFO ioctl to read the size.
714
     */
715
    ret = ioctl(s->fd, DKIOCGMEDIAINFO, &minfo);
716
    if (ret != -1) {
717
        return minfo.dki_lbsize * minfo.dki_capacity;
718
    }
719

    
720
    /*
721
     * There are reports that lseek on some devices fails, but
722
     * irc discussion said that contingency on contingency was overkill.
723
     */
724
    return lseek(s->fd, 0, SEEK_END);
725
}
726
#elif defined(CONFIG_BSD)
727
static int64_t raw_getlength(BlockDriverState *bs)
728
{
729
    BDRVRawState *s = bs->opaque;
730
    int fd = s->fd;
731
    int64_t size;
732
    struct stat sb;
733
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
734
    int reopened = 0;
735
#endif
736
    int ret;
737

    
738
    ret = fd_open(bs);
739
    if (ret < 0)
740
        return ret;
741

    
742
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
743
again:
744
#endif
745
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
746
#ifdef DIOCGMEDIASIZE
747
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
748
#elif defined(DIOCGPART)
749
        {
750
                struct partinfo pi;
751
                if (ioctl(fd, DIOCGPART, &pi) == 0)
752
                        size = pi.media_size;
753
                else
754
                        size = 0;
755
        }
756
        if (size == 0)
757
#endif
758
#ifdef CONFIG_COCOA
759
        size = LONG_LONG_MAX;
760
#else
761
        size = lseek(fd, 0LL, SEEK_END);
762
#endif
763
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
764
        switch(s->type) {
765
        case FTYPE_CD:
766
            /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
767
            if (size == 2048LL * (unsigned)-1)
768
                size = 0;
769
            /* XXX no disc?  maybe we need to reopen... */
770
            if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
771
                reopened = 1;
772
                goto again;
773
            }
774
        }
775
#endif
776
    } else {
777
        size = lseek(fd, 0, SEEK_END);
778
    }
779
    return size;
780
}
781
#else
782
static int64_t raw_getlength(BlockDriverState *bs)
783
{
784
    BDRVRawState *s = bs->opaque;
785
    int ret;
786

    
787
    ret = fd_open(bs);
788
    if (ret < 0) {
789
        return ret;
790
    }
791

    
792
    return lseek(s->fd, 0, SEEK_END);
793
}
794
#endif
795

    
796
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
797
{
798
    struct stat st;
799
    BDRVRawState *s = bs->opaque;
800

    
801
    if (fstat(s->fd, &st) < 0) {
802
        return -errno;
803
    }
804
    return (int64_t)st.st_blocks * 512;
805
}
806

    
807
static int raw_create(const char *filename, QEMUOptionParameter *options)
808
{
809
    int fd;
810
    int result = 0;
811
    int64_t total_size = 0;
812

    
813
    /* Read out options */
814
    while (options && options->name) {
815
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
816
            total_size = options->value.n / BDRV_SECTOR_SIZE;
817
        }
818
        options++;
819
    }
820

    
821
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
822
              0644);
823
    if (fd < 0) {
824
        result = -errno;
825
    } else {
826
        if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
827
            result = -errno;
828
        }
829
        if (close(fd) != 0) {
830
            result = -errno;
831
        }
832
    }
833
    return result;
834
}
835

    
836
static int raw_flush(BlockDriverState *bs)
837
{
838
    BDRVRawState *s = bs->opaque;
839
    return qemu_fdatasync(s->fd);
840
}
841

    
842
#ifdef CONFIG_XFS
843
static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
844
{
845
    struct xfs_flock64 fl;
846

    
847
    memset(&fl, 0, sizeof(fl));
848
    fl.l_whence = SEEK_SET;
849
    fl.l_start = sector_num << 9;
850
    fl.l_len = (int64_t)nb_sectors << 9;
851

    
852
    if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
853
        DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
854
        return -errno;
855
    }
856

    
857
    return 0;
858
}
859
#endif
860

    
861
static int raw_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
862
{
863
#ifdef CONFIG_XFS
864
    BDRVRawState *s = bs->opaque;
865

    
866
    if (s->is_xfs) {
867
        return xfs_discard(s, sector_num, nb_sectors);
868
    }
869
#endif
870

    
871
    return 0;
872
}
873

    
874
static QEMUOptionParameter raw_create_options[] = {
875
    {
876
        .name = BLOCK_OPT_SIZE,
877
        .type = OPT_SIZE,
878
        .help = "Virtual disk size"
879
    },
880
    { NULL }
881
};
882

    
883
static BlockDriver bdrv_file = {
884
    .format_name = "file",
885
    .protocol_name = "file",
886
    .instance_size = sizeof(BDRVRawState),
887
    .bdrv_probe = NULL, /* no probe for protocols */
888
    .bdrv_file_open = raw_open,
889
    .bdrv_read = raw_read,
890
    .bdrv_write = raw_write,
891
    .bdrv_close = raw_close,
892
    .bdrv_create = raw_create,
893
    .bdrv_flush = raw_flush,
894
    .bdrv_discard = raw_discard,
895

    
896
    .bdrv_aio_readv = raw_aio_readv,
897
    .bdrv_aio_writev = raw_aio_writev,
898
    .bdrv_aio_flush = raw_aio_flush,
899

    
900
    .bdrv_truncate = raw_truncate,
901
    .bdrv_getlength = raw_getlength,
902
    .bdrv_get_allocated_file_size
903
                        = raw_get_allocated_file_size,
904

    
905
    .create_options = raw_create_options,
906
};
907

    
908
/***********************************************/
909
/* host device */
910

    
911
#ifdef CONFIG_COCOA
912
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
913
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
914

    
915
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
916
{
917
    kern_return_t       kernResult;
918
    mach_port_t     masterPort;
919
    CFMutableDictionaryRef  classesToMatch;
920

    
921
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
922
    if ( KERN_SUCCESS != kernResult ) {
923
        printf( "IOMasterPort returned %d\n", kernResult );
924
    }
925

    
926
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
927
    if ( classesToMatch == NULL ) {
928
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
929
    } else {
930
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
931
    }
932
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
933
    if ( KERN_SUCCESS != kernResult )
934
    {
935
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
936
    }
937

    
938
    return kernResult;
939
}
940

    
941
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
942
{
943
    io_object_t     nextMedia;
944
    kern_return_t   kernResult = KERN_FAILURE;
945
    *bsdPath = '\0';
946
    nextMedia = IOIteratorNext( mediaIterator );
947
    if ( nextMedia )
948
    {
949
        CFTypeRef   bsdPathAsCFString;
950
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
951
        if ( bsdPathAsCFString ) {
952
            size_t devPathLength;
953
            strcpy( bsdPath, _PATH_DEV );
954
            strcat( bsdPath, "r" );
955
            devPathLength = strlen( bsdPath );
956
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
957
                kernResult = KERN_SUCCESS;
958
            }
959
            CFRelease( bsdPathAsCFString );
960
        }
961
        IOObjectRelease( nextMedia );
962
    }
963

    
964
    return kernResult;
965
}
966

    
967
#endif
968

    
969
static int hdev_probe_device(const char *filename)
970
{
971
    struct stat st;
972

    
973
    /* allow a dedicated CD-ROM driver to match with a higher priority */
974
    if (strstart(filename, "/dev/cdrom", NULL))
975
        return 50;
976

    
977
    if (stat(filename, &st) >= 0 &&
978
            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
979
        return 100;
980
    }
981

    
982
    return 0;
983
}
984

    
985
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
986
{
987
    BDRVRawState *s = bs->opaque;
988

    
989
#ifdef CONFIG_COCOA
990
    if (strstart(filename, "/dev/cdrom", NULL)) {
991
        kern_return_t kernResult;
992
        io_iterator_t mediaIterator;
993
        char bsdPath[ MAXPATHLEN ];
994
        int fd;
995

    
996
        kernResult = FindEjectableCDMedia( &mediaIterator );
997
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
998

    
999
        if ( bsdPath[ 0 ] != '\0' ) {
1000
            strcat(bsdPath,"s0");
1001
            /* some CDs don't have a partition 0 */
1002
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
1003
            if (fd < 0) {
1004
                bsdPath[strlen(bsdPath)-1] = '1';
1005
            } else {
1006
                close(fd);
1007
            }
1008
            filename = bsdPath;
1009
        }
1010

    
1011
        if ( mediaIterator )
1012
            IOObjectRelease( mediaIterator );
1013
    }
1014
#endif
1015

    
1016
    s->type = FTYPE_FILE;
1017
#if defined(__linux__)
1018
    {
1019
        char resolved_path[ MAXPATHLEN ], *temp;
1020

    
1021
        temp = realpath(filename, resolved_path);
1022
        if (temp && strstart(temp, "/dev/sg", NULL)) {
1023
            bs->sg = 1;
1024
        }
1025
    }
1026
#endif
1027

    
1028
    return raw_open_common(bs, filename, flags, 0);
1029
}
1030

    
1031
#if defined(__linux__)
1032
/* Note: we do not have a reliable method to detect if the floppy is
1033
   present. The current method is to try to open the floppy at every
1034
   I/O and to keep it opened during a few hundreds of ms. */
1035
static int fd_open(BlockDriverState *bs)
1036
{
1037
    BDRVRawState *s = bs->opaque;
1038
    int last_media_present;
1039

    
1040
    if (s->type != FTYPE_FD)
1041
        return 0;
1042
    last_media_present = (s->fd >= 0);
1043
    if (s->fd >= 0 &&
1044
        (get_clock() - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
1045
        close(s->fd);
1046
        s->fd = -1;
1047
#ifdef DEBUG_FLOPPY
1048
        printf("Floppy closed\n");
1049
#endif
1050
    }
1051
    if (s->fd < 0) {
1052
        if (s->fd_got_error &&
1053
            (get_clock() - s->fd_error_time) < FD_OPEN_TIMEOUT) {
1054
#ifdef DEBUG_FLOPPY
1055
            printf("No floppy (open delayed)\n");
1056
#endif
1057
            return -EIO;
1058
        }
1059
        s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
1060
        if (s->fd < 0) {
1061
            s->fd_error_time = get_clock();
1062
            s->fd_got_error = 1;
1063
            if (last_media_present)
1064
                s->fd_media_changed = 1;
1065
#ifdef DEBUG_FLOPPY
1066
            printf("No floppy\n");
1067
#endif
1068
            return -EIO;
1069
        }
1070
#ifdef DEBUG_FLOPPY
1071
        printf("Floppy opened\n");
1072
#endif
1073
    }
1074
    if (!last_media_present)
1075
        s->fd_media_changed = 1;
1076
    s->fd_open_time = get_clock();
1077
    s->fd_got_error = 0;
1078
    return 0;
1079
}
1080

    
1081
static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1082
{
1083
    BDRVRawState *s = bs->opaque;
1084

    
1085
    return ioctl(s->fd, req, buf);
1086
}
1087

    
1088
static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
1089
        unsigned long int req, void *buf,
1090
        BlockDriverCompletionFunc *cb, void *opaque)
1091
{
1092
    BDRVRawState *s = bs->opaque;
1093

    
1094
    if (fd_open(bs) < 0)
1095
        return NULL;
1096
    return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
1097
}
1098

    
1099
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1100
static int fd_open(BlockDriverState *bs)
1101
{
1102
    BDRVRawState *s = bs->opaque;
1103

    
1104
    /* this is just to ensure s->fd is sane (its called by io ops) */
1105
    if (s->fd >= 0)
1106
        return 0;
1107
    return -EIO;
1108
}
1109
#else /* !linux && !FreeBSD */
1110

    
1111
static int fd_open(BlockDriverState *bs)
1112
{
1113
    return 0;
1114
}
1115

    
1116
#endif /* !linux && !FreeBSD */
1117

    
1118
static int hdev_create(const char *filename, QEMUOptionParameter *options)
1119
{
1120
    int fd;
1121
    int ret = 0;
1122
    struct stat stat_buf;
1123
    int64_t total_size = 0;
1124

    
1125
    /* Read out options */
1126
    while (options && options->name) {
1127
        if (!strcmp(options->name, "size")) {
1128
            total_size = options->value.n / BDRV_SECTOR_SIZE;
1129
        }
1130
        options++;
1131
    }
1132

    
1133
    fd = open(filename, O_WRONLY | O_BINARY);
1134
    if (fd < 0)
1135
        return -errno;
1136

    
1137
    if (fstat(fd, &stat_buf) < 0)
1138
        ret = -errno;
1139
    else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
1140
        ret = -ENODEV;
1141
    else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
1142
        ret = -ENOSPC;
1143

    
1144
    close(fd);
1145
    return ret;
1146
}
1147

    
1148
static int hdev_has_zero_init(BlockDriverState *bs)
1149
{
1150
    return 0;
1151
}
1152

    
1153
static BlockDriver bdrv_host_device = {
1154
    .format_name        = "host_device",
1155
    .protocol_name        = "host_device",
1156
    .instance_size      = sizeof(BDRVRawState),
1157
    .bdrv_probe_device  = hdev_probe_device,
1158
    .bdrv_file_open     = hdev_open,
1159
    .bdrv_close         = raw_close,
1160
    .bdrv_create        = hdev_create,
1161
    .create_options     = raw_create_options,
1162
    .bdrv_has_zero_init = hdev_has_zero_init,
1163
    .bdrv_flush         = raw_flush,
1164

    
1165
    .bdrv_aio_readv        = raw_aio_readv,
1166
    .bdrv_aio_writev        = raw_aio_writev,
1167
    .bdrv_aio_flush        = raw_aio_flush,
1168

    
1169
    .bdrv_read          = raw_read,
1170
    .bdrv_write         = raw_write,
1171
    .bdrv_getlength        = raw_getlength,
1172
    .bdrv_get_allocated_file_size
1173
                        = raw_get_allocated_file_size,
1174

    
1175
    /* generic scsi device */
1176
#ifdef __linux__
1177
    .bdrv_ioctl         = hdev_ioctl,
1178
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1179
#endif
1180
};
1181

    
1182
#ifdef __linux__
1183
static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
1184
{
1185
    BDRVRawState *s = bs->opaque;
1186
    int ret;
1187

    
1188
    s->type = FTYPE_FD;
1189

    
1190
    /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
1191
    ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
1192
    if (ret)
1193
        return ret;
1194

    
1195
    /* close fd so that we can reopen it as needed */
1196
    close(s->fd);
1197
    s->fd = -1;
1198
    s->fd_media_changed = 1;
1199

    
1200
    return 0;
1201
}
1202

    
1203
static int floppy_probe_device(const char *filename)
1204
{
1205
    int fd, ret;
1206
    int prio = 0;
1207
    struct floppy_struct fdparam;
1208
    struct stat st;
1209

    
1210
    if (strstart(filename, "/dev/fd", NULL))
1211
        prio = 50;
1212

    
1213
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1214
    if (fd < 0) {
1215
        goto out;
1216
    }
1217
    ret = fstat(fd, &st);
1218
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
1219
        goto outc;
1220
    }
1221

    
1222
    /* Attempt to detect via a floppy specific ioctl */
1223
    ret = ioctl(fd, FDGETPRM, &fdparam);
1224
    if (ret >= 0)
1225
        prio = 100;
1226

    
1227
outc:
1228
    close(fd);
1229
out:
1230
    return prio;
1231
}
1232

    
1233

    
1234
static int floppy_is_inserted(BlockDriverState *bs)
1235
{
1236
    return fd_open(bs) >= 0;
1237
}
1238

    
1239
static int floppy_media_changed(BlockDriverState *bs)
1240
{
1241
    BDRVRawState *s = bs->opaque;
1242
    int ret;
1243

    
1244
    /*
1245
     * XXX: we do not have a true media changed indication.
1246
     * It does not work if the floppy is changed without trying to read it.
1247
     */
1248
    fd_open(bs);
1249
    ret = s->fd_media_changed;
1250
    s->fd_media_changed = 0;
1251
#ifdef DEBUG_FLOPPY
1252
    printf("Floppy changed=%d\n", ret);
1253
#endif
1254
    return ret;
1255
}
1256

    
1257
static int floppy_eject(BlockDriverState *bs, int eject_flag)
1258
{
1259
    BDRVRawState *s = bs->opaque;
1260
    int fd;
1261

    
1262
    if (s->fd >= 0) {
1263
        close(s->fd);
1264
        s->fd = -1;
1265
    }
1266
    fd = open(bs->filename, s->open_flags | O_NONBLOCK);
1267
    if (fd >= 0) {
1268
        if (ioctl(fd, FDEJECT, 0) < 0)
1269
            perror("FDEJECT");
1270
        close(fd);
1271
    }
1272

    
1273
    return 0;
1274
}
1275

    
1276
static BlockDriver bdrv_host_floppy = {
1277
    .format_name        = "host_floppy",
1278
    .protocol_name      = "host_floppy",
1279
    .instance_size      = sizeof(BDRVRawState),
1280
    .bdrv_probe_device        = floppy_probe_device,
1281
    .bdrv_file_open     = floppy_open,
1282
    .bdrv_close         = raw_close,
1283
    .bdrv_create        = hdev_create,
1284
    .create_options     = raw_create_options,
1285
    .bdrv_has_zero_init = hdev_has_zero_init,
1286
    .bdrv_flush         = raw_flush,
1287

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

    
1292
    .bdrv_read          = raw_read,
1293
    .bdrv_write         = raw_write,
1294
    .bdrv_getlength        = raw_getlength,
1295
    .bdrv_get_allocated_file_size
1296
                        = raw_get_allocated_file_size,
1297

    
1298
    /* removable device support */
1299
    .bdrv_is_inserted   = floppy_is_inserted,
1300
    .bdrv_media_changed = floppy_media_changed,
1301
    .bdrv_eject         = floppy_eject,
1302
};
1303

    
1304
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1305
{
1306
    BDRVRawState *s = bs->opaque;
1307

    
1308
    s->type = FTYPE_CD;
1309

    
1310
    /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
1311
    return raw_open_common(bs, filename, flags, O_NONBLOCK);
1312
}
1313

    
1314
static int cdrom_probe_device(const char *filename)
1315
{
1316
    int fd, ret;
1317
    int prio = 0;
1318
    struct stat st;
1319

    
1320
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1321
    if (fd < 0) {
1322
        goto out;
1323
    }
1324
    ret = fstat(fd, &st);
1325
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
1326
        goto outc;
1327
    }
1328

    
1329
    /* Attempt to detect via a CDROM specific ioctl */
1330
    ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1331
    if (ret >= 0)
1332
        prio = 100;
1333

    
1334
outc:
1335
    close(fd);
1336
out:
1337
    return prio;
1338
}
1339

    
1340
static int cdrom_is_inserted(BlockDriverState *bs)
1341
{
1342
    BDRVRawState *s = bs->opaque;
1343
    int ret;
1344

    
1345
    ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1346
    if (ret == CDS_DISC_OK)
1347
        return 1;
1348
    return 0;
1349
}
1350

    
1351
static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1352
{
1353
    BDRVRawState *s = bs->opaque;
1354

    
1355
    if (eject_flag) {
1356
        if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
1357
            perror("CDROMEJECT");
1358
    } else {
1359
        if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
1360
            perror("CDROMEJECT");
1361
    }
1362

    
1363
    return 0;
1364
}
1365

    
1366
static int cdrom_set_locked(BlockDriverState *bs, int locked)
1367
{
1368
    BDRVRawState *s = bs->opaque;
1369

    
1370
    if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
1371
        /*
1372
         * Note: an error can happen if the distribution automatically
1373
         * mounts the CD-ROM
1374
         */
1375
        /* perror("CDROM_LOCKDOOR"); */
1376
    }
1377

    
1378
    return 0;
1379
}
1380

    
1381
static BlockDriver bdrv_host_cdrom = {
1382
    .format_name        = "host_cdrom",
1383
    .protocol_name      = "host_cdrom",
1384
    .instance_size      = sizeof(BDRVRawState),
1385
    .bdrv_probe_device        = cdrom_probe_device,
1386
    .bdrv_file_open     = cdrom_open,
1387
    .bdrv_close         = raw_close,
1388
    .bdrv_create        = hdev_create,
1389
    .create_options     = raw_create_options,
1390
    .bdrv_has_zero_init = hdev_has_zero_init,
1391
    .bdrv_flush         = raw_flush,
1392

    
1393
    .bdrv_aio_readv     = raw_aio_readv,
1394
    .bdrv_aio_writev    = raw_aio_writev,
1395
    .bdrv_aio_flush        = raw_aio_flush,
1396

    
1397
    .bdrv_read          = raw_read,
1398
    .bdrv_write         = raw_write,
1399
    .bdrv_getlength     = raw_getlength,
1400
    .bdrv_get_allocated_file_size
1401
                        = raw_get_allocated_file_size,
1402

    
1403
    /* removable device support */
1404
    .bdrv_is_inserted   = cdrom_is_inserted,
1405
    .bdrv_eject         = cdrom_eject,
1406
    .bdrv_set_locked    = cdrom_set_locked,
1407

    
1408
    /* generic scsi device */
1409
    .bdrv_ioctl         = hdev_ioctl,
1410
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1411
};
1412
#endif /* __linux__ */
1413

    
1414
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1415
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1416
{
1417
    BDRVRawState *s = bs->opaque;
1418
    int ret;
1419

    
1420
    s->type = FTYPE_CD;
1421

    
1422
    ret = raw_open_common(bs, filename, flags, 0);
1423
    if (ret)
1424
        return ret;
1425

    
1426
    /* make sure the door isnt locked at this time */
1427
    ioctl(s->fd, CDIOCALLOW);
1428
    return 0;
1429
}
1430

    
1431
static int cdrom_probe_device(const char *filename)
1432
{
1433
    if (strstart(filename, "/dev/cd", NULL) ||
1434
            strstart(filename, "/dev/acd", NULL))
1435
        return 100;
1436
    return 0;
1437
}
1438

    
1439
static int cdrom_reopen(BlockDriverState *bs)
1440
{
1441
    BDRVRawState *s = bs->opaque;
1442
    int fd;
1443

    
1444
    /*
1445
     * Force reread of possibly changed/newly loaded disc,
1446
     * FreeBSD seems to not notice sometimes...
1447
     */
1448
    if (s->fd >= 0)
1449
        close(s->fd);
1450
    fd = open(bs->filename, s->open_flags, 0644);
1451
    if (fd < 0) {
1452
        s->fd = -1;
1453
        return -EIO;
1454
    }
1455
    s->fd = fd;
1456

    
1457
    /* make sure the door isnt locked at this time */
1458
    ioctl(s->fd, CDIOCALLOW);
1459
    return 0;
1460
}
1461

    
1462
static int cdrom_is_inserted(BlockDriverState *bs)
1463
{
1464
    return raw_getlength(bs) > 0;
1465
}
1466

    
1467
static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1468
{
1469
    BDRVRawState *s = bs->opaque;
1470

    
1471
    if (s->fd < 0)
1472
        return -ENOTSUP;
1473

    
1474
    (void) ioctl(s->fd, CDIOCALLOW);
1475

    
1476
    if (eject_flag) {
1477
        if (ioctl(s->fd, CDIOCEJECT) < 0)
1478
            perror("CDIOCEJECT");
1479
    } else {
1480
        if (ioctl(s->fd, CDIOCCLOSE) < 0)
1481
            perror("CDIOCCLOSE");
1482
    }
1483

    
1484
    if (cdrom_reopen(bs) < 0)
1485
        return -ENOTSUP;
1486
    return 0;
1487
}
1488

    
1489
static int cdrom_set_locked(BlockDriverState *bs, int locked)
1490
{
1491
    BDRVRawState *s = bs->opaque;
1492

    
1493
    if (s->fd < 0)
1494
        return -ENOTSUP;
1495
    if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1496
        /*
1497
         * Note: an error can happen if the distribution automatically
1498
         * mounts the CD-ROM
1499
         */
1500
        /* perror("CDROM_LOCKDOOR"); */
1501
    }
1502

    
1503
    return 0;
1504
}
1505

    
1506
static BlockDriver bdrv_host_cdrom = {
1507
    .format_name        = "host_cdrom",
1508
    .protocol_name      = "host_cdrom",
1509
    .instance_size      = sizeof(BDRVRawState),
1510
    .bdrv_probe_device        = cdrom_probe_device,
1511
    .bdrv_file_open     = cdrom_open,
1512
    .bdrv_close         = raw_close,
1513
    .bdrv_create        = hdev_create,
1514
    .create_options     = raw_create_options,
1515
    .bdrv_has_zero_init = hdev_has_zero_init,
1516
    .bdrv_flush         = raw_flush,
1517

    
1518
    .bdrv_aio_readv     = raw_aio_readv,
1519
    .bdrv_aio_writev    = raw_aio_writev,
1520
    .bdrv_aio_flush        = raw_aio_flush,
1521

    
1522
    .bdrv_read          = raw_read,
1523
    .bdrv_write         = raw_write,
1524
    .bdrv_getlength     = raw_getlength,
1525
    .bdrv_get_allocated_file_size
1526
                        = raw_get_allocated_file_size,
1527

    
1528
    /* removable device support */
1529
    .bdrv_is_inserted   = cdrom_is_inserted,
1530
    .bdrv_eject         = cdrom_eject,
1531
    .bdrv_set_locked    = cdrom_set_locked,
1532
};
1533
#endif /* __FreeBSD__ */
1534

    
1535
static void bdrv_file_init(void)
1536
{
1537
    /*
1538
     * Register all the drivers.  Note that order is important, the driver
1539
     * registered last will get probed first.
1540
     */
1541
    bdrv_register(&bdrv_file);
1542
    bdrv_register(&bdrv_host_device);
1543
#ifdef __linux__
1544
    bdrv_register(&bdrv_host_floppy);
1545
    bdrv_register(&bdrv_host_cdrom);
1546
#endif
1547
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1548
    bdrv_register(&bdrv_host_cdrom);
1549
#endif
1550
}
1551

    
1552
block_init(bdrv_file_init);