Statistics
| Branch: | Revision:

root / block / raw-posix.c @ 7a3f5fe9

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
    /* We're falling back to POSIX AIO in some cases so init always */
234
    if (paio_init() < 0) {
235
        goto out_free_buf;
236
    }
237

    
238
#ifdef CONFIG_LINUX_AIO
239
    /*
240
     * Currently Linux do AIO only for files opened with O_DIRECT
241
     * specified so check NOCACHE flag too
242
     */
243
    if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
244
                      (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
245

    
246
        s->aio_ctx = laio_init();
247
        if (!s->aio_ctx) {
248
            goto out_free_buf;
249
        }
250
        s->use_aio = 1;
251
    } else
252
#endif
253
    {
254
#ifdef CONFIG_LINUX_AIO
255
        s->use_aio = 0;
256
#endif
257
    }
258

    
259
#ifdef CONFIG_XFS
260
    if (platform_test_xfs_fd(s->fd)) {
261
        s->is_xfs = 1;
262
    }
263
#endif
264

    
265
    return 0;
266

    
267
out_free_buf:
268
    qemu_vfree(s->aligned_buf);
269
out_close:
270
    close(fd);
271
    return -errno;
272
}
273

    
274
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
275
{
276
    BDRVRawState *s = bs->opaque;
277

    
278
    s->type = FTYPE_FILE;
279
    return raw_open_common(bs, filename, flags, 0);
280
}
281

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

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

    
312
    ret = fd_open(bs);
313
    if (ret < 0)
314
        return ret;
315

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

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

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

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

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

    
349
    return  (ret < 0) ? -errno : ret;
350
}
351

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

    
366
    ret = fd_open(bs);
367
    if (ret < 0)
368
        return -errno;
369

    
370
    ret = pwrite(s->fd, buf, count, offset);
371
    if (ret == count)
372
        return ret;
373

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

    
379
    return  (ret < 0) ? -errno : ret;
380
}
381

    
382

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

    
395
    sum = 0;
396

    
397
    if (s->aligned_buf != NULL)  {
398

    
399
        if (offset & sector_mask) {
400
            /* align offset on a sector size bytes boundary */
401

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

    
410
            size = bs->buffer_alignment - shift;
411
            if (size > count)
412
                size = count;
413
            memcpy(buf, s->aligned_buf + shift, size);
414

    
415
            buf += size;
416
            offset += size;
417
            count -= size;
418
            sum += size;
419

    
420
            if (count == 0)
421
                return sum;
422
        }
423
        if (count & sector_mask || (uintptr_t) buf & sector_mask) {
424

    
425
            /* read on aligned buffer */
426

    
427
            while (count) {
428

    
429
                size = (count + sector_mask) & ~sector_mask;
430
                if (size > s->aligned_buf_size)
431
                    size = s->aligned_buf_size;
432

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

    
441
                size = ret;
442
                if (size > count)
443
                    size = count;
444

    
445
                memcpy(buf, s->aligned_buf, size);
446

    
447
                buf += size;
448
                offset += size;
449
                count -= size;
450
                sum += size;
451
            }
452

    
453
            return sum;
454
        }
455
    }
456

    
457
    return raw_pread_aligned(bs, offset, buf, count) + sum;
458
}
459

    
460
static int raw_read(BlockDriverState *bs, int64_t sector_num,
461
                    uint8_t *buf, int nb_sectors)
462
{
463
    int ret;
464

    
465
    ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
466
                    nb_sectors * BDRV_SECTOR_SIZE);
467
    if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
468
        ret = 0;
469
    return ret;
470
}
471

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

    
484
    sum = 0;
485

    
486
    if (s->aligned_buf != NULL) {
487

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

    
496
            size = bs->buffer_alignment - shift;
497
            if (size > count)
498
                size = count;
499
            memcpy(s->aligned_buf + shift, buf, size);
500

    
501
            ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf,
502
                                     bs->buffer_alignment);
503
            if (ret < 0)
504
                return ret;
505

    
506
            buf += size;
507
            offset += size;
508
            count -= size;
509
            sum += size;
510

    
511
            if (count == 0)
512
                return sum;
513
        }
514
        if (count & sector_mask || (uintptr_t) buf & sector_mask) {
515

    
516
            while ((size = (count & ~sector_mask)) != 0) {
517

    
518
                if (size > s->aligned_buf_size)
519
                    size = s->aligned_buf_size;
520

    
521
                memcpy(s->aligned_buf, buf, size);
522

    
523
                ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
524
                if (ret < 0)
525
                    return ret;
526

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

    
540
                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf,
541
                                     bs->buffer_alignment);
542
                 if (ret < 0)
543
                     return ret;
544
                 if (count < ret)
545
                     ret = count;
546

    
547
                 sum += ret;
548
            }
549
            return sum;
550
        }
551
    }
552
    return raw_pwrite_aligned(bs, offset, buf, count) + sum;
553
}
554

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

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

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

    
579
    return 1;
580
}
581

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

    
588
    if (fd_open(bs) < 0)
589
        return NULL;
590

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

    
607
    return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
608
                       cb, opaque, type);
609
}
610

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

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

    
627
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
628
        BlockDriverCompletionFunc *cb, void *opaque)
629
{
630
    BDRVRawState *s = bs->opaque;
631

    
632
    if (fd_open(bs) < 0)
633
        return NULL;
634

    
635
    return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
636
}
637

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

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

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

    
666
    if (fstat(fd, &st))
667
        return -1;
668
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
669
        struct disklabel dl;
670

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

    
685
    if (fstat(fd, &st))
686
        return -1;
687
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
688
        struct dkwedge_info dkw;
689

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

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

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

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

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

    
741
    ret = fd_open(bs);
742
    if (ret < 0)
743
        return ret;
744

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

    
790
    ret = fd_open(bs);
791
    if (ret < 0) {
792
        return ret;
793
    }
794

    
795
    return lseek(s->fd, 0, SEEK_END);
796
}
797
#endif
798

    
799
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
800
{
801
    struct stat st;
802
    BDRVRawState *s = bs->opaque;
803

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

    
810
static int raw_create(const char *filename, QEMUOptionParameter *options)
811
{
812
    int fd;
813
    int result = 0;
814
    int64_t total_size = 0;
815

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

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

    
839
static int raw_flush(BlockDriverState *bs)
840
{
841
    BDRVRawState *s = bs->opaque;
842
    int ret;
843

    
844
    ret = qemu_fdatasync(s->fd);
845
    if (ret < 0) {
846
        return -errno;
847
    }
848

    
849
    return 0;
850
}
851

    
852
#ifdef CONFIG_XFS
853
static int xfs_discard(BDRVRawState *s, int64_t sector_num, int nb_sectors)
854
{
855
    struct xfs_flock64 fl;
856

    
857
    memset(&fl, 0, sizeof(fl));
858
    fl.l_whence = SEEK_SET;
859
    fl.l_start = sector_num << 9;
860
    fl.l_len = (int64_t)nb_sectors << 9;
861

    
862
    if (xfsctl(NULL, s->fd, XFS_IOC_UNRESVSP64, &fl) < 0) {
863
        DEBUG_BLOCK_PRINT("cannot punch hole (%s)\n", strerror(errno));
864
        return -errno;
865
    }
866

    
867
    return 0;
868
}
869
#endif
870

    
871
static int raw_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
872
{
873
#ifdef CONFIG_XFS
874
    BDRVRawState *s = bs->opaque;
875

    
876
    if (s->is_xfs) {
877
        return xfs_discard(s, sector_num, nb_sectors);
878
    }
879
#endif
880

    
881
    return 0;
882
}
883

    
884
static QEMUOptionParameter raw_create_options[] = {
885
    {
886
        .name = BLOCK_OPT_SIZE,
887
        .type = OPT_SIZE,
888
        .help = "Virtual disk size"
889
    },
890
    { NULL }
891
};
892

    
893
static BlockDriver bdrv_file = {
894
    .format_name = "file",
895
    .protocol_name = "file",
896
    .instance_size = sizeof(BDRVRawState),
897
    .bdrv_probe = NULL, /* no probe for protocols */
898
    .bdrv_file_open = raw_open,
899
    .bdrv_read = raw_read,
900
    .bdrv_write = raw_write,
901
    .bdrv_close = raw_close,
902
    .bdrv_create = raw_create,
903
    .bdrv_flush = raw_flush,
904
    .bdrv_discard = raw_discard,
905

    
906
    .bdrv_aio_readv = raw_aio_readv,
907
    .bdrv_aio_writev = raw_aio_writev,
908
    .bdrv_aio_flush = raw_aio_flush,
909

    
910
    .bdrv_truncate = raw_truncate,
911
    .bdrv_getlength = raw_getlength,
912
    .bdrv_get_allocated_file_size
913
                        = raw_get_allocated_file_size,
914

    
915
    .create_options = raw_create_options,
916
};
917

    
918
/***********************************************/
919
/* host device */
920

    
921
#ifdef CONFIG_COCOA
922
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
923
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
924

    
925
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
926
{
927
    kern_return_t       kernResult;
928
    mach_port_t     masterPort;
929
    CFMutableDictionaryRef  classesToMatch;
930

    
931
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
932
    if ( KERN_SUCCESS != kernResult ) {
933
        printf( "IOMasterPort returned %d\n", kernResult );
934
    }
935

    
936
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
937
    if ( classesToMatch == NULL ) {
938
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
939
    } else {
940
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
941
    }
942
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
943
    if ( KERN_SUCCESS != kernResult )
944
    {
945
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
946
    }
947

    
948
    return kernResult;
949
}
950

    
951
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
952
{
953
    io_object_t     nextMedia;
954
    kern_return_t   kernResult = KERN_FAILURE;
955
    *bsdPath = '\0';
956
    nextMedia = IOIteratorNext( mediaIterator );
957
    if ( nextMedia )
958
    {
959
        CFTypeRef   bsdPathAsCFString;
960
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
961
        if ( bsdPathAsCFString ) {
962
            size_t devPathLength;
963
            strcpy( bsdPath, _PATH_DEV );
964
            strcat( bsdPath, "r" );
965
            devPathLength = strlen( bsdPath );
966
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
967
                kernResult = KERN_SUCCESS;
968
            }
969
            CFRelease( bsdPathAsCFString );
970
        }
971
        IOObjectRelease( nextMedia );
972
    }
973

    
974
    return kernResult;
975
}
976

    
977
#endif
978

    
979
static int hdev_probe_device(const char *filename)
980
{
981
    struct stat st;
982

    
983
    /* allow a dedicated CD-ROM driver to match with a higher priority */
984
    if (strstart(filename, "/dev/cdrom", NULL))
985
        return 50;
986

    
987
    if (stat(filename, &st) >= 0 &&
988
            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
989
        return 100;
990
    }
991

    
992
    return 0;
993
}
994

    
995
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
996
{
997
    BDRVRawState *s = bs->opaque;
998

    
999
#ifdef CONFIG_COCOA
1000
    if (strstart(filename, "/dev/cdrom", NULL)) {
1001
        kern_return_t kernResult;
1002
        io_iterator_t mediaIterator;
1003
        char bsdPath[ MAXPATHLEN ];
1004
        int fd;
1005

    
1006
        kernResult = FindEjectableCDMedia( &mediaIterator );
1007
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
1008

    
1009
        if ( bsdPath[ 0 ] != '\0' ) {
1010
            strcat(bsdPath,"s0");
1011
            /* some CDs don't have a partition 0 */
1012
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
1013
            if (fd < 0) {
1014
                bsdPath[strlen(bsdPath)-1] = '1';
1015
            } else {
1016
                close(fd);
1017
            }
1018
            filename = bsdPath;
1019
        }
1020

    
1021
        if ( mediaIterator )
1022
            IOObjectRelease( mediaIterator );
1023
    }
1024
#endif
1025

    
1026
    s->type = FTYPE_FILE;
1027
#if defined(__linux__)
1028
    {
1029
        char resolved_path[ MAXPATHLEN ], *temp;
1030

    
1031
        temp = realpath(filename, resolved_path);
1032
        if (temp && strstart(temp, "/dev/sg", NULL)) {
1033
            bs->sg = 1;
1034
        }
1035
    }
1036
#endif
1037

    
1038
    return raw_open_common(bs, filename, flags, 0);
1039
}
1040

    
1041
#if defined(__linux__)
1042
/* Note: we do not have a reliable method to detect if the floppy is
1043
   present. The current method is to try to open the floppy at every
1044
   I/O and to keep it opened during a few hundreds of ms. */
1045
static int fd_open(BlockDriverState *bs)
1046
{
1047
    BDRVRawState *s = bs->opaque;
1048
    int last_media_present;
1049

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

    
1091
static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1092
{
1093
    BDRVRawState *s = bs->opaque;
1094

    
1095
    return ioctl(s->fd, req, buf);
1096
}
1097

    
1098
static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
1099
        unsigned long int req, void *buf,
1100
        BlockDriverCompletionFunc *cb, void *opaque)
1101
{
1102
    BDRVRawState *s = bs->opaque;
1103

    
1104
    if (fd_open(bs) < 0)
1105
        return NULL;
1106
    return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
1107
}
1108

    
1109
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1110
static int fd_open(BlockDriverState *bs)
1111
{
1112
    BDRVRawState *s = bs->opaque;
1113

    
1114
    /* this is just to ensure s->fd is sane (its called by io ops) */
1115
    if (s->fd >= 0)
1116
        return 0;
1117
    return -EIO;
1118
}
1119
#else /* !linux && !FreeBSD */
1120

    
1121
static int fd_open(BlockDriverState *bs)
1122
{
1123
    return 0;
1124
}
1125

    
1126
#endif /* !linux && !FreeBSD */
1127

    
1128
static int hdev_create(const char *filename, QEMUOptionParameter *options)
1129
{
1130
    int fd;
1131
    int ret = 0;
1132
    struct stat stat_buf;
1133
    int64_t total_size = 0;
1134

    
1135
    /* Read out options */
1136
    while (options && options->name) {
1137
        if (!strcmp(options->name, "size")) {
1138
            total_size = options->value.n / BDRV_SECTOR_SIZE;
1139
        }
1140
        options++;
1141
    }
1142

    
1143
    fd = open(filename, O_WRONLY | O_BINARY);
1144
    if (fd < 0)
1145
        return -errno;
1146

    
1147
    if (fstat(fd, &stat_buf) < 0)
1148
        ret = -errno;
1149
    else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
1150
        ret = -ENODEV;
1151
    else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
1152
        ret = -ENOSPC;
1153

    
1154
    close(fd);
1155
    return ret;
1156
}
1157

    
1158
static int hdev_has_zero_init(BlockDriverState *bs)
1159
{
1160
    return 0;
1161
}
1162

    
1163
static BlockDriver bdrv_host_device = {
1164
    .format_name        = "host_device",
1165
    .protocol_name        = "host_device",
1166
    .instance_size      = sizeof(BDRVRawState),
1167
    .bdrv_probe_device  = hdev_probe_device,
1168
    .bdrv_file_open     = hdev_open,
1169
    .bdrv_close         = raw_close,
1170
    .bdrv_create        = hdev_create,
1171
    .create_options     = raw_create_options,
1172
    .bdrv_has_zero_init = hdev_has_zero_init,
1173
    .bdrv_flush         = raw_flush,
1174

    
1175
    .bdrv_aio_readv        = raw_aio_readv,
1176
    .bdrv_aio_writev        = raw_aio_writev,
1177
    .bdrv_aio_flush        = raw_aio_flush,
1178

    
1179
    .bdrv_read          = raw_read,
1180
    .bdrv_write         = raw_write,
1181
    .bdrv_getlength        = raw_getlength,
1182
    .bdrv_get_allocated_file_size
1183
                        = raw_get_allocated_file_size,
1184

    
1185
    /* generic scsi device */
1186
#ifdef __linux__
1187
    .bdrv_ioctl         = hdev_ioctl,
1188
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1189
#endif
1190
};
1191

    
1192
#ifdef __linux__
1193
static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
1194
{
1195
    BDRVRawState *s = bs->opaque;
1196
    int ret;
1197

    
1198
    s->type = FTYPE_FD;
1199

    
1200
    /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
1201
    ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
1202
    if (ret)
1203
        return ret;
1204

    
1205
    /* close fd so that we can reopen it as needed */
1206
    close(s->fd);
1207
    s->fd = -1;
1208
    s->fd_media_changed = 1;
1209

    
1210
    return 0;
1211
}
1212

    
1213
static int floppy_probe_device(const char *filename)
1214
{
1215
    int fd, ret;
1216
    int prio = 0;
1217
    struct floppy_struct fdparam;
1218
    struct stat st;
1219

    
1220
    if (strstart(filename, "/dev/fd", NULL))
1221
        prio = 50;
1222

    
1223
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1224
    if (fd < 0) {
1225
        goto out;
1226
    }
1227
    ret = fstat(fd, &st);
1228
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
1229
        goto outc;
1230
    }
1231

    
1232
    /* Attempt to detect via a floppy specific ioctl */
1233
    ret = ioctl(fd, FDGETPRM, &fdparam);
1234
    if (ret >= 0)
1235
        prio = 100;
1236

    
1237
outc:
1238
    close(fd);
1239
out:
1240
    return prio;
1241
}
1242

    
1243

    
1244
static int floppy_is_inserted(BlockDriverState *bs)
1245
{
1246
    return fd_open(bs) >= 0;
1247
}
1248

    
1249
static int floppy_media_changed(BlockDriverState *bs)
1250
{
1251
    BDRVRawState *s = bs->opaque;
1252
    int ret;
1253

    
1254
    /*
1255
     * XXX: we do not have a true media changed indication.
1256
     * It does not work if the floppy is changed without trying to read it.
1257
     */
1258
    fd_open(bs);
1259
    ret = s->fd_media_changed;
1260
    s->fd_media_changed = 0;
1261
#ifdef DEBUG_FLOPPY
1262
    printf("Floppy changed=%d\n", ret);
1263
#endif
1264
    return ret;
1265
}
1266

    
1267
static void floppy_eject(BlockDriverState *bs, int eject_flag)
1268
{
1269
    BDRVRawState *s = bs->opaque;
1270
    int fd;
1271

    
1272
    if (s->fd >= 0) {
1273
        close(s->fd);
1274
        s->fd = -1;
1275
    }
1276
    fd = open(bs->filename, s->open_flags | O_NONBLOCK);
1277
    if (fd >= 0) {
1278
        if (ioctl(fd, FDEJECT, 0) < 0)
1279
            perror("FDEJECT");
1280
        close(fd);
1281
    }
1282
}
1283

    
1284
static BlockDriver bdrv_host_floppy = {
1285
    .format_name        = "host_floppy",
1286
    .protocol_name      = "host_floppy",
1287
    .instance_size      = sizeof(BDRVRawState),
1288
    .bdrv_probe_device        = floppy_probe_device,
1289
    .bdrv_file_open     = floppy_open,
1290
    .bdrv_close         = raw_close,
1291
    .bdrv_create        = hdev_create,
1292
    .create_options     = raw_create_options,
1293
    .bdrv_has_zero_init = hdev_has_zero_init,
1294
    .bdrv_flush         = raw_flush,
1295

    
1296
    .bdrv_aio_readv     = raw_aio_readv,
1297
    .bdrv_aio_writev    = raw_aio_writev,
1298
    .bdrv_aio_flush        = raw_aio_flush,
1299

    
1300
    .bdrv_read          = raw_read,
1301
    .bdrv_write         = raw_write,
1302
    .bdrv_getlength        = raw_getlength,
1303
    .bdrv_get_allocated_file_size
1304
                        = raw_get_allocated_file_size,
1305

    
1306
    /* removable device support */
1307
    .bdrv_is_inserted   = floppy_is_inserted,
1308
    .bdrv_media_changed = floppy_media_changed,
1309
    .bdrv_eject         = floppy_eject,
1310
};
1311

    
1312
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1313
{
1314
    BDRVRawState *s = bs->opaque;
1315

    
1316
    s->type = FTYPE_CD;
1317

    
1318
    /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
1319
    return raw_open_common(bs, filename, flags, O_NONBLOCK);
1320
}
1321

    
1322
static int cdrom_probe_device(const char *filename)
1323
{
1324
    int fd, ret;
1325
    int prio = 0;
1326
    struct stat st;
1327

    
1328
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1329
    if (fd < 0) {
1330
        goto out;
1331
    }
1332
    ret = fstat(fd, &st);
1333
    if (ret == -1 || !S_ISBLK(st.st_mode)) {
1334
        goto outc;
1335
    }
1336

    
1337
    /* Attempt to detect via a CDROM specific ioctl */
1338
    ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1339
    if (ret >= 0)
1340
        prio = 100;
1341

    
1342
outc:
1343
    close(fd);
1344
out:
1345
    return prio;
1346
}
1347

    
1348
static int cdrom_is_inserted(BlockDriverState *bs)
1349
{
1350
    BDRVRawState *s = bs->opaque;
1351
    int ret;
1352

    
1353
    ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1354
    if (ret == CDS_DISC_OK)
1355
        return 1;
1356
    return 0;
1357
}
1358

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

    
1363
    if (eject_flag) {
1364
        if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
1365
            perror("CDROMEJECT");
1366
    } else {
1367
        if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
1368
            perror("CDROMEJECT");
1369
    }
1370
}
1371

    
1372
static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
1373
{
1374
    BDRVRawState *s = bs->opaque;
1375

    
1376
    if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
1377
        /*
1378
         * Note: an error can happen if the distribution automatically
1379
         * mounts the CD-ROM
1380
         */
1381
        /* perror("CDROM_LOCKDOOR"); */
1382
    }
1383
}
1384

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

    
1397
    .bdrv_aio_readv     = raw_aio_readv,
1398
    .bdrv_aio_writev    = raw_aio_writev,
1399
    .bdrv_aio_flush        = raw_aio_flush,
1400

    
1401
    .bdrv_read          = raw_read,
1402
    .bdrv_write         = raw_write,
1403
    .bdrv_getlength     = raw_getlength,
1404
    .bdrv_get_allocated_file_size
1405
                        = raw_get_allocated_file_size,
1406

    
1407
    /* removable device support */
1408
    .bdrv_is_inserted   = cdrom_is_inserted,
1409
    .bdrv_eject         = cdrom_eject,
1410
    .bdrv_lock_medium   = cdrom_lock_medium,
1411

    
1412
    /* generic scsi device */
1413
    .bdrv_ioctl         = hdev_ioctl,
1414
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1415
};
1416
#endif /* __linux__ */
1417

    
1418
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1419
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1420
{
1421
    BDRVRawState *s = bs->opaque;
1422
    int ret;
1423

    
1424
    s->type = FTYPE_CD;
1425

    
1426
    ret = raw_open_common(bs, filename, flags, 0);
1427
    if (ret)
1428
        return ret;
1429

    
1430
    /* make sure the door isnt locked at this time */
1431
    ioctl(s->fd, CDIOCALLOW);
1432
    return 0;
1433
}
1434

    
1435
static int cdrom_probe_device(const char *filename)
1436
{
1437
    if (strstart(filename, "/dev/cd", NULL) ||
1438
            strstart(filename, "/dev/acd", NULL))
1439
        return 100;
1440
    return 0;
1441
}
1442

    
1443
static int cdrom_reopen(BlockDriverState *bs)
1444
{
1445
    BDRVRawState *s = bs->opaque;
1446
    int fd;
1447

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

    
1461
    /* make sure the door isnt locked at this time */
1462
    ioctl(s->fd, CDIOCALLOW);
1463
    return 0;
1464
}
1465

    
1466
static int cdrom_is_inserted(BlockDriverState *bs)
1467
{
1468
    return raw_getlength(bs) > 0;
1469
}
1470

    
1471
static void cdrom_eject(BlockDriverState *bs, int eject_flag)
1472
{
1473
    BDRVRawState *s = bs->opaque;
1474

    
1475
    if (s->fd < 0)
1476
        return;
1477

    
1478
    (void) ioctl(s->fd, CDIOCALLOW);
1479

    
1480
    if (eject_flag) {
1481
        if (ioctl(s->fd, CDIOCEJECT) < 0)
1482
            perror("CDIOCEJECT");
1483
    } else {
1484
        if (ioctl(s->fd, CDIOCCLOSE) < 0)
1485
            perror("CDIOCCLOSE");
1486
    }
1487

    
1488
    cdrom_reopen(bs);
1489
}
1490

    
1491
static void cdrom_lock_medium(BlockDriverState *bs, bool locked)
1492
{
1493
    BDRVRawState *s = bs->opaque;
1494

    
1495
    if (s->fd < 0)
1496
        return;
1497
    if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1498
        /*
1499
         * Note: an error can happen if the distribution automatically
1500
         * mounts the CD-ROM
1501
         */
1502
        /* perror("CDROM_LOCKDOOR"); */
1503
    }
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_lock_medium   = cdrom_lock_medium,
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);