Statistics
| Branch: | Revision:

root / block-raw-posix.c @ 2cade6a3

History | View | Annotate | Download (30.2 kB)

1 83f64091 bellard
/*
2 223d4670 ths
 * Block driver for RAW files (posix)
3 5fafdf24 ths
 *
4 83f64091 bellard
 * Copyright (c) 2006 Fabrice Bellard
5 5fafdf24 ths
 *
6 83f64091 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 83f64091 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 83f64091 bellard
 * in the Software without restriction, including without limitation the rights
9 83f64091 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 83f64091 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 83f64091 bellard
 * furnished to do so, subject to the following conditions:
12 83f64091 bellard
 *
13 83f64091 bellard
 * The above copyright notice and this permission notice shall be included in
14 83f64091 bellard
 * all copies or substantial portions of the Software.
15 83f64091 bellard
 *
16 83f64091 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 83f64091 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 83f64091 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 83f64091 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 83f64091 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 83f64091 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 83f64091 bellard
 * THE SOFTWARE.
23 83f64091 bellard
 */
24 faf07963 pbrook
#include "qemu-common.h"
25 2f726488 ths
#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
26 87ecb68b pbrook
#include "qemu-timer.h"
27 ae5fc450 pbrook
#include "exec-all.h"
28 faf07963 pbrook
#endif
29 83f64091 bellard
#include "block_int.h"
30 83f64091 bellard
#include <assert.h>
31 83f64091 bellard
#include <aio.h>
32 83f64091 bellard
33 83f64091 bellard
#ifdef CONFIG_COCOA
34 83f64091 bellard
#include <paths.h>
35 83f64091 bellard
#include <sys/param.h>
36 83f64091 bellard
#include <IOKit/IOKitLib.h>
37 83f64091 bellard
#include <IOKit/IOBSD.h>
38 83f64091 bellard
#include <IOKit/storage/IOMediaBSDClient.h>
39 83f64091 bellard
#include <IOKit/storage/IOMedia.h>
40 83f64091 bellard
#include <IOKit/storage/IOCDMedia.h>
41 83f64091 bellard
//#include <IOKit/storage/IOCDTypes.h>
42 83f64091 bellard
#include <CoreFoundation/CoreFoundation.h>
43 83f64091 bellard
#endif
44 83f64091 bellard
45 83f64091 bellard
#ifdef __sun__
46 2e9671da ths
#define _POSIX_PTHREAD_SEMANTICS 1
47 2e9671da ths
#include <signal.h>
48 83f64091 bellard
#include <sys/dkio.h>
49 83f64091 bellard
#endif
50 19cb3738 bellard
#ifdef __linux__
51 19cb3738 bellard
#include <sys/ioctl.h>
52 19cb3738 bellard
#include <linux/cdrom.h>
53 19cb3738 bellard
#include <linux/fd.h>
54 19cb3738 bellard
#endif
55 1cb6c3fd ths
#ifdef __FreeBSD__
56 1cb6c3fd ths
#include <sys/disk.h>
57 1cb6c3fd ths
#endif
58 83f64091 bellard
59 19cb3738 bellard
//#define DEBUG_FLOPPY
60 83f64091 bellard
61 faf07963 pbrook
//#define DEBUG_BLOCK
62 2f726488 ths
#if defined(DEBUG_BLOCK) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
63 a50a6282 balrog
#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0)        \
64 2e03286b balrog
    { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
65 8c05dbf9 ths
#else
66 8c05dbf9 ths
#define DEBUG_BLOCK_PRINT(formatCstr, args...)
67 8c05dbf9 ths
#endif
68 8c05dbf9 ths
69 19cb3738 bellard
#define FTYPE_FILE   0
70 19cb3738 bellard
#define FTYPE_CD     1
71 19cb3738 bellard
#define FTYPE_FD     2
72 83f64091 bellard
73 bed5cc52 bellard
#define ALIGNED_BUFFER_SIZE (32 * 512)
74 bed5cc52 bellard
75 19cb3738 bellard
/* if the FD is not accessed during that time (in ms), we try to
76 19cb3738 bellard
   reopen it to see if the disk has been changed */
77 19cb3738 bellard
#define FD_OPEN_TIMEOUT 1000
78 83f64091 bellard
79 19cb3738 bellard
typedef struct BDRVRawState {
80 19cb3738 bellard
    int fd;
81 19cb3738 bellard
    int type;
82 8c05dbf9 ths
    unsigned int lseek_err_cnt;
83 19cb3738 bellard
#if defined(__linux__)
84 19cb3738 bellard
    /* linux floppy specific */
85 6dd2db52 blueswir1
    int fd_open_flags;
86 19cb3738 bellard
    int64_t fd_open_time;
87 19cb3738 bellard
    int64_t fd_error_time;
88 19cb3738 bellard
    int fd_got_error;
89 19cb3738 bellard
    int fd_media_changed;
90 83f64091 bellard
#endif
91 bed5cc52 bellard
#if defined(O_DIRECT) && !defined(QEMU_IMG)
92 bed5cc52 bellard
    uint8_t* aligned_buf;
93 bed5cc52 bellard
#endif
94 19cb3738 bellard
} BDRVRawState;
95 19cb3738 bellard
96 19cb3738 bellard
static int fd_open(BlockDriverState *bs);
97 83f64091 bellard
98 83f64091 bellard
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
99 83f64091 bellard
{
100 83f64091 bellard
    BDRVRawState *s = bs->opaque;
101 19cb3738 bellard
    int fd, open_flags, ret;
102 83f64091 bellard
103 8c05dbf9 ths
    s->lseek_err_cnt = 0;
104 8c05dbf9 ths
105 83f64091 bellard
    open_flags = O_BINARY;
106 83f64091 bellard
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
107 83f64091 bellard
        open_flags |= O_RDWR;
108 83f64091 bellard
    } else {
109 83f64091 bellard
        open_flags |= O_RDONLY;
110 83f64091 bellard
        bs->read_only = 1;
111 83f64091 bellard
    }
112 83f64091 bellard
    if (flags & BDRV_O_CREAT)
113 83f64091 bellard
        open_flags |= O_CREAT | O_TRUNC;
114 33f00271 balrog
#ifdef O_DIRECT
115 33f00271 balrog
    if (flags & BDRV_O_DIRECT)
116 33f00271 balrog
        open_flags |= O_DIRECT;
117 33f00271 balrog
#endif
118 83f64091 bellard
119 19cb3738 bellard
    s->type = FTYPE_FILE;
120 19cb3738 bellard
121 83f64091 bellard
    fd = open(filename, open_flags, 0644);
122 19cb3738 bellard
    if (fd < 0) {
123 19cb3738 bellard
        ret = -errno;
124 19cb3738 bellard
        if (ret == -EROFS)
125 19cb3738 bellard
            ret = -EACCES;
126 19cb3738 bellard
        return ret;
127 19cb3738 bellard
    }
128 83f64091 bellard
    s->fd = fd;
129 bed5cc52 bellard
#if defined(O_DIRECT) && !defined(QEMU_IMG)
130 bed5cc52 bellard
    s->aligned_buf = NULL;
131 bed5cc52 bellard
    if (flags & BDRV_O_DIRECT) {
132 bed5cc52 bellard
        s->aligned_buf = qemu_memalign(512, ALIGNED_BUFFER_SIZE);
133 bed5cc52 bellard
        if (s->aligned_buf == NULL) {
134 bed5cc52 bellard
            ret = -errno;
135 bed5cc52 bellard
            close(fd);
136 bed5cc52 bellard
            return ret;
137 bed5cc52 bellard
        }
138 bed5cc52 bellard
    }
139 bed5cc52 bellard
#endif
140 83f64091 bellard
    return 0;
141 83f64091 bellard
}
142 83f64091 bellard
143 83f64091 bellard
/* XXX: use host sector size if necessary with:
144 83f64091 bellard
#ifdef DIOCGSECTORSIZE
145 83f64091 bellard
        {
146 83f64091 bellard
            unsigned int sectorsize = 512;
147 83f64091 bellard
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
148 83f64091 bellard
                sectorsize > bufsize)
149 83f64091 bellard
                bufsize = sectorsize;
150 83f64091 bellard
        }
151 83f64091 bellard
#endif
152 83f64091 bellard
#ifdef CONFIG_COCOA
153 83f64091 bellard
        u_int32_t   blockSize = 512;
154 83f64091 bellard
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
155 83f64091 bellard
            bufsize = blockSize;
156 83f64091 bellard
        }
157 83f64091 bellard
#endif
158 83f64091 bellard
*/
159 83f64091 bellard
160 bed5cc52 bellard
/*
161 bed5cc52 bellard
 * offset and count are in bytes, but must be multiples of 512 for files
162 bed5cc52 bellard
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
163 bed5cc52 bellard
 *
164 bed5cc52 bellard
 * This function may be called without alignment if the caller ensures
165 bed5cc52 bellard
 * that O_DIRECT is not in effect.
166 bed5cc52 bellard
 */
167 bed5cc52 bellard
static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
168 83f64091 bellard
                     uint8_t *buf, int count)
169 83f64091 bellard
{
170 83f64091 bellard
    BDRVRawState *s = bs->opaque;
171 83f64091 bellard
    int ret;
172 3b46e624 ths
173 19cb3738 bellard
    ret = fd_open(bs);
174 19cb3738 bellard
    if (ret < 0)
175 19cb3738 bellard
        return ret;
176 19cb3738 bellard
177 985a03b0 ths
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
178 8c05dbf9 ths
        ++(s->lseek_err_cnt);
179 8c05dbf9 ths
        if(s->lseek_err_cnt <= 10) {
180 92868412 j_mayer
            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
181 92868412 j_mayer
                              "] lseek failed : %d = %s\n",
182 8c05dbf9 ths
                              s->fd, bs->filename, offset, buf, count,
183 8c05dbf9 ths
                              bs->total_sectors, errno, strerror(errno));
184 8c05dbf9 ths
        }
185 8c05dbf9 ths
        return -1;
186 8c05dbf9 ths
    }
187 8c05dbf9 ths
    s->lseek_err_cnt=0;
188 8c05dbf9 ths
189 83f64091 bellard
    ret = read(s->fd, buf, count);
190 8c05dbf9 ths
    if (ret == count)
191 8c05dbf9 ths
        goto label__raw_read__success;
192 8c05dbf9 ths
193 92868412 j_mayer
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
194 92868412 j_mayer
                      "] read failed %d : %d = %s\n",
195 8c05dbf9 ths
                      s->fd, bs->filename, offset, buf, count,
196 8c05dbf9 ths
                      bs->total_sectors, ret, errno, strerror(errno));
197 8c05dbf9 ths
198 8c05dbf9 ths
    /* Try harder for CDrom. */
199 8c05dbf9 ths
    if (bs->type == BDRV_TYPE_CDROM) {
200 8c05dbf9 ths
        lseek(s->fd, offset, SEEK_SET);
201 8c05dbf9 ths
        ret = read(s->fd, buf, count);
202 8c05dbf9 ths
        if (ret == count)
203 8c05dbf9 ths
            goto label__raw_read__success;
204 8c05dbf9 ths
        lseek(s->fd, offset, SEEK_SET);
205 8c05dbf9 ths
        ret = read(s->fd, buf, count);
206 8c05dbf9 ths
        if (ret == count)
207 8c05dbf9 ths
            goto label__raw_read__success;
208 8c05dbf9 ths
209 92868412 j_mayer
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
210 92868412 j_mayer
                          "] retry read failed %d : %d = %s\n",
211 8c05dbf9 ths
                          s->fd, bs->filename, offset, buf, count,
212 8c05dbf9 ths
                          bs->total_sectors, ret, errno, strerror(errno));
213 8c05dbf9 ths
    }
214 8c05dbf9 ths
215 8c05dbf9 ths
label__raw_read__success:
216 8c05dbf9 ths
217 83f64091 bellard
    return ret;
218 83f64091 bellard
}
219 83f64091 bellard
220 bed5cc52 bellard
/*
221 bed5cc52 bellard
 * offset and count are in bytes, but must be multiples of 512 for files
222 bed5cc52 bellard
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
223 bed5cc52 bellard
 *
224 bed5cc52 bellard
 * This function may be called without alignment if the caller ensures
225 bed5cc52 bellard
 * that O_DIRECT is not in effect.
226 bed5cc52 bellard
 */
227 bed5cc52 bellard
static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
228 83f64091 bellard
                      const uint8_t *buf, int count)
229 83f64091 bellard
{
230 83f64091 bellard
    BDRVRawState *s = bs->opaque;
231 83f64091 bellard
    int ret;
232 3b46e624 ths
233 19cb3738 bellard
    ret = fd_open(bs);
234 19cb3738 bellard
    if (ret < 0)
235 19cb3738 bellard
        return ret;
236 19cb3738 bellard
237 985a03b0 ths
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
238 8c05dbf9 ths
        ++(s->lseek_err_cnt);
239 8c05dbf9 ths
        if(s->lseek_err_cnt) {
240 92868412 j_mayer
            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
241 92868412 j_mayer
                              PRId64 "] lseek failed : %d = %s\n",
242 8c05dbf9 ths
                              s->fd, bs->filename, offset, buf, count,
243 8c05dbf9 ths
                              bs->total_sectors, errno, strerror(errno));
244 8c05dbf9 ths
        }
245 8c05dbf9 ths
        return -1;
246 8c05dbf9 ths
    }
247 8c05dbf9 ths
    s->lseek_err_cnt = 0;
248 8c05dbf9 ths
249 83f64091 bellard
    ret = write(s->fd, buf, count);
250 8c05dbf9 ths
    if (ret == count)
251 8c05dbf9 ths
        goto label__raw_write__success;
252 8c05dbf9 ths
253 92868412 j_mayer
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
254 92868412 j_mayer
                      "] write failed %d : %d = %s\n",
255 8c05dbf9 ths
                      s->fd, bs->filename, offset, buf, count,
256 8c05dbf9 ths
                      bs->total_sectors, ret, errno, strerror(errno));
257 8c05dbf9 ths
258 8c05dbf9 ths
label__raw_write__success:
259 8c05dbf9 ths
260 83f64091 bellard
    return ret;
261 83f64091 bellard
}
262 83f64091 bellard
263 bed5cc52 bellard
264 bed5cc52 bellard
#if defined(O_DIRECT) && !defined(QEMU_IMG)
265 bed5cc52 bellard
/*
266 bed5cc52 bellard
 * offset and count are in bytes and possibly not aligned. For files opened
267 bed5cc52 bellard
 * with O_DIRECT, necessary alignments are ensured before calling
268 bed5cc52 bellard
 * raw_pread_aligned to do the actual read.
269 bed5cc52 bellard
 */
270 bed5cc52 bellard
static int raw_pread(BlockDriverState *bs, int64_t offset,
271 bed5cc52 bellard
                     uint8_t *buf, int count)
272 bed5cc52 bellard
{
273 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
274 bed5cc52 bellard
    int size, ret, shift, sum;
275 bed5cc52 bellard
276 bed5cc52 bellard
    sum = 0;
277 bed5cc52 bellard
278 bed5cc52 bellard
    if (s->aligned_buf != NULL)  {
279 bed5cc52 bellard
280 bed5cc52 bellard
        if (offset & 0x1ff) {
281 bed5cc52 bellard
            /* align offset on a 512 bytes boundary */
282 bed5cc52 bellard
283 bed5cc52 bellard
            shift = offset & 0x1ff;
284 bed5cc52 bellard
            size = (shift + count + 0x1ff) & ~0x1ff;
285 bed5cc52 bellard
            if (size > ALIGNED_BUFFER_SIZE)
286 bed5cc52 bellard
                size = ALIGNED_BUFFER_SIZE;
287 bed5cc52 bellard
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
288 bed5cc52 bellard
            if (ret < 0)
289 bed5cc52 bellard
                return ret;
290 bed5cc52 bellard
291 bed5cc52 bellard
            size = 512 - shift;
292 bed5cc52 bellard
            if (size > count)
293 bed5cc52 bellard
                size = count;
294 bed5cc52 bellard
            memcpy(buf, s->aligned_buf + shift, size);
295 bed5cc52 bellard
296 bed5cc52 bellard
            buf += size;
297 bed5cc52 bellard
            offset += size;
298 bed5cc52 bellard
            count -= size;
299 bed5cc52 bellard
            sum += size;
300 bed5cc52 bellard
301 bed5cc52 bellard
            if (count == 0)
302 bed5cc52 bellard
                return sum;
303 bed5cc52 bellard
        }
304 bed5cc52 bellard
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
305 bed5cc52 bellard
306 bed5cc52 bellard
            /* read on aligned buffer */
307 bed5cc52 bellard
308 bed5cc52 bellard
            while (count) {
309 bed5cc52 bellard
310 bed5cc52 bellard
                size = (count + 0x1ff) & ~0x1ff;
311 bed5cc52 bellard
                if (size > ALIGNED_BUFFER_SIZE)
312 bed5cc52 bellard
                    size = ALIGNED_BUFFER_SIZE;
313 bed5cc52 bellard
314 bed5cc52 bellard
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
315 bed5cc52 bellard
                if (ret < 0)
316 bed5cc52 bellard
                    return ret;
317 bed5cc52 bellard
318 bed5cc52 bellard
                size = ret;
319 bed5cc52 bellard
                if (size > count)
320 bed5cc52 bellard
                    size = count;
321 bed5cc52 bellard
322 bed5cc52 bellard
                memcpy(buf, s->aligned_buf, size);
323 bed5cc52 bellard
324 bed5cc52 bellard
                buf += size;
325 bed5cc52 bellard
                offset += size;
326 bed5cc52 bellard
                count -= size;
327 bed5cc52 bellard
                sum += size;
328 bed5cc52 bellard
            }
329 bed5cc52 bellard
330 bed5cc52 bellard
            return sum;
331 bed5cc52 bellard
        }
332 bed5cc52 bellard
    }
333 bed5cc52 bellard
334 bed5cc52 bellard
    return raw_pread_aligned(bs, offset, buf, count) + sum;
335 bed5cc52 bellard
}
336 bed5cc52 bellard
337 bed5cc52 bellard
/*
338 bed5cc52 bellard
 * offset and count are in bytes and possibly not aligned. For files opened
339 bed5cc52 bellard
 * with O_DIRECT, necessary alignments are ensured before calling
340 bed5cc52 bellard
 * raw_pwrite_aligned to do the actual write.
341 bed5cc52 bellard
 */
342 bed5cc52 bellard
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
343 bed5cc52 bellard
                      const uint8_t *buf, int count)
344 bed5cc52 bellard
{
345 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
346 bed5cc52 bellard
    int size, ret, shift, sum;
347 bed5cc52 bellard
348 bed5cc52 bellard
    sum = 0;
349 bed5cc52 bellard
350 bed5cc52 bellard
    if (s->aligned_buf != NULL) {
351 bed5cc52 bellard
352 bed5cc52 bellard
        if (offset & 0x1ff) {
353 bed5cc52 bellard
            /* align offset on a 512 bytes boundary */
354 bed5cc52 bellard
            shift = offset & 0x1ff;
355 bed5cc52 bellard
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
356 bed5cc52 bellard
            if (ret < 0)
357 bed5cc52 bellard
                return ret;
358 bed5cc52 bellard
359 bed5cc52 bellard
            size = 512 - shift;
360 bed5cc52 bellard
            if (size > count)
361 bed5cc52 bellard
                size = count;
362 bed5cc52 bellard
            memcpy(s->aligned_buf + shift, buf, size);
363 bed5cc52 bellard
364 bed5cc52 bellard
            ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
365 bed5cc52 bellard
            if (ret < 0)
366 bed5cc52 bellard
                return ret;
367 bed5cc52 bellard
368 bed5cc52 bellard
            buf += size;
369 bed5cc52 bellard
            offset += size;
370 bed5cc52 bellard
            count -= size;
371 bed5cc52 bellard
            sum += size;
372 bed5cc52 bellard
373 bed5cc52 bellard
            if (count == 0)
374 bed5cc52 bellard
                return sum;
375 bed5cc52 bellard
        }
376 bed5cc52 bellard
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
377 bed5cc52 bellard
378 bed5cc52 bellard
            while ((size = (count & ~0x1ff)) != 0) {
379 bed5cc52 bellard
380 bed5cc52 bellard
                if (size > ALIGNED_BUFFER_SIZE)
381 bed5cc52 bellard
                    size = ALIGNED_BUFFER_SIZE;
382 bed5cc52 bellard
383 bed5cc52 bellard
                memcpy(s->aligned_buf, buf, size);
384 bed5cc52 bellard
385 bed5cc52 bellard
                ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
386 bed5cc52 bellard
                if (ret < 0)
387 bed5cc52 bellard
                    return ret;
388 bed5cc52 bellard
389 bed5cc52 bellard
                buf += ret;
390 bed5cc52 bellard
                offset += ret;
391 bed5cc52 bellard
                count -= ret;
392 bed5cc52 bellard
                sum += ret;
393 bed5cc52 bellard
            }
394 bed5cc52 bellard
            /* here, count < 512 because (count & ~0x1ff) == 0 */
395 bed5cc52 bellard
            if (count) {
396 bed5cc52 bellard
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
397 bed5cc52 bellard
                if (ret < 0)
398 bed5cc52 bellard
                    return ret;
399 bed5cc52 bellard
                 memcpy(s->aligned_buf, buf, count);
400 bed5cc52 bellard
401 bed5cc52 bellard
                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
402 bed5cc52 bellard
                 if (ret < 0)
403 bed5cc52 bellard
                     return ret;
404 bed5cc52 bellard
                 if (count < ret)
405 bed5cc52 bellard
                     ret = count;
406 bed5cc52 bellard
407 bed5cc52 bellard
                 sum += ret;
408 bed5cc52 bellard
            }
409 bed5cc52 bellard
            return sum;
410 bed5cc52 bellard
        }
411 bed5cc52 bellard
    }
412 bed5cc52 bellard
    return raw_pwrite_aligned(bs, offset, buf, count) + sum;
413 bed5cc52 bellard
}
414 bed5cc52 bellard
415 bed5cc52 bellard
#else
416 bed5cc52 bellard
#define raw_pread raw_pread_aligned
417 bed5cc52 bellard
#define raw_pwrite raw_pwrite_aligned
418 bed5cc52 bellard
#endif
419 bed5cc52 bellard
420 bed5cc52 bellard
421 83f64091 bellard
/***********************************************************/
422 19cb3738 bellard
/* Unix AIO using POSIX AIO */
423 83f64091 bellard
424 83f64091 bellard
typedef struct RawAIOCB {
425 ce1a14dc pbrook
    BlockDriverAIOCB common;
426 83f64091 bellard
    struct aiocb aiocb;
427 ce1a14dc pbrook
    struct RawAIOCB *next;
428 bed5cc52 bellard
    int ret;
429 83f64091 bellard
} RawAIOCB;
430 83f64091 bellard
431 83f64091 bellard
static int aio_sig_num = SIGUSR2;
432 ce1a14dc pbrook
static RawAIOCB *first_aio; /* AIO issued */
433 979b67ad bellard
static int aio_initialized = 0;
434 83f64091 bellard
435 83f64091 bellard
static void aio_signal_handler(int signum)
436 83f64091 bellard
{
437 2f726488 ths
#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
438 83f64091 bellard
    CPUState *env = cpu_single_env;
439 83f64091 bellard
    if (env) {
440 83f64091 bellard
        /* stop the currently executing cpu because a timer occured */
441 83f64091 bellard
        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
442 83f64091 bellard
#ifdef USE_KQEMU
443 83f64091 bellard
        if (env->kqemu_enabled) {
444 83f64091 bellard
            kqemu_cpu_interrupt(env);
445 83f64091 bellard
        }
446 83f64091 bellard
#endif
447 83f64091 bellard
    }
448 979b67ad bellard
#endif
449 83f64091 bellard
}
450 83f64091 bellard
451 83f64091 bellard
void qemu_aio_init(void)
452 83f64091 bellard
{
453 83f64091 bellard
    struct sigaction act;
454 979b67ad bellard
455 979b67ad bellard
    aio_initialized = 1;
456 3b46e624 ths
457 83f64091 bellard
    sigfillset(&act.sa_mask);
458 83f64091 bellard
    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
459 83f64091 bellard
    act.sa_handler = aio_signal_handler;
460 83f64091 bellard
    sigaction(aio_sig_num, &act, NULL);
461 83f64091 bellard
462 19cb3738 bellard
#if defined(__GLIBC__) && defined(__linux__)
463 83f64091 bellard
    {
464 19cb3738 bellard
        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
465 19cb3738 bellard
           seems to fix the problem. */
466 83f64091 bellard
        struct aioinit ai;
467 83f64091 bellard
        memset(&ai, 0, sizeof(ai));
468 01534fe9 bellard
        ai.aio_threads = 1;
469 01534fe9 bellard
        ai.aio_num = 1;
470 83f64091 bellard
        ai.aio_idle_time = 365 * 100000;
471 83f64091 bellard
        aio_init(&ai);
472 83f64091 bellard
    }
473 19cb3738 bellard
#endif
474 83f64091 bellard
}
475 83f64091 bellard
476 83f64091 bellard
void qemu_aio_poll(void)
477 83f64091 bellard
{
478 ce1a14dc pbrook
    RawAIOCB *acb, **pacb;
479 83f64091 bellard
    int ret;
480 83f64091 bellard
481 83f64091 bellard
    for(;;) {
482 83f64091 bellard
        pacb = &first_aio;
483 83f64091 bellard
        for(;;) {
484 83f64091 bellard
            acb = *pacb;
485 83f64091 bellard
            if (!acb)
486 83f64091 bellard
                goto the_end;
487 ce1a14dc pbrook
            ret = aio_error(&acb->aiocb);
488 83f64091 bellard
            if (ret == ECANCELED) {
489 83f64091 bellard
                /* remove the request */
490 ce1a14dc pbrook
                *pacb = acb->next;
491 ce1a14dc pbrook
                qemu_aio_release(acb);
492 83f64091 bellard
            } else if (ret != EINPROGRESS) {
493 83f64091 bellard
                /* end of aio */
494 83f64091 bellard
                if (ret == 0) {
495 ce1a14dc pbrook
                    ret = aio_return(&acb->aiocb);
496 ce1a14dc pbrook
                    if (ret == acb->aiocb.aio_nbytes)
497 83f64091 bellard
                        ret = 0;
498 83f64091 bellard
                    else
499 19cb3738 bellard
                        ret = -EINVAL;
500 83f64091 bellard
                } else {
501 83f64091 bellard
                    ret = -ret;
502 83f64091 bellard
                }
503 83f64091 bellard
                /* remove the request */
504 ce1a14dc pbrook
                *pacb = acb->next;
505 83f64091 bellard
                /* call the callback */
506 ce1a14dc pbrook
                acb->common.cb(acb->common.opaque, ret);
507 ce1a14dc pbrook
                qemu_aio_release(acb);
508 83f64091 bellard
                break;
509 83f64091 bellard
            } else {
510 ce1a14dc pbrook
                pacb = &acb->next;
511 83f64091 bellard
            }
512 83f64091 bellard
        }
513 83f64091 bellard
    }
514 83f64091 bellard
 the_end: ;
515 83f64091 bellard
}
516 83f64091 bellard
517 6192bc37 pbrook
/* Wait for all IO requests to complete.  */
518 6192bc37 pbrook
void qemu_aio_flush(void)
519 6192bc37 pbrook
{
520 6192bc37 pbrook
    qemu_aio_wait_start();
521 6192bc37 pbrook
    qemu_aio_poll();
522 6192bc37 pbrook
    while (first_aio) {
523 6192bc37 pbrook
        qemu_aio_wait();
524 6192bc37 pbrook
    }
525 6192bc37 pbrook
    qemu_aio_wait_end();
526 6192bc37 pbrook
}
527 6192bc37 pbrook
528 83f64091 bellard
/* wait until at least one AIO was handled */
529 83f64091 bellard
static sigset_t wait_oset;
530 83f64091 bellard
531 83f64091 bellard
void qemu_aio_wait_start(void)
532 83f64091 bellard
{
533 83f64091 bellard
    sigset_t set;
534 979b67ad bellard
535 979b67ad bellard
    if (!aio_initialized)
536 979b67ad bellard
        qemu_aio_init();
537 83f64091 bellard
    sigemptyset(&set);
538 83f64091 bellard
    sigaddset(&set, aio_sig_num);
539 83f64091 bellard
    sigprocmask(SIG_BLOCK, &set, &wait_oset);
540 83f64091 bellard
}
541 83f64091 bellard
542 83f64091 bellard
void qemu_aio_wait(void)
543 83f64091 bellard
{
544 83f64091 bellard
    sigset_t set;
545 83f64091 bellard
    int nb_sigs;
546 6eb5733a bellard
547 2f726488 ths
#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
548 6eb5733a bellard
    if (qemu_bh_poll())
549 6eb5733a bellard
        return;
550 6eb5733a bellard
#endif
551 83f64091 bellard
    sigemptyset(&set);
552 83f64091 bellard
    sigaddset(&set, aio_sig_num);
553 83f64091 bellard
    sigwait(&set, &nb_sigs);
554 83f64091 bellard
    qemu_aio_poll();
555 83f64091 bellard
}
556 83f64091 bellard
557 83f64091 bellard
void qemu_aio_wait_end(void)
558 83f64091 bellard
{
559 83f64091 bellard
    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
560 83f64091 bellard
}
561 83f64091 bellard
562 ce1a14dc pbrook
static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
563 ce1a14dc pbrook
        int64_t sector_num, uint8_t *buf, int nb_sectors,
564 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
565 83f64091 bellard
{
566 ce1a14dc pbrook
    BDRVRawState *s = bs->opaque;
567 ce1a14dc pbrook
    RawAIOCB *acb;
568 ce1a14dc pbrook
569 19cb3738 bellard
    if (fd_open(bs) < 0)
570 19cb3738 bellard
        return NULL;
571 19cb3738 bellard
572 ce1a14dc pbrook
    acb = qemu_aio_get(bs, cb, opaque);
573 ce1a14dc pbrook
    if (!acb)
574 ce1a14dc pbrook
        return NULL;
575 ce1a14dc pbrook
    acb->aiocb.aio_fildes = s->fd;
576 ce1a14dc pbrook
    acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
577 ce1a14dc pbrook
    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
578 ce1a14dc pbrook
    acb->aiocb.aio_buf = buf;
579 985a03b0 ths
    if (nb_sectors < 0)
580 985a03b0 ths
        acb->aiocb.aio_nbytes = -nb_sectors;
581 985a03b0 ths
    else
582 985a03b0 ths
        acb->aiocb.aio_nbytes = nb_sectors * 512;
583 ce1a14dc pbrook
    acb->aiocb.aio_offset = sector_num * 512;
584 ce1a14dc pbrook
    acb->next = first_aio;
585 ce1a14dc pbrook
    first_aio = acb;
586 ce1a14dc pbrook
    return acb;
587 83f64091 bellard
}
588 83f64091 bellard
589 2f726488 ths
#if !defined(QEMU_IMG) && !defined(QEMU_NBD)
590 bed5cc52 bellard
static void raw_aio_em_cb(void* opaque)
591 bed5cc52 bellard
{
592 bed5cc52 bellard
    RawAIOCB *acb = opaque;
593 bed5cc52 bellard
    acb->common.cb(acb->common.opaque, acb->ret);
594 bed5cc52 bellard
    qemu_aio_release(acb);
595 bed5cc52 bellard
}
596 bed5cc52 bellard
#endif
597 bed5cc52 bellard
598 ce1a14dc pbrook
static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
599 ce1a14dc pbrook
        int64_t sector_num, uint8_t *buf, int nb_sectors,
600 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
601 83f64091 bellard
{
602 ce1a14dc pbrook
    RawAIOCB *acb;
603 83f64091 bellard
604 bed5cc52 bellard
    /*
605 bed5cc52 bellard
     * If O_DIRECT is used and the buffer is not aligned fall back
606 bed5cc52 bellard
     * to synchronous IO.
607 bed5cc52 bellard
     */
608 2f726488 ths
#if defined(O_DIRECT) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
609 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
610 bed5cc52 bellard
611 bed5cc52 bellard
    if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
612 bed5cc52 bellard
        QEMUBH *bh;
613 bed5cc52 bellard
        acb = qemu_aio_get(bs, cb, opaque);
614 bed5cc52 bellard
        acb->ret = raw_pread(bs, 512 * sector_num, buf, 512 * nb_sectors);
615 bed5cc52 bellard
        bh = qemu_bh_new(raw_aio_em_cb, acb);
616 bed5cc52 bellard
        qemu_bh_schedule(bh);
617 bed5cc52 bellard
        return &acb->common;
618 bed5cc52 bellard
    }
619 bed5cc52 bellard
#endif
620 bed5cc52 bellard
621 ce1a14dc pbrook
    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
622 ce1a14dc pbrook
    if (!acb)
623 ce1a14dc pbrook
        return NULL;
624 ce1a14dc pbrook
    if (aio_read(&acb->aiocb) < 0) {
625 ce1a14dc pbrook
        qemu_aio_release(acb);
626 ce1a14dc pbrook
        return NULL;
627 5fafdf24 ths
    }
628 ce1a14dc pbrook
    return &acb->common;
629 83f64091 bellard
}
630 83f64091 bellard
631 ce1a14dc pbrook
static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
632 ce1a14dc pbrook
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
633 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
634 83f64091 bellard
{
635 ce1a14dc pbrook
    RawAIOCB *acb;
636 83f64091 bellard
637 bed5cc52 bellard
    /*
638 bed5cc52 bellard
     * If O_DIRECT is used and the buffer is not aligned fall back
639 bed5cc52 bellard
     * to synchronous IO.
640 bed5cc52 bellard
     */
641 2f726488 ths
#if defined(O_DIRECT) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
642 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
643 bed5cc52 bellard
644 bed5cc52 bellard
    if (unlikely(s->aligned_buf != NULL && ((uintptr_t) buf % 512))) {
645 bed5cc52 bellard
        QEMUBH *bh;
646 bed5cc52 bellard
        acb = qemu_aio_get(bs, cb, opaque);
647 bed5cc52 bellard
        acb->ret = raw_pwrite(bs, 512 * sector_num, buf, 512 * nb_sectors);
648 bed5cc52 bellard
        bh = qemu_bh_new(raw_aio_em_cb, acb);
649 bed5cc52 bellard
        qemu_bh_schedule(bh);
650 bed5cc52 bellard
        return &acb->common;
651 bed5cc52 bellard
    }
652 bed5cc52 bellard
#endif
653 bed5cc52 bellard
654 ce1a14dc pbrook
    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
655 ce1a14dc pbrook
    if (!acb)
656 ce1a14dc pbrook
        return NULL;
657 ce1a14dc pbrook
    if (aio_write(&acb->aiocb) < 0) {
658 ce1a14dc pbrook
        qemu_aio_release(acb);
659 ce1a14dc pbrook
        return NULL;
660 5fafdf24 ths
    }
661 ce1a14dc pbrook
    return &acb->common;
662 83f64091 bellard
}
663 83f64091 bellard
664 ce1a14dc pbrook
static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
665 83f64091 bellard
{
666 83f64091 bellard
    int ret;
667 ce1a14dc pbrook
    RawAIOCB *acb = (RawAIOCB *)blockacb;
668 ce1a14dc pbrook
    RawAIOCB **pacb;
669 83f64091 bellard
670 ce1a14dc pbrook
    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
671 83f64091 bellard
    if (ret == AIO_NOTCANCELED) {
672 83f64091 bellard
        /* fail safe: if the aio could not be canceled, we wait for
673 83f64091 bellard
           it */
674 ce1a14dc pbrook
        while (aio_error(&acb->aiocb) == EINPROGRESS);
675 83f64091 bellard
    }
676 83f64091 bellard
677 83f64091 bellard
    /* remove the callback from the queue */
678 83f64091 bellard
    pacb = &first_aio;
679 83f64091 bellard
    for(;;) {
680 83f64091 bellard
        if (*pacb == NULL) {
681 83f64091 bellard
            break;
682 83f64091 bellard
        } else if (*pacb == acb) {
683 ce1a14dc pbrook
            *pacb = acb->next;
684 ce1a14dc pbrook
            qemu_aio_release(acb);
685 83f64091 bellard
            break;
686 83f64091 bellard
        }
687 ce1a14dc pbrook
        pacb = &acb->next;
688 83f64091 bellard
    }
689 83f64091 bellard
}
690 83f64091 bellard
691 83f64091 bellard
static void raw_close(BlockDriverState *bs)
692 83f64091 bellard
{
693 83f64091 bellard
    BDRVRawState *s = bs->opaque;
694 19cb3738 bellard
    if (s->fd >= 0) {
695 19cb3738 bellard
        close(s->fd);
696 19cb3738 bellard
        s->fd = -1;
697 bed5cc52 bellard
#if defined(O_DIRECT) && !defined(QEMU_IMG)
698 bed5cc52 bellard
        if (s->aligned_buf != NULL)
699 bed5cc52 bellard
            qemu_free(s->aligned_buf);
700 bed5cc52 bellard
#endif
701 19cb3738 bellard
    }
702 83f64091 bellard
}
703 83f64091 bellard
704 83f64091 bellard
static int raw_truncate(BlockDriverState *bs, int64_t offset)
705 83f64091 bellard
{
706 83f64091 bellard
    BDRVRawState *s = bs->opaque;
707 19cb3738 bellard
    if (s->type != FTYPE_FILE)
708 19cb3738 bellard
        return -ENOTSUP;
709 83f64091 bellard
    if (ftruncate(s->fd, offset) < 0)
710 83f64091 bellard
        return -errno;
711 83f64091 bellard
    return 0;
712 83f64091 bellard
}
713 83f64091 bellard
714 83f64091 bellard
static int64_t  raw_getlength(BlockDriverState *bs)
715 83f64091 bellard
{
716 83f64091 bellard
    BDRVRawState *s = bs->opaque;
717 83f64091 bellard
    int fd = s->fd;
718 83f64091 bellard
    int64_t size;
719 83f64091 bellard
#ifdef _BSD
720 83f64091 bellard
    struct stat sb;
721 83f64091 bellard
#endif
722 83f64091 bellard
#ifdef __sun__
723 83f64091 bellard
    struct dk_minfo minfo;
724 83f64091 bellard
    int rv;
725 83f64091 bellard
#endif
726 19cb3738 bellard
    int ret;
727 19cb3738 bellard
728 19cb3738 bellard
    ret = fd_open(bs);
729 19cb3738 bellard
    if (ret < 0)
730 19cb3738 bellard
        return ret;
731 83f64091 bellard
732 83f64091 bellard
#ifdef _BSD
733 83f64091 bellard
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
734 83f64091 bellard
#ifdef DIOCGMEDIASIZE
735 83f64091 bellard
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
736 83f64091 bellard
#endif
737 83f64091 bellard
#ifdef CONFIG_COCOA
738 83f64091 bellard
        size = LONG_LONG_MAX;
739 83f64091 bellard
#else
740 83f64091 bellard
        size = lseek(fd, 0LL, SEEK_END);
741 83f64091 bellard
#endif
742 83f64091 bellard
    } else
743 83f64091 bellard
#endif
744 83f64091 bellard
#ifdef __sun__
745 83f64091 bellard
    /*
746 83f64091 bellard
     * use the DKIOCGMEDIAINFO ioctl to read the size.
747 83f64091 bellard
     */
748 83f64091 bellard
    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
749 83f64091 bellard
    if ( rv != -1 ) {
750 83f64091 bellard
        size = minfo.dki_lbsize * minfo.dki_capacity;
751 83f64091 bellard
    } else /* there are reports that lseek on some devices
752 83f64091 bellard
              fails, but irc discussion said that contingency
753 83f64091 bellard
              on contingency was overkill */
754 83f64091 bellard
#endif
755 83f64091 bellard
    {
756 83f64091 bellard
        size = lseek(fd, 0, SEEK_END);
757 83f64091 bellard
    }
758 83f64091 bellard
    return size;
759 83f64091 bellard
}
760 83f64091 bellard
761 83f64091 bellard
static int raw_create(const char *filename, int64_t total_size,
762 83f64091 bellard
                      const char *backing_file, int flags)
763 83f64091 bellard
{
764 83f64091 bellard
    int fd;
765 83f64091 bellard
766 83f64091 bellard
    if (flags || backing_file)
767 83f64091 bellard
        return -ENOTSUP;
768 83f64091 bellard
769 5fafdf24 ths
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
770 83f64091 bellard
              0644);
771 83f64091 bellard
    if (fd < 0)
772 83f64091 bellard
        return -EIO;
773 83f64091 bellard
    ftruncate(fd, total_size * 512);
774 83f64091 bellard
    close(fd);
775 83f64091 bellard
    return 0;
776 83f64091 bellard
}
777 83f64091 bellard
778 83f64091 bellard
static void raw_flush(BlockDriverState *bs)
779 83f64091 bellard
{
780 83f64091 bellard
    BDRVRawState *s = bs->opaque;
781 83f64091 bellard
    fsync(s->fd);
782 83f64091 bellard
}
783 83f64091 bellard
784 83f64091 bellard
BlockDriver bdrv_raw = {
785 83f64091 bellard
    "raw",
786 83f64091 bellard
    sizeof(BDRVRawState),
787 83f64091 bellard
    NULL, /* no probe for protocols */
788 83f64091 bellard
    raw_open,
789 83f64091 bellard
    NULL,
790 83f64091 bellard
    NULL,
791 83f64091 bellard
    raw_close,
792 83f64091 bellard
    raw_create,
793 83f64091 bellard
    raw_flush,
794 3b46e624 ths
795 83f64091 bellard
    .bdrv_aio_read = raw_aio_read,
796 83f64091 bellard
    .bdrv_aio_write = raw_aio_write,
797 83f64091 bellard
    .bdrv_aio_cancel = raw_aio_cancel,
798 ce1a14dc pbrook
    .aiocb_size = sizeof(RawAIOCB),
799 83f64091 bellard
    .protocol_name = "file",
800 83f64091 bellard
    .bdrv_pread = raw_pread,
801 83f64091 bellard
    .bdrv_pwrite = raw_pwrite,
802 83f64091 bellard
    .bdrv_truncate = raw_truncate,
803 83f64091 bellard
    .bdrv_getlength = raw_getlength,
804 83f64091 bellard
};
805 83f64091 bellard
806 19cb3738 bellard
/***********************************************/
807 19cb3738 bellard
/* host device */
808 19cb3738 bellard
809 19cb3738 bellard
#ifdef CONFIG_COCOA
810 19cb3738 bellard
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
811 19cb3738 bellard
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
812 19cb3738 bellard
813 19cb3738 bellard
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
814 19cb3738 bellard
{
815 5fafdf24 ths
    kern_return_t       kernResult;
816 19cb3738 bellard
    mach_port_t     masterPort;
817 19cb3738 bellard
    CFMutableDictionaryRef  classesToMatch;
818 19cb3738 bellard
819 19cb3738 bellard
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
820 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult ) {
821 19cb3738 bellard
        printf( "IOMasterPort returned %d\n", kernResult );
822 19cb3738 bellard
    }
823 3b46e624 ths
824 5fafdf24 ths
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
825 19cb3738 bellard
    if ( classesToMatch == NULL ) {
826 19cb3738 bellard
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
827 19cb3738 bellard
    } else {
828 19cb3738 bellard
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
829 19cb3738 bellard
    }
830 19cb3738 bellard
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
831 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult )
832 19cb3738 bellard
    {
833 19cb3738 bellard
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
834 19cb3738 bellard
    }
835 3b46e624 ths
836 19cb3738 bellard
    return kernResult;
837 19cb3738 bellard
}
838 19cb3738 bellard
839 19cb3738 bellard
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
840 19cb3738 bellard
{
841 19cb3738 bellard
    io_object_t     nextMedia;
842 19cb3738 bellard
    kern_return_t   kernResult = KERN_FAILURE;
843 19cb3738 bellard
    *bsdPath = '\0';
844 19cb3738 bellard
    nextMedia = IOIteratorNext( mediaIterator );
845 19cb3738 bellard
    if ( nextMedia )
846 19cb3738 bellard
    {
847 19cb3738 bellard
        CFTypeRef   bsdPathAsCFString;
848 19cb3738 bellard
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
849 19cb3738 bellard
        if ( bsdPathAsCFString ) {
850 19cb3738 bellard
            size_t devPathLength;
851 19cb3738 bellard
            strcpy( bsdPath, _PATH_DEV );
852 19cb3738 bellard
            strcat( bsdPath, "r" );
853 19cb3738 bellard
            devPathLength = strlen( bsdPath );
854 19cb3738 bellard
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
855 19cb3738 bellard
                kernResult = KERN_SUCCESS;
856 19cb3738 bellard
            }
857 19cb3738 bellard
            CFRelease( bsdPathAsCFString );
858 19cb3738 bellard
        }
859 19cb3738 bellard
        IOObjectRelease( nextMedia );
860 19cb3738 bellard
    }
861 3b46e624 ths
862 19cb3738 bellard
    return kernResult;
863 19cb3738 bellard
}
864 19cb3738 bellard
865 19cb3738 bellard
#endif
866 19cb3738 bellard
867 19cb3738 bellard
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
868 19cb3738 bellard
{
869 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
870 19cb3738 bellard
    int fd, open_flags, ret;
871 19cb3738 bellard
872 19cb3738 bellard
#ifdef CONFIG_COCOA
873 19cb3738 bellard
    if (strstart(filename, "/dev/cdrom", NULL)) {
874 19cb3738 bellard
        kern_return_t kernResult;
875 19cb3738 bellard
        io_iterator_t mediaIterator;
876 19cb3738 bellard
        char bsdPath[ MAXPATHLEN ];
877 19cb3738 bellard
        int fd;
878 5fafdf24 ths
879 19cb3738 bellard
        kernResult = FindEjectableCDMedia( &mediaIterator );
880 19cb3738 bellard
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
881 3b46e624 ths
882 19cb3738 bellard
        if ( bsdPath[ 0 ] != '\0' ) {
883 19cb3738 bellard
            strcat(bsdPath,"s0");
884 19cb3738 bellard
            /* some CDs don't have a partition 0 */
885 19cb3738 bellard
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
886 19cb3738 bellard
            if (fd < 0) {
887 19cb3738 bellard
                bsdPath[strlen(bsdPath)-1] = '1';
888 19cb3738 bellard
            } else {
889 19cb3738 bellard
                close(fd);
890 19cb3738 bellard
            }
891 19cb3738 bellard
            filename = bsdPath;
892 19cb3738 bellard
        }
893 3b46e624 ths
894 19cb3738 bellard
        if ( mediaIterator )
895 19cb3738 bellard
            IOObjectRelease( mediaIterator );
896 19cb3738 bellard
    }
897 19cb3738 bellard
#endif
898 19cb3738 bellard
    open_flags = O_BINARY;
899 19cb3738 bellard
    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
900 19cb3738 bellard
        open_flags |= O_RDWR;
901 19cb3738 bellard
    } else {
902 19cb3738 bellard
        open_flags |= O_RDONLY;
903 19cb3738 bellard
        bs->read_only = 1;
904 19cb3738 bellard
    }
905 33f00271 balrog
#ifdef O_DIRECT
906 33f00271 balrog
    if (flags & BDRV_O_DIRECT)
907 33f00271 balrog
        open_flags |= O_DIRECT;
908 33f00271 balrog
#endif
909 19cb3738 bellard
910 19cb3738 bellard
    s->type = FTYPE_FILE;
911 19cb3738 bellard
#if defined(__linux__)
912 19cb3738 bellard
    if (strstart(filename, "/dev/cd", NULL)) {
913 19cb3738 bellard
        /* open will not fail even if no CD is inserted */
914 19cb3738 bellard
        open_flags |= O_NONBLOCK;
915 19cb3738 bellard
        s->type = FTYPE_CD;
916 19cb3738 bellard
    } else if (strstart(filename, "/dev/fd", NULL)) {
917 19cb3738 bellard
        s->type = FTYPE_FD;
918 6dd2db52 blueswir1
        s->fd_open_flags = open_flags;
919 19cb3738 bellard
        /* open will not fail even if no floppy is inserted */
920 19cb3738 bellard
        open_flags |= O_NONBLOCK;
921 985a03b0 ths
    } else if (strstart(filename, "/dev/sg", NULL)) {
922 985a03b0 ths
        bs->sg = 1;
923 19cb3738 bellard
    }
924 19cb3738 bellard
#endif
925 19cb3738 bellard
    fd = open(filename, open_flags, 0644);
926 19cb3738 bellard
    if (fd < 0) {
927 19cb3738 bellard
        ret = -errno;
928 19cb3738 bellard
        if (ret == -EROFS)
929 19cb3738 bellard
            ret = -EACCES;
930 19cb3738 bellard
        return ret;
931 19cb3738 bellard
    }
932 19cb3738 bellard
    s->fd = fd;
933 19cb3738 bellard
#if defined(__linux__)
934 19cb3738 bellard
    /* close fd so that we can reopen it as needed */
935 19cb3738 bellard
    if (s->type == FTYPE_FD) {
936 19cb3738 bellard
        close(s->fd);
937 19cb3738 bellard
        s->fd = -1;
938 19cb3738 bellard
        s->fd_media_changed = 1;
939 19cb3738 bellard
    }
940 19cb3738 bellard
#endif
941 19cb3738 bellard
    return 0;
942 19cb3738 bellard
}
943 19cb3738 bellard
944 2f726488 ths
#if defined(__linux__) && !defined(QEMU_IMG) && !defined(QEMU_NBD)
945 19cb3738 bellard
946 19cb3738 bellard
/* Note: we do not have a reliable method to detect if the floppy is
947 19cb3738 bellard
   present. The current method is to try to open the floppy at every
948 19cb3738 bellard
   I/O and to keep it opened during a few hundreds of ms. */
949 19cb3738 bellard
static int fd_open(BlockDriverState *bs)
950 19cb3738 bellard
{
951 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
952 19cb3738 bellard
    int last_media_present;
953 19cb3738 bellard
954 19cb3738 bellard
    if (s->type != FTYPE_FD)
955 19cb3738 bellard
        return 0;
956 19cb3738 bellard
    last_media_present = (s->fd >= 0);
957 5fafdf24 ths
    if (s->fd >= 0 &&
958 19cb3738 bellard
        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
959 19cb3738 bellard
        close(s->fd);
960 19cb3738 bellard
        s->fd = -1;
961 19cb3738 bellard
#ifdef DEBUG_FLOPPY
962 19cb3738 bellard
        printf("Floppy closed\n");
963 19cb3738 bellard
#endif
964 19cb3738 bellard
    }
965 19cb3738 bellard
    if (s->fd < 0) {
966 5fafdf24 ths
        if (s->fd_got_error &&
967 19cb3738 bellard
            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
968 19cb3738 bellard
#ifdef DEBUG_FLOPPY
969 19cb3738 bellard
            printf("No floppy (open delayed)\n");
970 19cb3738 bellard
#endif
971 19cb3738 bellard
            return -EIO;
972 19cb3738 bellard
        }
973 6dd2db52 blueswir1
        s->fd = open(bs->filename, s->fd_open_flags);
974 19cb3738 bellard
        if (s->fd < 0) {
975 19cb3738 bellard
            s->fd_error_time = qemu_get_clock(rt_clock);
976 19cb3738 bellard
            s->fd_got_error = 1;
977 19cb3738 bellard
            if (last_media_present)
978 19cb3738 bellard
                s->fd_media_changed = 1;
979 19cb3738 bellard
#ifdef DEBUG_FLOPPY
980 19cb3738 bellard
            printf("No floppy\n");
981 19cb3738 bellard
#endif
982 19cb3738 bellard
            return -EIO;
983 19cb3738 bellard
        }
984 19cb3738 bellard
#ifdef DEBUG_FLOPPY
985 19cb3738 bellard
        printf("Floppy opened\n");
986 19cb3738 bellard
#endif
987 19cb3738 bellard
    }
988 19cb3738 bellard
    if (!last_media_present)
989 19cb3738 bellard
        s->fd_media_changed = 1;
990 19cb3738 bellard
    s->fd_open_time = qemu_get_clock(rt_clock);
991 19cb3738 bellard
    s->fd_got_error = 0;
992 19cb3738 bellard
    return 0;
993 19cb3738 bellard
}
994 19cb3738 bellard
#else
995 19cb3738 bellard
static int fd_open(BlockDriverState *bs)
996 19cb3738 bellard
{
997 19cb3738 bellard
    return 0;
998 19cb3738 bellard
}
999 19cb3738 bellard
#endif
1000 19cb3738 bellard
1001 19cb3738 bellard
#if defined(__linux__)
1002 19cb3738 bellard
1003 19cb3738 bellard
static int raw_is_inserted(BlockDriverState *bs)
1004 19cb3738 bellard
{
1005 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1006 19cb3738 bellard
    int ret;
1007 19cb3738 bellard
1008 19cb3738 bellard
    switch(s->type) {
1009 19cb3738 bellard
    case FTYPE_CD:
1010 19cb3738 bellard
        ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1011 19cb3738 bellard
        if (ret == CDS_DISC_OK)
1012 19cb3738 bellard
            return 1;
1013 19cb3738 bellard
        else
1014 19cb3738 bellard
            return 0;
1015 19cb3738 bellard
        break;
1016 19cb3738 bellard
    case FTYPE_FD:
1017 19cb3738 bellard
        ret = fd_open(bs);
1018 19cb3738 bellard
        return (ret >= 0);
1019 19cb3738 bellard
    default:
1020 19cb3738 bellard
        return 1;
1021 19cb3738 bellard
    }
1022 19cb3738 bellard
}
1023 19cb3738 bellard
1024 19cb3738 bellard
/* currently only used by fdc.c, but a CD version would be good too */
1025 19cb3738 bellard
static int raw_media_changed(BlockDriverState *bs)
1026 19cb3738 bellard
{
1027 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1028 19cb3738 bellard
1029 19cb3738 bellard
    switch(s->type) {
1030 19cb3738 bellard
    case FTYPE_FD:
1031 19cb3738 bellard
        {
1032 19cb3738 bellard
            int ret;
1033 19cb3738 bellard
            /* XXX: we do not have a true media changed indication. It
1034 19cb3738 bellard
               does not work if the floppy is changed without trying
1035 19cb3738 bellard
               to read it */
1036 19cb3738 bellard
            fd_open(bs);
1037 19cb3738 bellard
            ret = s->fd_media_changed;
1038 19cb3738 bellard
            s->fd_media_changed = 0;
1039 19cb3738 bellard
#ifdef DEBUG_FLOPPY
1040 19cb3738 bellard
            printf("Floppy changed=%d\n", ret);
1041 19cb3738 bellard
#endif
1042 19cb3738 bellard
            return ret;
1043 19cb3738 bellard
        }
1044 19cb3738 bellard
    default:
1045 19cb3738 bellard
        return -ENOTSUP;
1046 19cb3738 bellard
    }
1047 19cb3738 bellard
}
1048 19cb3738 bellard
1049 19cb3738 bellard
static int raw_eject(BlockDriverState *bs, int eject_flag)
1050 19cb3738 bellard
{
1051 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1052 19cb3738 bellard
1053 19cb3738 bellard
    switch(s->type) {
1054 19cb3738 bellard
    case FTYPE_CD:
1055 19cb3738 bellard
        if (eject_flag) {
1056 19cb3738 bellard
            if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
1057 19cb3738 bellard
                perror("CDROMEJECT");
1058 19cb3738 bellard
        } else {
1059 19cb3738 bellard
            if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
1060 19cb3738 bellard
                perror("CDROMEJECT");
1061 19cb3738 bellard
        }
1062 19cb3738 bellard
        break;
1063 19cb3738 bellard
    case FTYPE_FD:
1064 19cb3738 bellard
        {
1065 19cb3738 bellard
            int fd;
1066 19cb3738 bellard
            if (s->fd >= 0) {
1067 19cb3738 bellard
                close(s->fd);
1068 19cb3738 bellard
                s->fd = -1;
1069 19cb3738 bellard
            }
1070 6dd2db52 blueswir1
            fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
1071 19cb3738 bellard
            if (fd >= 0) {
1072 19cb3738 bellard
                if (ioctl(fd, FDEJECT, 0) < 0)
1073 19cb3738 bellard
                    perror("FDEJECT");
1074 19cb3738 bellard
                close(fd);
1075 19cb3738 bellard
            }
1076 19cb3738 bellard
        }
1077 19cb3738 bellard
        break;
1078 19cb3738 bellard
    default:
1079 19cb3738 bellard
        return -ENOTSUP;
1080 19cb3738 bellard
    }
1081 19cb3738 bellard
    return 0;
1082 19cb3738 bellard
}
1083 19cb3738 bellard
1084 19cb3738 bellard
static int raw_set_locked(BlockDriverState *bs, int locked)
1085 19cb3738 bellard
{
1086 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
1087 19cb3738 bellard
1088 19cb3738 bellard
    switch(s->type) {
1089 19cb3738 bellard
    case FTYPE_CD:
1090 19cb3738 bellard
        if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
1091 19cb3738 bellard
            /* Note: an error can happen if the distribution automatically
1092 19cb3738 bellard
               mounts the CD-ROM */
1093 19cb3738 bellard
            //        perror("CDROM_LOCKDOOR");
1094 19cb3738 bellard
        }
1095 19cb3738 bellard
        break;
1096 19cb3738 bellard
    default:
1097 19cb3738 bellard
        return -ENOTSUP;
1098 19cb3738 bellard
    }
1099 19cb3738 bellard
    return 0;
1100 19cb3738 bellard
}
1101 19cb3738 bellard
1102 985a03b0 ths
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1103 985a03b0 ths
{
1104 985a03b0 ths
    BDRVRawState *s = bs->opaque;
1105 985a03b0 ths
1106 985a03b0 ths
    return ioctl(s->fd, req, buf);
1107 985a03b0 ths
}
1108 19cb3738 bellard
#else
1109 19cb3738 bellard
1110 19cb3738 bellard
static int raw_is_inserted(BlockDriverState *bs)
1111 19cb3738 bellard
{
1112 19cb3738 bellard
    return 1;
1113 19cb3738 bellard
}
1114 19cb3738 bellard
1115 19cb3738 bellard
static int raw_media_changed(BlockDriverState *bs)
1116 19cb3738 bellard
{
1117 19cb3738 bellard
    return -ENOTSUP;
1118 19cb3738 bellard
}
1119 19cb3738 bellard
1120 19cb3738 bellard
static int raw_eject(BlockDriverState *bs, int eject_flag)
1121 19cb3738 bellard
{
1122 19cb3738 bellard
    return -ENOTSUP;
1123 19cb3738 bellard
}
1124 19cb3738 bellard
1125 19cb3738 bellard
static int raw_set_locked(BlockDriverState *bs, int locked)
1126 19cb3738 bellard
{
1127 19cb3738 bellard
    return -ENOTSUP;
1128 19cb3738 bellard
}
1129 19cb3738 bellard
1130 985a03b0 ths
static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1131 985a03b0 ths
{
1132 985a03b0 ths
    return -ENOTSUP;
1133 985a03b0 ths
}
1134 19cb3738 bellard
#endif /* !linux */
1135 19cb3738 bellard
1136 19cb3738 bellard
BlockDriver bdrv_host_device = {
1137 19cb3738 bellard
    "host_device",
1138 19cb3738 bellard
    sizeof(BDRVRawState),
1139 19cb3738 bellard
    NULL, /* no probe for protocols */
1140 19cb3738 bellard
    hdev_open,
1141 19cb3738 bellard
    NULL,
1142 19cb3738 bellard
    NULL,
1143 19cb3738 bellard
    raw_close,
1144 19cb3738 bellard
    NULL,
1145 19cb3738 bellard
    raw_flush,
1146 3b46e624 ths
1147 19cb3738 bellard
    .bdrv_aio_read = raw_aio_read,
1148 19cb3738 bellard
    .bdrv_aio_write = raw_aio_write,
1149 19cb3738 bellard
    .bdrv_aio_cancel = raw_aio_cancel,
1150 19cb3738 bellard
    .aiocb_size = sizeof(RawAIOCB),
1151 19cb3738 bellard
    .bdrv_pread = raw_pread,
1152 19cb3738 bellard
    .bdrv_pwrite = raw_pwrite,
1153 19cb3738 bellard
    .bdrv_getlength = raw_getlength,
1154 19cb3738 bellard
1155 19cb3738 bellard
    /* removable device support */
1156 19cb3738 bellard
    .bdrv_is_inserted = raw_is_inserted,
1157 19cb3738 bellard
    .bdrv_media_changed = raw_media_changed,
1158 19cb3738 bellard
    .bdrv_eject = raw_eject,
1159 19cb3738 bellard
    .bdrv_set_locked = raw_set_locked,
1160 985a03b0 ths
    /* generic scsi device */
1161 985a03b0 ths
    .bdrv_ioctl = raw_ioctl,
1162 19cb3738 bellard
};