Statistics
| Branch: | Revision:

root / block / raw-posix.c @ 205ef796

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