~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to block/raw-posix.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

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