Statistics
| Branch: | Revision:

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

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