Statistics
| Branch: | Revision:

root / block / raw-posix.c @ 333c574d

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