Statistics
| Branch: | Revision:

root / block / raw-posix.c @ 5bc89ef6

History | View | Annotate | Download (34.2 kB)

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