Statistics
| Branch: | Revision:

root / block.c @ 42fc925e

History | View | Annotate | Download (33.8 kB)

1 fc01f7e7 bellard
/*
2 fc01f7e7 bellard
 * QEMU System Emulator block driver
3 fc01f7e7 bellard
 * 
4 fc01f7e7 bellard
 * Copyright (c) 2003 Fabrice Bellard
5 fc01f7e7 bellard
 * 
6 fc01f7e7 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 fc01f7e7 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 fc01f7e7 bellard
 * in the Software without restriction, including without limitation the rights
9 fc01f7e7 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 fc01f7e7 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 fc01f7e7 bellard
 * furnished to do so, subject to the following conditions:
12 fc01f7e7 bellard
 *
13 fc01f7e7 bellard
 * The above copyright notice and this permission notice shall be included in
14 fc01f7e7 bellard
 * all copies or substantial portions of the Software.
15 fc01f7e7 bellard
 *
16 fc01f7e7 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 fc01f7e7 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 fc01f7e7 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 fc01f7e7 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 fc01f7e7 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 fc01f7e7 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 fc01f7e7 bellard
 * THE SOFTWARE.
23 fc01f7e7 bellard
 */
24 fc01f7e7 bellard
#include "vl.h"
25 ea2384d3 bellard
#include "block_int.h"
26 fc01f7e7 bellard
27 7674e7bf bellard
#ifdef _BSD
28 7674e7bf bellard
#include <sys/types.h>
29 7674e7bf bellard
#include <sys/stat.h>
30 7674e7bf bellard
#include <sys/ioctl.h>
31 7674e7bf bellard
#include <sys/queue.h>
32 7674e7bf bellard
#include <sys/disk.h>
33 7674e7bf bellard
#endif
34 7674e7bf bellard
35 83f64091 bellard
#define SECTOR_BITS 9
36 83f64091 bellard
#define SECTOR_SIZE (1 << SECTOR_BITS)
37 83f64091 bellard
38 90765429 bellard
typedef struct BlockDriverAIOCBSync {
39 90765429 bellard
    BlockDriverAIOCB common;
40 90765429 bellard
    QEMUBH *bh;
41 90765429 bellard
    int ret;
42 90765429 bellard
} BlockDriverAIOCBSync;
43 90765429 bellard
44 ce1a14dc pbrook
static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
45 ce1a14dc pbrook
        int64_t sector_num, uint8_t *buf, int nb_sectors,
46 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque);
47 ce1a14dc pbrook
static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
48 ce1a14dc pbrook
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
49 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque);
50 83f64091 bellard
static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
51 83f64091 bellard
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
52 83f64091 bellard
                        uint8_t *buf, int nb_sectors);
53 83f64091 bellard
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
54 83f64091 bellard
                         const uint8_t *buf, int nb_sectors);
55 ec530c81 bellard
56 b338082b bellard
static BlockDriverState *bdrv_first;
57 ea2384d3 bellard
static BlockDriver *first_drv;
58 ea2384d3 bellard
59 83f64091 bellard
#ifdef _WIN32
60 83f64091 bellard
#define PATH_SEP '\\'
61 83f64091 bellard
#else
62 83f64091 bellard
#define PATH_SEP '/'
63 83f64091 bellard
#endif
64 3b0d4f61 bellard
65 83f64091 bellard
int path_is_absolute(const char *path)
66 3b0d4f61 bellard
{
67 83f64091 bellard
    const char *p;
68 83f64091 bellard
    p = strchr(path, ':');
69 83f64091 bellard
    if (p)
70 83f64091 bellard
        p++;
71 83f64091 bellard
    else
72 83f64091 bellard
        p = path;
73 83f64091 bellard
    return (*p == PATH_SEP);
74 3b0d4f61 bellard
}
75 3b0d4f61 bellard
76 83f64091 bellard
/* if filename is absolute, just copy it to dest. Otherwise, build a
77 83f64091 bellard
   path to it by considering it is relative to base_path. URL are
78 83f64091 bellard
   supported. */
79 83f64091 bellard
void path_combine(char *dest, int dest_size,
80 83f64091 bellard
                  const char *base_path,
81 83f64091 bellard
                  const char *filename)
82 3b0d4f61 bellard
{
83 83f64091 bellard
    const char *p, *p1;
84 83f64091 bellard
    int len;
85 83f64091 bellard
86 83f64091 bellard
    if (dest_size <= 0)
87 83f64091 bellard
        return;
88 83f64091 bellard
    if (path_is_absolute(filename)) {
89 83f64091 bellard
        pstrcpy(dest, dest_size, filename);
90 83f64091 bellard
    } else {
91 83f64091 bellard
        p = strchr(base_path, ':');
92 83f64091 bellard
        if (p)
93 83f64091 bellard
            p++;
94 83f64091 bellard
        else
95 83f64091 bellard
            p = base_path;
96 83f64091 bellard
        p1 = strrchr(base_path, PATH_SEP);
97 83f64091 bellard
        if (p1)
98 83f64091 bellard
            p1++;
99 83f64091 bellard
        else
100 83f64091 bellard
            p1 = base_path;
101 83f64091 bellard
        if (p1 > p)
102 83f64091 bellard
            p = p1;
103 83f64091 bellard
        len = p - base_path;
104 83f64091 bellard
        if (len > dest_size - 1)
105 83f64091 bellard
            len = dest_size - 1;
106 83f64091 bellard
        memcpy(dest, base_path, len);
107 83f64091 bellard
        dest[len] = '\0';
108 83f64091 bellard
        pstrcat(dest, dest_size, filename);
109 3b0d4f61 bellard
    }
110 3b0d4f61 bellard
}
111 3b0d4f61 bellard
112 3b0d4f61 bellard
113 ea2384d3 bellard
void bdrv_register(BlockDriver *bdrv)
114 ea2384d3 bellard
{
115 ce1a14dc pbrook
    if (!bdrv->bdrv_aio_read) {
116 83f64091 bellard
        /* add AIO emulation layer */
117 83f64091 bellard
        bdrv->bdrv_aio_read = bdrv_aio_read_em;
118 83f64091 bellard
        bdrv->bdrv_aio_write = bdrv_aio_write_em;
119 83f64091 bellard
        bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
120 90765429 bellard
        bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
121 83f64091 bellard
    } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
122 83f64091 bellard
        /* add synchronous IO emulation layer */
123 83f64091 bellard
        bdrv->bdrv_read = bdrv_read_em;
124 83f64091 bellard
        bdrv->bdrv_write = bdrv_write_em;
125 83f64091 bellard
    }
126 ea2384d3 bellard
    bdrv->next = first_drv;
127 ea2384d3 bellard
    first_drv = bdrv;
128 ea2384d3 bellard
}
129 b338082b bellard
130 b338082b bellard
/* create a new block device (by default it is empty) */
131 b338082b bellard
BlockDriverState *bdrv_new(const char *device_name)
132 b338082b bellard
{
133 b338082b bellard
    BlockDriverState **pbs, *bs;
134 b338082b bellard
135 b338082b bellard
    bs = qemu_mallocz(sizeof(BlockDriverState));
136 b338082b bellard
    if(!bs)
137 b338082b bellard
        return NULL;
138 b338082b bellard
    pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
139 ea2384d3 bellard
    if (device_name[0] != '\0') {
140 ea2384d3 bellard
        /* insert at the end */
141 ea2384d3 bellard
        pbs = &bdrv_first;
142 ea2384d3 bellard
        while (*pbs != NULL)
143 ea2384d3 bellard
            pbs = &(*pbs)->next;
144 ea2384d3 bellard
        *pbs = bs;
145 ea2384d3 bellard
    }
146 b338082b bellard
    return bs;
147 b338082b bellard
}
148 b338082b bellard
149 ea2384d3 bellard
BlockDriver *bdrv_find_format(const char *format_name)
150 ea2384d3 bellard
{
151 ea2384d3 bellard
    BlockDriver *drv1;
152 ea2384d3 bellard
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
153 ea2384d3 bellard
        if (!strcmp(drv1->format_name, format_name))
154 ea2384d3 bellard
            return drv1;
155 ea2384d3 bellard
    }
156 ea2384d3 bellard
    return NULL;
157 ea2384d3 bellard
}
158 ea2384d3 bellard
159 ea2384d3 bellard
int bdrv_create(BlockDriver *drv, 
160 ea2384d3 bellard
                const char *filename, int64_t size_in_sectors,
161 ea2384d3 bellard
                const char *backing_file, int flags)
162 ea2384d3 bellard
{
163 ea2384d3 bellard
    if (!drv->bdrv_create)
164 ea2384d3 bellard
        return -ENOTSUP;
165 ea2384d3 bellard
    return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
166 ea2384d3 bellard
}
167 ea2384d3 bellard
168 d5249393 bellard
#ifdef _WIN32
169 95389c86 bellard
void get_tmp_filename(char *filename, int size)
170 d5249393 bellard
{
171 83f64091 bellard
    tmpnam(filename);
172 d5249393 bellard
}
173 d5249393 bellard
#else
174 95389c86 bellard
void get_tmp_filename(char *filename, int size)
175 fc01f7e7 bellard
{
176 67b915a5 bellard
    int fd;
177 d5249393 bellard
    /* XXX: race condition possible */
178 ea2384d3 bellard
    pstrcpy(filename, size, "/tmp/vl.XXXXXX");
179 ea2384d3 bellard
    fd = mkstemp(filename);
180 ea2384d3 bellard
    close(fd);
181 ea2384d3 bellard
}
182 d5249393 bellard
#endif
183 fc01f7e7 bellard
184 19cb3738 bellard
#ifdef _WIN32
185 f45512fe bellard
static int is_windows_drive_prefix(const char *filename)
186 f45512fe bellard
{
187 f45512fe bellard
    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
188 f45512fe bellard
             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
189 f45512fe bellard
            filename[1] == ':');
190 f45512fe bellard
}
191 f45512fe bellard
    
192 19cb3738 bellard
static int is_windows_drive(const char *filename)
193 19cb3738 bellard
{
194 f45512fe bellard
    if (is_windows_drive_prefix(filename) && 
195 f45512fe bellard
        filename[2] == '\0')
196 19cb3738 bellard
        return 1;
197 19cb3738 bellard
    if (strstart(filename, "\\\\.\\", NULL) ||
198 19cb3738 bellard
        strstart(filename, "//./", NULL))
199 19cb3738 bellard
        return 1;
200 19cb3738 bellard
    return 0;
201 19cb3738 bellard
}
202 19cb3738 bellard
#endif
203 19cb3738 bellard
204 83f64091 bellard
static BlockDriver *find_protocol(const char *filename)
205 83f64091 bellard
{
206 83f64091 bellard
    BlockDriver *drv1;
207 83f64091 bellard
    char protocol[128];
208 83f64091 bellard
    int len;
209 83f64091 bellard
    const char *p;
210 19cb3738 bellard
211 19cb3738 bellard
#ifdef _WIN32
212 f45512fe bellard
    if (is_windows_drive(filename) ||
213 f45512fe bellard
        is_windows_drive_prefix(filename))
214 19cb3738 bellard
        return &bdrv_raw;
215 19cb3738 bellard
#endif
216 83f64091 bellard
    p = strchr(filename, ':');
217 83f64091 bellard
    if (!p)
218 83f64091 bellard
        return &bdrv_raw;
219 83f64091 bellard
    len = p - filename;
220 83f64091 bellard
    if (len > sizeof(protocol) - 1)
221 83f64091 bellard
        len = sizeof(protocol) - 1;
222 83f64091 bellard
    memcpy(protocol, filename, len);
223 83f64091 bellard
    protocol[len] = '\0';
224 83f64091 bellard
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
225 83f64091 bellard
        if (drv1->protocol_name && 
226 83f64091 bellard
            !strcmp(drv1->protocol_name, protocol))
227 83f64091 bellard
            return drv1;
228 83f64091 bellard
    }
229 83f64091 bellard
    return NULL;
230 83f64091 bellard
}
231 83f64091 bellard
232 7674e7bf bellard
/* XXX: force raw format if block or character device ? It would
233 7674e7bf bellard
   simplify the BSD case */
234 ea2384d3 bellard
static BlockDriver *find_image_format(const char *filename)
235 ea2384d3 bellard
{
236 83f64091 bellard
    int ret, score, score_max;
237 ea2384d3 bellard
    BlockDriver *drv1, *drv;
238 83f64091 bellard
    uint8_t buf[2048];
239 83f64091 bellard
    BlockDriverState *bs;
240 ea2384d3 bellard
    
241 19cb3738 bellard
    /* detect host devices. By convention, /dev/cdrom[N] is always
242 19cb3738 bellard
       recognized as a host CDROM */
243 19cb3738 bellard
    if (strstart(filename, "/dev/cdrom", NULL))
244 19cb3738 bellard
        return &bdrv_host_device;
245 19cb3738 bellard
#ifdef _WIN32
246 19cb3738 bellard
    if (is_windows_drive(filename))
247 19cb3738 bellard
        return &bdrv_host_device;
248 19cb3738 bellard
#else
249 19cb3738 bellard
    {
250 19cb3738 bellard
        struct stat st;
251 19cb3738 bellard
        if (stat(filename, &st) >= 0 && 
252 19cb3738 bellard
            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
253 19cb3738 bellard
            return &bdrv_host_device;
254 19cb3738 bellard
        }
255 19cb3738 bellard
    }
256 19cb3738 bellard
#endif
257 19cb3738 bellard
    
258 83f64091 bellard
    drv = find_protocol(filename);
259 19cb3738 bellard
    /* no need to test disk image formats for vvfat */
260 83f64091 bellard
    if (drv == &bdrv_vvfat)
261 83f64091 bellard
        return drv;
262 19cb3738 bellard
263 83f64091 bellard
    ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
264 83f64091 bellard
    if (ret < 0)
265 83f64091 bellard
        return NULL;
266 83f64091 bellard
    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
267 83f64091 bellard
    bdrv_delete(bs);
268 83f64091 bellard
    if (ret < 0) {
269 83f64091 bellard
        return NULL;
270 83f64091 bellard
    }
271 83f64091 bellard
272 ea2384d3 bellard
    score_max = 0;
273 ea2384d3 bellard
    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
274 83f64091 bellard
        if (drv1->bdrv_probe) {
275 83f64091 bellard
            score = drv1->bdrv_probe(buf, ret, filename);
276 83f64091 bellard
            if (score > score_max) {
277 83f64091 bellard
                score_max = score;
278 83f64091 bellard
                drv = drv1;
279 83f64091 bellard
            }
280 0849bf08 bellard
        }
281 fc01f7e7 bellard
    }
282 ea2384d3 bellard
    return drv;
283 ea2384d3 bellard
}
284 ea2384d3 bellard
285 83f64091 bellard
int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
286 ea2384d3 bellard
{
287 83f64091 bellard
    BlockDriverState *bs;
288 83f64091 bellard
    int ret;
289 83f64091 bellard
290 83f64091 bellard
    bs = bdrv_new("");
291 83f64091 bellard
    if (!bs)
292 83f64091 bellard
        return -ENOMEM;
293 83f64091 bellard
    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
294 83f64091 bellard
    if (ret < 0) {
295 83f64091 bellard
        bdrv_delete(bs);
296 83f64091 bellard
        return ret;
297 3b0d4f61 bellard
    }
298 83f64091 bellard
    *pbs = bs;
299 83f64091 bellard
    return 0;
300 83f64091 bellard
}
301 83f64091 bellard
302 83f64091 bellard
int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
303 83f64091 bellard
{
304 83f64091 bellard
    return bdrv_open2(bs, filename, flags, NULL);
305 ea2384d3 bellard
}
306 ea2384d3 bellard
307 83f64091 bellard
int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
308 ea2384d3 bellard
               BlockDriver *drv)
309 ea2384d3 bellard
{
310 83f64091 bellard
    int ret, open_flags;
311 ea2384d3 bellard
    char tmp_filename[1024];
312 83f64091 bellard
    char backing_filename[1024];
313 ea2384d3 bellard
    
314 ea2384d3 bellard
    bs->read_only = 0;
315 ea2384d3 bellard
    bs->is_temporary = 0;
316 ea2384d3 bellard
    bs->encrypted = 0;
317 712e7874 bellard
318 83f64091 bellard
    if (flags & BDRV_O_SNAPSHOT) {
319 ea2384d3 bellard
        BlockDriverState *bs1;
320 ea2384d3 bellard
        int64_t total_size;
321 ea2384d3 bellard
        
322 ea2384d3 bellard
        /* if snapshot, we create a temporary backing file and open it
323 ea2384d3 bellard
           instead of opening 'filename' directly */
324 33e3963e bellard
325 ea2384d3 bellard
        /* if there is a backing file, use it */
326 ea2384d3 bellard
        bs1 = bdrv_new("");
327 ea2384d3 bellard
        if (!bs1) {
328 83f64091 bellard
            return -ENOMEM;
329 ea2384d3 bellard
        }
330 ea2384d3 bellard
        if (bdrv_open(bs1, filename, 0) < 0) {
331 ea2384d3 bellard
            bdrv_delete(bs1);
332 ea2384d3 bellard
            return -1;
333 ea2384d3 bellard
        }
334 83f64091 bellard
        total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
335 ea2384d3 bellard
        bdrv_delete(bs1);
336 ea2384d3 bellard
        
337 ea2384d3 bellard
        get_tmp_filename(tmp_filename, sizeof(tmp_filename));
338 a817d936 bellard
        realpath(filename, backing_filename);
339 d15a771d bellard
        if (bdrv_create(&bdrv_qcow2, tmp_filename, 
340 a817d936 bellard
                        total_size, backing_filename, 0) < 0) {
341 ea2384d3 bellard
            return -1;
342 ea2384d3 bellard
        }
343 ea2384d3 bellard
        filename = tmp_filename;
344 ea2384d3 bellard
        bs->is_temporary = 1;
345 ea2384d3 bellard
    }
346 712e7874 bellard
347 ea2384d3 bellard
    pstrcpy(bs->filename, sizeof(bs->filename), filename);
348 83f64091 bellard
    if (flags & BDRV_O_FILE) {
349 83f64091 bellard
        drv = find_protocol(filename);
350 ea2384d3 bellard
        if (!drv)
351 83f64091 bellard
            return -ENOENT;
352 83f64091 bellard
    } else {
353 83f64091 bellard
        if (!drv) {
354 83f64091 bellard
            drv = find_image_format(filename);
355 83f64091 bellard
            if (!drv)
356 83f64091 bellard
                return -1;
357 83f64091 bellard
        }
358 ea2384d3 bellard
    }
359 ea2384d3 bellard
    bs->drv = drv;
360 ea2384d3 bellard
    bs->opaque = qemu_mallocz(drv->instance_size);
361 ea2384d3 bellard
    if (bs->opaque == NULL && drv->instance_size > 0)
362 ea2384d3 bellard
        return -1;
363 83f64091 bellard
    /* Note: for compatibility, we open disk image files as RDWR, and
364 83f64091 bellard
       RDONLY as fallback */
365 83f64091 bellard
    if (!(flags & BDRV_O_FILE))
366 83f64091 bellard
        open_flags = BDRV_O_RDWR;
367 83f64091 bellard
    else
368 83f64091 bellard
        open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
369 83f64091 bellard
    ret = drv->bdrv_open(bs, filename, open_flags);
370 83f64091 bellard
    if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
371 83f64091 bellard
        ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
372 83f64091 bellard
        bs->read_only = 1;
373 83f64091 bellard
    }
374 ea2384d3 bellard
    if (ret < 0) {
375 ea2384d3 bellard
        qemu_free(bs->opaque);
376 6b21b973 bellard
        bs->opaque = NULL;
377 6b21b973 bellard
        bs->drv = NULL;
378 83f64091 bellard
        return ret;
379 33e3963e bellard
    }
380 d15a771d bellard
    if (drv->bdrv_getlength) {
381 d15a771d bellard
        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
382 d15a771d bellard
    }
383 67b915a5 bellard
#ifndef _WIN32
384 ea2384d3 bellard
    if (bs->is_temporary) {
385 ea2384d3 bellard
        unlink(filename);
386 ea2384d3 bellard
    }
387 ea2384d3 bellard
#endif
388 83f64091 bellard
    if (bs->backing_file[0] != '\0') {
389 ea2384d3 bellard
        /* if there is a backing file, use it */
390 ea2384d3 bellard
        bs->backing_hd = bdrv_new("");
391 ea2384d3 bellard
        if (!bs->backing_hd) {
392 ea2384d3 bellard
        fail:
393 ea2384d3 bellard
            bdrv_close(bs);
394 6b21b973 bellard
            return -ENOMEM;
395 33e3963e bellard
        }
396 83f64091 bellard
        path_combine(backing_filename, sizeof(backing_filename),
397 83f64091 bellard
                     filename, bs->backing_file);
398 83f64091 bellard
        if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
399 33e3963e bellard
            goto fail;
400 33e3963e bellard
    }
401 33e3963e bellard
402 b338082b bellard
    /* call the change callback */
403 19cb3738 bellard
    bs->media_changed = 1;
404 b338082b bellard
    if (bs->change_cb)
405 b338082b bellard
        bs->change_cb(bs->change_opaque);
406 b338082b bellard
407 b338082b bellard
    return 0;
408 fc01f7e7 bellard
}
409 fc01f7e7 bellard
410 fc01f7e7 bellard
void bdrv_close(BlockDriverState *bs)
411 fc01f7e7 bellard
{
412 19cb3738 bellard
    if (bs->drv) {
413 ea2384d3 bellard
        if (bs->backing_hd)
414 ea2384d3 bellard
            bdrv_delete(bs->backing_hd);
415 ea2384d3 bellard
        bs->drv->bdrv_close(bs);
416 ea2384d3 bellard
        qemu_free(bs->opaque);
417 ea2384d3 bellard
#ifdef _WIN32
418 ea2384d3 bellard
        if (bs->is_temporary) {
419 ea2384d3 bellard
            unlink(bs->filename);
420 ea2384d3 bellard
        }
421 67b915a5 bellard
#endif
422 ea2384d3 bellard
        bs->opaque = NULL;
423 ea2384d3 bellard
        bs->drv = NULL;
424 b338082b bellard
425 b338082b bellard
        /* call the change callback */
426 19cb3738 bellard
        bs->media_changed = 1;
427 b338082b bellard
        if (bs->change_cb)
428 b338082b bellard
            bs->change_cb(bs->change_opaque);
429 b338082b bellard
    }
430 b338082b bellard
}
431 b338082b bellard
432 b338082b bellard
void bdrv_delete(BlockDriverState *bs)
433 b338082b bellard
{
434 ea2384d3 bellard
    /* XXX: remove the driver list */
435 b338082b bellard
    bdrv_close(bs);
436 b338082b bellard
    qemu_free(bs);
437 fc01f7e7 bellard
}
438 fc01f7e7 bellard
439 33e3963e bellard
/* commit COW file into the raw image */
440 33e3963e bellard
int bdrv_commit(BlockDriverState *bs)
441 33e3963e bellard
{
442 19cb3738 bellard
    BlockDriver *drv = bs->drv;
443 83f64091 bellard
    int64_t i, total_sectors;
444 ea2384d3 bellard
    int n, j;
445 ea2384d3 bellard
    unsigned char sector[512];
446 33e3963e bellard
447 19cb3738 bellard
    if (!drv)
448 19cb3738 bellard
        return -ENOMEDIUM;
449 33e3963e bellard
450 33e3963e bellard
    if (bs->read_only) {
451 ea2384d3 bellard
        return -EACCES;
452 33e3963e bellard
    }
453 33e3963e bellard
454 ea2384d3 bellard
    if (!bs->backing_hd) {
455 ea2384d3 bellard
        return -ENOTSUP;
456 ea2384d3 bellard
    }
457 33e3963e bellard
458 83f64091 bellard
    total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
459 83f64091 bellard
    for (i = 0; i < total_sectors;) {
460 19cb3738 bellard
        if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
461 ea2384d3 bellard
            for(j = 0; j < n; j++) {
462 ea2384d3 bellard
                if (bdrv_read(bs, i, sector, 1) != 0) {
463 ea2384d3 bellard
                    return -EIO;
464 ea2384d3 bellard
                }
465 ea2384d3 bellard
466 ea2384d3 bellard
                if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
467 ea2384d3 bellard
                    return -EIO;
468 ea2384d3 bellard
                }
469 ea2384d3 bellard
                i++;
470 33e3963e bellard
            }
471 ea2384d3 bellard
        } else {
472 ea2384d3 bellard
            i += n;
473 ea2384d3 bellard
        }
474 33e3963e bellard
    }
475 95389c86 bellard
476 19cb3738 bellard
    if (drv->bdrv_make_empty)
477 19cb3738 bellard
        return drv->bdrv_make_empty(bs);
478 95389c86 bellard
479 33e3963e bellard
    return 0;
480 33e3963e bellard
}
481 33e3963e bellard
482 19cb3738 bellard
/* return < 0 if error. See bdrv_write() for the return codes */
483 fc01f7e7 bellard
int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
484 fc01f7e7 bellard
              uint8_t *buf, int nb_sectors)
485 fc01f7e7 bellard
{
486 ea2384d3 bellard
    BlockDriver *drv = bs->drv;
487 ea2384d3 bellard
488 19cb3738 bellard
    if (!drv)
489 19cb3738 bellard
        return -ENOMEDIUM;
490 b338082b bellard
491 83f64091 bellard
    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
492 cf98951b bellard
            memcpy(buf, bs->boot_sector_data, 512);
493 83f64091 bellard
        sector_num++;
494 83f64091 bellard
        nb_sectors--;
495 83f64091 bellard
        buf += 512;
496 83f64091 bellard
        if (nb_sectors == 0)
497 83f64091 bellard
            return 0;
498 83f64091 bellard
    }
499 83f64091 bellard
    if (drv->bdrv_pread) {
500 83f64091 bellard
        int ret, len;
501 83f64091 bellard
        len = nb_sectors * 512;
502 83f64091 bellard
        ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
503 83f64091 bellard
        if (ret < 0)
504 83f64091 bellard
            return ret;
505 83f64091 bellard
        else if (ret != len)
506 19cb3738 bellard
            return -EINVAL;
507 83f64091 bellard
        else
508 83f64091 bellard
            return 0;
509 83f64091 bellard
    } else {
510 83f64091 bellard
        return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
511 33e3963e bellard
    }
512 fc01f7e7 bellard
}
513 fc01f7e7 bellard
514 19cb3738 bellard
/* Return < 0 if error. Important errors are: 
515 19cb3738 bellard
  -EIO         generic I/O error (may happen for all errors)
516 19cb3738 bellard
  -ENOMEDIUM   No media inserted.
517 19cb3738 bellard
  -EINVAL      Invalid sector number or nb_sectors
518 19cb3738 bellard
  -EACCES      Trying to write a read-only device
519 19cb3738 bellard
*/
520 fc01f7e7 bellard
int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
521 fc01f7e7 bellard
               const uint8_t *buf, int nb_sectors)
522 fc01f7e7 bellard
{
523 83f64091 bellard
    BlockDriver *drv = bs->drv;
524 19cb3738 bellard
    if (!bs->drv)
525 19cb3738 bellard
        return -ENOMEDIUM;
526 0849bf08 bellard
    if (bs->read_only)
527 19cb3738 bellard
        return -EACCES;
528 79639d42 bellard
    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
529 79639d42 bellard
        memcpy(bs->boot_sector_data, buf, 512);   
530 79639d42 bellard
    }
531 83f64091 bellard
    if (drv->bdrv_pwrite) {
532 83f64091 bellard
        int ret, len;
533 83f64091 bellard
        len = nb_sectors * 512;
534 83f64091 bellard
        ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
535 83f64091 bellard
        if (ret < 0)
536 83f64091 bellard
            return ret;
537 83f64091 bellard
        else if (ret != len)
538 83f64091 bellard
            return -EIO;
539 83f64091 bellard
        else
540 83f64091 bellard
            return 0;
541 83f64091 bellard
    } else {
542 83f64091 bellard
        return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
543 83f64091 bellard
    }
544 83f64091 bellard
}
545 83f64091 bellard
546 83f64091 bellard
static int bdrv_pread_em(BlockDriverState *bs, int64_t offset, 
547 faea38e7 bellard
                         uint8_t *buf, int count1)
548 83f64091 bellard
{
549 83f64091 bellard
    uint8_t tmp_buf[SECTOR_SIZE];
550 83f64091 bellard
    int len, nb_sectors, count;
551 83f64091 bellard
    int64_t sector_num;
552 83f64091 bellard
553 83f64091 bellard
    count = count1;
554 83f64091 bellard
    /* first read to align to sector start */
555 83f64091 bellard
    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
556 83f64091 bellard
    if (len > count)
557 83f64091 bellard
        len = count;
558 83f64091 bellard
    sector_num = offset >> SECTOR_BITS;
559 83f64091 bellard
    if (len > 0) {
560 83f64091 bellard
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
561 83f64091 bellard
            return -EIO;
562 83f64091 bellard
        memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
563 83f64091 bellard
        count -= len;
564 83f64091 bellard
        if (count == 0)
565 83f64091 bellard
            return count1;
566 83f64091 bellard
        sector_num++;
567 83f64091 bellard
        buf += len;
568 83f64091 bellard
    }
569 83f64091 bellard
570 83f64091 bellard
    /* read the sectors "in place" */
571 83f64091 bellard
    nb_sectors = count >> SECTOR_BITS;
572 83f64091 bellard
    if (nb_sectors > 0) {
573 83f64091 bellard
        if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
574 83f64091 bellard
            return -EIO;
575 83f64091 bellard
        sector_num += nb_sectors;
576 83f64091 bellard
        len = nb_sectors << SECTOR_BITS;
577 83f64091 bellard
        buf += len;
578 83f64091 bellard
        count -= len;
579 83f64091 bellard
    }
580 83f64091 bellard
581 83f64091 bellard
    /* add data from the last sector */
582 83f64091 bellard
    if (count > 0) {
583 83f64091 bellard
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
584 83f64091 bellard
            return -EIO;
585 83f64091 bellard
        memcpy(buf, tmp_buf, count);
586 83f64091 bellard
    }
587 83f64091 bellard
    return count1;
588 83f64091 bellard
}
589 83f64091 bellard
590 83f64091 bellard
static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset, 
591 faea38e7 bellard
                          const uint8_t *buf, int count1)
592 83f64091 bellard
{
593 83f64091 bellard
    uint8_t tmp_buf[SECTOR_SIZE];
594 83f64091 bellard
    int len, nb_sectors, count;
595 83f64091 bellard
    int64_t sector_num;
596 83f64091 bellard
597 83f64091 bellard
    count = count1;
598 83f64091 bellard
    /* first write to align to sector start */
599 83f64091 bellard
    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
600 83f64091 bellard
    if (len > count)
601 83f64091 bellard
        len = count;
602 83f64091 bellard
    sector_num = offset >> SECTOR_BITS;
603 83f64091 bellard
    if (len > 0) {
604 83f64091 bellard
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
605 83f64091 bellard
            return -EIO;
606 83f64091 bellard
        memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
607 83f64091 bellard
        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
608 83f64091 bellard
            return -EIO;
609 83f64091 bellard
        count -= len;
610 83f64091 bellard
        if (count == 0)
611 83f64091 bellard
            return count1;
612 83f64091 bellard
        sector_num++;
613 83f64091 bellard
        buf += len;
614 83f64091 bellard
    }
615 83f64091 bellard
616 83f64091 bellard
    /* write the sectors "in place" */
617 83f64091 bellard
    nb_sectors = count >> SECTOR_BITS;
618 83f64091 bellard
    if (nb_sectors > 0) {
619 83f64091 bellard
        if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
620 83f64091 bellard
            return -EIO;
621 83f64091 bellard
        sector_num += nb_sectors;
622 83f64091 bellard
        len = nb_sectors << SECTOR_BITS;
623 83f64091 bellard
        buf += len;
624 83f64091 bellard
        count -= len;
625 83f64091 bellard
    }
626 83f64091 bellard
627 83f64091 bellard
    /* add data from the last sector */
628 83f64091 bellard
    if (count > 0) {
629 83f64091 bellard
        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
630 83f64091 bellard
            return -EIO;
631 83f64091 bellard
        memcpy(tmp_buf, buf, count);
632 83f64091 bellard
        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
633 83f64091 bellard
            return -EIO;
634 83f64091 bellard
    }
635 83f64091 bellard
    return count1;
636 83f64091 bellard
}
637 83f64091 bellard
638 83f64091 bellard
/**
639 83f64091 bellard
 * Read with byte offsets (needed only for file protocols) 
640 83f64091 bellard
 */
641 83f64091 bellard
int bdrv_pread(BlockDriverState *bs, int64_t offset, 
642 83f64091 bellard
               void *buf1, int count1)
643 83f64091 bellard
{
644 83f64091 bellard
    BlockDriver *drv = bs->drv;
645 83f64091 bellard
646 83f64091 bellard
    if (!drv)
647 19cb3738 bellard
        return -ENOMEDIUM;
648 83f64091 bellard
    if (!drv->bdrv_pread)
649 faea38e7 bellard
        return bdrv_pread_em(bs, offset, buf1, count1);
650 83f64091 bellard
    return drv->bdrv_pread(bs, offset, buf1, count1);
651 83f64091 bellard
}
652 83f64091 bellard
653 83f64091 bellard
/** 
654 83f64091 bellard
 * Write with byte offsets (needed only for file protocols) 
655 83f64091 bellard
 */
656 83f64091 bellard
int bdrv_pwrite(BlockDriverState *bs, int64_t offset, 
657 83f64091 bellard
                const void *buf1, int count1)
658 83f64091 bellard
{
659 83f64091 bellard
    BlockDriver *drv = bs->drv;
660 83f64091 bellard
661 83f64091 bellard
    if (!drv)
662 19cb3738 bellard
        return -ENOMEDIUM;
663 83f64091 bellard
    if (!drv->bdrv_pwrite)
664 faea38e7 bellard
        return bdrv_pwrite_em(bs, offset, buf1, count1);
665 83f64091 bellard
    return drv->bdrv_pwrite(bs, offset, buf1, count1);
666 83f64091 bellard
}
667 83f64091 bellard
668 83f64091 bellard
/**
669 83f64091 bellard
 * Truncate file to 'offset' bytes (needed only for file protocols)
670 83f64091 bellard
 */
671 83f64091 bellard
int bdrv_truncate(BlockDriverState *bs, int64_t offset)
672 83f64091 bellard
{
673 83f64091 bellard
    BlockDriver *drv = bs->drv;
674 83f64091 bellard
    if (!drv)
675 19cb3738 bellard
        return -ENOMEDIUM;
676 83f64091 bellard
    if (!drv->bdrv_truncate)
677 83f64091 bellard
        return -ENOTSUP;
678 83f64091 bellard
    return drv->bdrv_truncate(bs, offset);
679 83f64091 bellard
}
680 83f64091 bellard
681 83f64091 bellard
/**
682 83f64091 bellard
 * Length of a file in bytes. Return < 0 if error or unknown.
683 83f64091 bellard
 */
684 83f64091 bellard
int64_t bdrv_getlength(BlockDriverState *bs)
685 83f64091 bellard
{
686 83f64091 bellard
    BlockDriver *drv = bs->drv;
687 83f64091 bellard
    if (!drv)
688 19cb3738 bellard
        return -ENOMEDIUM;
689 83f64091 bellard
    if (!drv->bdrv_getlength) {
690 83f64091 bellard
        /* legacy mode */
691 83f64091 bellard
        return bs->total_sectors * SECTOR_SIZE;
692 83f64091 bellard
    }
693 83f64091 bellard
    return drv->bdrv_getlength(bs);
694 fc01f7e7 bellard
}
695 fc01f7e7 bellard
696 19cb3738 bellard
/* return 0 as number of sectors if no device present or error */
697 fc01f7e7 bellard
void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
698 fc01f7e7 bellard
{
699 19cb3738 bellard
    int64_t length;
700 19cb3738 bellard
    length = bdrv_getlength(bs);
701 19cb3738 bellard
    if (length < 0)
702 19cb3738 bellard
        length = 0;
703 19cb3738 bellard
    else
704 19cb3738 bellard
        length = length >> SECTOR_BITS;
705 19cb3738 bellard
    *nb_sectors_ptr = length;
706 fc01f7e7 bellard
}
707 cf98951b bellard
708 cf98951b bellard
/* force a given boot sector. */
709 cf98951b bellard
void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
710 cf98951b bellard
{
711 cf98951b bellard
    bs->boot_sector_enabled = 1;
712 cf98951b bellard
    if (size > 512)
713 cf98951b bellard
        size = 512;
714 cf98951b bellard
    memcpy(bs->boot_sector_data, data, size);
715 cf98951b bellard
    memset(bs->boot_sector_data + size, 0, 512 - size);
716 cf98951b bellard
}
717 b338082b bellard
718 b338082b bellard
void bdrv_set_geometry_hint(BlockDriverState *bs, 
719 b338082b bellard
                            int cyls, int heads, int secs)
720 b338082b bellard
{
721 b338082b bellard
    bs->cyls = cyls;
722 b338082b bellard
    bs->heads = heads;
723 b338082b bellard
    bs->secs = secs;
724 b338082b bellard
}
725 b338082b bellard
726 b338082b bellard
void bdrv_set_type_hint(BlockDriverState *bs, int type)
727 b338082b bellard
{
728 b338082b bellard
    bs->type = type;
729 b338082b bellard
    bs->removable = ((type == BDRV_TYPE_CDROM ||
730 b338082b bellard
                      type == BDRV_TYPE_FLOPPY));
731 b338082b bellard
}
732 b338082b bellard
733 46d4767d bellard
void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
734 46d4767d bellard
{
735 46d4767d bellard
    bs->translation = translation;
736 46d4767d bellard
}
737 46d4767d bellard
738 b338082b bellard
void bdrv_get_geometry_hint(BlockDriverState *bs, 
739 b338082b bellard
                            int *pcyls, int *pheads, int *psecs)
740 b338082b bellard
{
741 b338082b bellard
    *pcyls = bs->cyls;
742 b338082b bellard
    *pheads = bs->heads;
743 b338082b bellard
    *psecs = bs->secs;
744 b338082b bellard
}
745 b338082b bellard
746 b338082b bellard
int bdrv_get_type_hint(BlockDriverState *bs)
747 b338082b bellard
{
748 b338082b bellard
    return bs->type;
749 b338082b bellard
}
750 b338082b bellard
751 46d4767d bellard
int bdrv_get_translation_hint(BlockDriverState *bs)
752 46d4767d bellard
{
753 46d4767d bellard
    return bs->translation;
754 46d4767d bellard
}
755 46d4767d bellard
756 b338082b bellard
int bdrv_is_removable(BlockDriverState *bs)
757 b338082b bellard
{
758 b338082b bellard
    return bs->removable;
759 b338082b bellard
}
760 b338082b bellard
761 b338082b bellard
int bdrv_is_read_only(BlockDriverState *bs)
762 b338082b bellard
{
763 b338082b bellard
    return bs->read_only;
764 b338082b bellard
}
765 b338082b bellard
766 19cb3738 bellard
/* XXX: no longer used */
767 b338082b bellard
void bdrv_set_change_cb(BlockDriverState *bs, 
768 b338082b bellard
                        void (*change_cb)(void *opaque), void *opaque)
769 b338082b bellard
{
770 b338082b bellard
    bs->change_cb = change_cb;
771 b338082b bellard
    bs->change_opaque = opaque;
772 b338082b bellard
}
773 b338082b bellard
774 ea2384d3 bellard
int bdrv_is_encrypted(BlockDriverState *bs)
775 ea2384d3 bellard
{
776 ea2384d3 bellard
    if (bs->backing_hd && bs->backing_hd->encrypted)
777 ea2384d3 bellard
        return 1;
778 ea2384d3 bellard
    return bs->encrypted;
779 ea2384d3 bellard
}
780 ea2384d3 bellard
781 ea2384d3 bellard
int bdrv_set_key(BlockDriverState *bs, const char *key)
782 ea2384d3 bellard
{
783 ea2384d3 bellard
    int ret;
784 ea2384d3 bellard
    if (bs->backing_hd && bs->backing_hd->encrypted) {
785 ea2384d3 bellard
        ret = bdrv_set_key(bs->backing_hd, key);
786 ea2384d3 bellard
        if (ret < 0)
787 ea2384d3 bellard
            return ret;
788 ea2384d3 bellard
        if (!bs->encrypted)
789 ea2384d3 bellard
            return 0;
790 ea2384d3 bellard
    }
791 ea2384d3 bellard
    if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
792 ea2384d3 bellard
        return -1;
793 ea2384d3 bellard
    return bs->drv->bdrv_set_key(bs, key);
794 ea2384d3 bellard
}
795 ea2384d3 bellard
796 ea2384d3 bellard
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
797 ea2384d3 bellard
{
798 19cb3738 bellard
    if (!bs->drv) {
799 ea2384d3 bellard
        buf[0] = '\0';
800 ea2384d3 bellard
    } else {
801 ea2384d3 bellard
        pstrcpy(buf, buf_size, bs->drv->format_name);
802 ea2384d3 bellard
    }
803 ea2384d3 bellard
}
804 ea2384d3 bellard
805 ea2384d3 bellard
void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
806 ea2384d3 bellard
                         void *opaque)
807 ea2384d3 bellard
{
808 ea2384d3 bellard
    BlockDriver *drv;
809 ea2384d3 bellard
810 ea2384d3 bellard
    for (drv = first_drv; drv != NULL; drv = drv->next) {
811 ea2384d3 bellard
        it(opaque, drv->format_name);
812 ea2384d3 bellard
    }
813 ea2384d3 bellard
}
814 ea2384d3 bellard
815 b338082b bellard
BlockDriverState *bdrv_find(const char *name)
816 b338082b bellard
{
817 b338082b bellard
    BlockDriverState *bs;
818 b338082b bellard
819 b338082b bellard
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
820 b338082b bellard
        if (!strcmp(name, bs->device_name))
821 b338082b bellard
            return bs;
822 b338082b bellard
    }
823 b338082b bellard
    return NULL;
824 b338082b bellard
}
825 b338082b bellard
826 81d0912d bellard
void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
827 81d0912d bellard
{
828 81d0912d bellard
    BlockDriverState *bs;
829 81d0912d bellard
830 81d0912d bellard
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
831 81d0912d bellard
        it(opaque, bs->device_name);
832 81d0912d bellard
    }
833 81d0912d bellard
}
834 81d0912d bellard
835 ea2384d3 bellard
const char *bdrv_get_device_name(BlockDriverState *bs)
836 ea2384d3 bellard
{
837 ea2384d3 bellard
    return bs->device_name;
838 ea2384d3 bellard
}
839 ea2384d3 bellard
840 7a6cba61 pbrook
void bdrv_flush(BlockDriverState *bs)
841 7a6cba61 pbrook
{
842 7a6cba61 pbrook
    if (bs->drv->bdrv_flush)
843 7a6cba61 pbrook
        bs->drv->bdrv_flush(bs);
844 7a6cba61 pbrook
    if (bs->backing_hd)
845 7a6cba61 pbrook
        bdrv_flush(bs->backing_hd);
846 7a6cba61 pbrook
}
847 7a6cba61 pbrook
848 b338082b bellard
void bdrv_info(void)
849 b338082b bellard
{
850 b338082b bellard
    BlockDriverState *bs;
851 b338082b bellard
852 b338082b bellard
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
853 b338082b bellard
        term_printf("%s:", bs->device_name);
854 b338082b bellard
        term_printf(" type=");
855 b338082b bellard
        switch(bs->type) {
856 b338082b bellard
        case BDRV_TYPE_HD:
857 b338082b bellard
            term_printf("hd");
858 b338082b bellard
            break;
859 b338082b bellard
        case BDRV_TYPE_CDROM:
860 b338082b bellard
            term_printf("cdrom");
861 b338082b bellard
            break;
862 b338082b bellard
        case BDRV_TYPE_FLOPPY:
863 b338082b bellard
            term_printf("floppy");
864 b338082b bellard
            break;
865 b338082b bellard
        }
866 b338082b bellard
        term_printf(" removable=%d", bs->removable);
867 b338082b bellard
        if (bs->removable) {
868 b338082b bellard
            term_printf(" locked=%d", bs->locked);
869 b338082b bellard
        }
870 19cb3738 bellard
        if (bs->drv) {
871 b338082b bellard
            term_printf(" file=%s", bs->filename);
872 ea2384d3 bellard
            if (bs->backing_file[0] != '\0')
873 ea2384d3 bellard
                term_printf(" backing_file=%s", bs->backing_file);
874 b338082b bellard
            term_printf(" ro=%d", bs->read_only);
875 ea2384d3 bellard
            term_printf(" drv=%s", bs->drv->format_name);
876 ea2384d3 bellard
            if (bs->encrypted)
877 ea2384d3 bellard
                term_printf(" encrypted");
878 b338082b bellard
        } else {
879 b338082b bellard
            term_printf(" [not inserted]");
880 b338082b bellard
        }
881 b338082b bellard
        term_printf("\n");
882 b338082b bellard
    }
883 b338082b bellard
}
884 ea2384d3 bellard
885 83f64091 bellard
void bdrv_get_backing_filename(BlockDriverState *bs, 
886 83f64091 bellard
                               char *filename, int filename_size)
887 83f64091 bellard
{
888 83f64091 bellard
    if (!bs->backing_hd) {
889 83f64091 bellard
        pstrcpy(filename, filename_size, "");
890 83f64091 bellard
    } else {
891 83f64091 bellard
        pstrcpy(filename, filename_size, bs->backing_file);
892 83f64091 bellard
    }
893 83f64091 bellard
}
894 83f64091 bellard
895 faea38e7 bellard
int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, 
896 faea38e7 bellard
                          const uint8_t *buf, int nb_sectors)
897 faea38e7 bellard
{
898 faea38e7 bellard
    BlockDriver *drv = bs->drv;
899 faea38e7 bellard
    if (!drv)
900 19cb3738 bellard
        return -ENOMEDIUM;
901 faea38e7 bellard
    if (!drv->bdrv_write_compressed)
902 faea38e7 bellard
        return -ENOTSUP;
903 faea38e7 bellard
    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
904 faea38e7 bellard
}
905 faea38e7 bellard
    
906 faea38e7 bellard
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
907 faea38e7 bellard
{
908 faea38e7 bellard
    BlockDriver *drv = bs->drv;
909 faea38e7 bellard
    if (!drv)
910 19cb3738 bellard
        return -ENOMEDIUM;
911 faea38e7 bellard
    if (!drv->bdrv_get_info)
912 faea38e7 bellard
        return -ENOTSUP;
913 faea38e7 bellard
    memset(bdi, 0, sizeof(*bdi));
914 faea38e7 bellard
    return drv->bdrv_get_info(bs, bdi);
915 faea38e7 bellard
}
916 faea38e7 bellard
917 faea38e7 bellard
/**************************************************************/
918 faea38e7 bellard
/* handling of snapshots */
919 faea38e7 bellard
920 faea38e7 bellard
int bdrv_snapshot_create(BlockDriverState *bs, 
921 faea38e7 bellard
                         QEMUSnapshotInfo *sn_info)
922 faea38e7 bellard
{
923 faea38e7 bellard
    BlockDriver *drv = bs->drv;
924 faea38e7 bellard
    if (!drv)
925 19cb3738 bellard
        return -ENOMEDIUM;
926 faea38e7 bellard
    if (!drv->bdrv_snapshot_create)
927 faea38e7 bellard
        return -ENOTSUP;
928 faea38e7 bellard
    return drv->bdrv_snapshot_create(bs, sn_info);
929 faea38e7 bellard
}
930 faea38e7 bellard
931 faea38e7 bellard
int bdrv_snapshot_goto(BlockDriverState *bs, 
932 faea38e7 bellard
                       const char *snapshot_id)
933 faea38e7 bellard
{
934 faea38e7 bellard
    BlockDriver *drv = bs->drv;
935 faea38e7 bellard
    if (!drv)
936 19cb3738 bellard
        return -ENOMEDIUM;
937 faea38e7 bellard
    if (!drv->bdrv_snapshot_goto)
938 faea38e7 bellard
        return -ENOTSUP;
939 faea38e7 bellard
    return drv->bdrv_snapshot_goto(bs, snapshot_id);
940 faea38e7 bellard
}
941 faea38e7 bellard
942 faea38e7 bellard
int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
943 faea38e7 bellard
{
944 faea38e7 bellard
    BlockDriver *drv = bs->drv;
945 faea38e7 bellard
    if (!drv)
946 19cb3738 bellard
        return -ENOMEDIUM;
947 faea38e7 bellard
    if (!drv->bdrv_snapshot_delete)
948 faea38e7 bellard
        return -ENOTSUP;
949 faea38e7 bellard
    return drv->bdrv_snapshot_delete(bs, snapshot_id);
950 faea38e7 bellard
}
951 faea38e7 bellard
952 faea38e7 bellard
int bdrv_snapshot_list(BlockDriverState *bs, 
953 faea38e7 bellard
                       QEMUSnapshotInfo **psn_info)
954 faea38e7 bellard
{
955 faea38e7 bellard
    BlockDriver *drv = bs->drv;
956 faea38e7 bellard
    if (!drv)
957 19cb3738 bellard
        return -ENOMEDIUM;
958 faea38e7 bellard
    if (!drv->bdrv_snapshot_list)
959 faea38e7 bellard
        return -ENOTSUP;
960 faea38e7 bellard
    return drv->bdrv_snapshot_list(bs, psn_info);
961 faea38e7 bellard
}
962 faea38e7 bellard
963 faea38e7 bellard
#define NB_SUFFIXES 4
964 faea38e7 bellard
965 faea38e7 bellard
char *get_human_readable_size(char *buf, int buf_size, int64_t size)
966 faea38e7 bellard
{
967 faea38e7 bellard
    static const char suffixes[NB_SUFFIXES] = "KMGT";
968 faea38e7 bellard
    int64_t base;
969 faea38e7 bellard
    int i;
970 faea38e7 bellard
971 faea38e7 bellard
    if (size <= 999) {
972 faea38e7 bellard
        snprintf(buf, buf_size, "%" PRId64, size);
973 faea38e7 bellard
    } else {
974 faea38e7 bellard
        base = 1024;
975 faea38e7 bellard
        for(i = 0; i < NB_SUFFIXES; i++) {
976 faea38e7 bellard
            if (size < (10 * base)) {
977 faea38e7 bellard
                snprintf(buf, buf_size, "%0.1f%c", 
978 faea38e7 bellard
                         (double)size / base,
979 faea38e7 bellard
                         suffixes[i]);
980 faea38e7 bellard
                break;
981 faea38e7 bellard
            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
982 faea38e7 bellard
                snprintf(buf, buf_size, "%" PRId64 "%c", 
983 faea38e7 bellard
                         ((size + (base >> 1)) / base),
984 faea38e7 bellard
                         suffixes[i]);
985 faea38e7 bellard
                break;
986 faea38e7 bellard
            }
987 faea38e7 bellard
            base = base * 1024;
988 faea38e7 bellard
        }
989 faea38e7 bellard
    }
990 faea38e7 bellard
    return buf;
991 faea38e7 bellard
}
992 faea38e7 bellard
993 faea38e7 bellard
char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
994 faea38e7 bellard
{
995 faea38e7 bellard
    char buf1[128], date_buf[128], clock_buf[128];
996 faea38e7 bellard
    struct tm tm;
997 faea38e7 bellard
    time_t ti;
998 faea38e7 bellard
    int64_t secs;
999 faea38e7 bellard
1000 faea38e7 bellard
    if (!sn) {
1001 faea38e7 bellard
        snprintf(buf, buf_size, 
1002 faea38e7 bellard
                 "%-10s%-20s%7s%20s%15s", 
1003 faea38e7 bellard
                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
1004 faea38e7 bellard
    } else {
1005 faea38e7 bellard
        ti = sn->date_sec;
1006 ce1a14dc pbrook
#ifndef _WIN32
1007 faea38e7 bellard
        localtime_r(&ti, &tm);
1008 ce1a14dc pbrook
#endif
1009 faea38e7 bellard
        strftime(date_buf, sizeof(date_buf),
1010 faea38e7 bellard
                 "%Y-%m-%d %H:%M:%S", &tm);
1011 faea38e7 bellard
        secs = sn->vm_clock_nsec / 1000000000;
1012 faea38e7 bellard
        snprintf(clock_buf, sizeof(clock_buf),
1013 faea38e7 bellard
                 "%02d:%02d:%02d.%03d",
1014 faea38e7 bellard
                 (int)(secs / 3600),
1015 faea38e7 bellard
                 (int)((secs / 60) % 60),
1016 faea38e7 bellard
                 (int)(secs % 60), 
1017 faea38e7 bellard
                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
1018 faea38e7 bellard
        snprintf(buf, buf_size,
1019 faea38e7 bellard
                 "%-10s%-20s%7s%20s%15s", 
1020 faea38e7 bellard
                 sn->id_str, sn->name,
1021 faea38e7 bellard
                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
1022 faea38e7 bellard
                 date_buf,
1023 faea38e7 bellard
                 clock_buf);
1024 faea38e7 bellard
    }
1025 faea38e7 bellard
    return buf;
1026 faea38e7 bellard
}
1027 faea38e7 bellard
1028 83f64091 bellard
1029 ea2384d3 bellard
/**************************************************************/
1030 83f64091 bellard
/* async I/Os */
1031 ea2384d3 bellard
1032 ce1a14dc pbrook
BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
1033 ce1a14dc pbrook
                                uint8_t *buf, int nb_sectors,
1034 ce1a14dc pbrook
                                BlockDriverCompletionFunc *cb, void *opaque)
1035 83f64091 bellard
{
1036 83f64091 bellard
    BlockDriver *drv = bs->drv;
1037 83f64091 bellard
1038 19cb3738 bellard
    if (!drv)
1039 ce1a14dc pbrook
        return NULL;
1040 83f64091 bellard
    
1041 83f64091 bellard
    /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
1042 83f64091 bellard
    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
1043 83f64091 bellard
        memcpy(buf, bs->boot_sector_data, 512);
1044 83f64091 bellard
        sector_num++;
1045 83f64091 bellard
        nb_sectors--;
1046 83f64091 bellard
        buf += 512;
1047 83f64091 bellard
    }
1048 83f64091 bellard
1049 ce1a14dc pbrook
    return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
1050 ea2384d3 bellard
}
1051 ea2384d3 bellard
1052 ce1a14dc pbrook
BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
1053 ce1a14dc pbrook
                                 const uint8_t *buf, int nb_sectors,
1054 ce1a14dc pbrook
                                 BlockDriverCompletionFunc *cb, void *opaque)
1055 ea2384d3 bellard
{
1056 83f64091 bellard
    BlockDriver *drv = bs->drv;
1057 ea2384d3 bellard
1058 19cb3738 bellard
    if (!drv)
1059 ce1a14dc pbrook
        return NULL;
1060 83f64091 bellard
    if (bs->read_only)
1061 ce1a14dc pbrook
        return NULL;
1062 83f64091 bellard
    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
1063 83f64091 bellard
        memcpy(bs->boot_sector_data, buf, 512);   
1064 ea2384d3 bellard
    }
1065 83f64091 bellard
1066 ce1a14dc pbrook
    return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
1067 83f64091 bellard
}
1068 83f64091 bellard
1069 83f64091 bellard
void bdrv_aio_cancel(BlockDriverAIOCB *acb)
1070 83f64091 bellard
{
1071 ce1a14dc pbrook
    BlockDriver *drv = acb->bs->drv;
1072 83f64091 bellard
1073 ce1a14dc pbrook
    drv->bdrv_aio_cancel(acb);
1074 83f64091 bellard
}
1075 83f64091 bellard
1076 ce1a14dc pbrook
1077 83f64091 bellard
/**************************************************************/
1078 83f64091 bellard
/* async block device emulation */
1079 83f64091 bellard
1080 83f64091 bellard
#ifdef QEMU_TOOL
1081 ce1a14dc pbrook
static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
1082 ce1a14dc pbrook
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1083 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
1084 ea2384d3 bellard
{
1085 ea2384d3 bellard
    int ret;
1086 ce1a14dc pbrook
    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
1087 ce1a14dc pbrook
    cb(opaque, ret);
1088 ce1a14dc pbrook
    return NULL;
1089 ea2384d3 bellard
}
1090 ea2384d3 bellard
1091 ce1a14dc pbrook
static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
1092 ce1a14dc pbrook
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
1093 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
1094 ea2384d3 bellard
{
1095 ea2384d3 bellard
    int ret;
1096 ce1a14dc pbrook
    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
1097 ce1a14dc pbrook
    cb(opaque, ret);
1098 ce1a14dc pbrook
    return NULL;
1099 ea2384d3 bellard
}
1100 ea2384d3 bellard
1101 83f64091 bellard
static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
1102 ea2384d3 bellard
{
1103 ea2384d3 bellard
}
1104 83f64091 bellard
#else
1105 ce1a14dc pbrook
static void bdrv_aio_bh_cb(void *opaque)
1106 83f64091 bellard
{
1107 ce1a14dc pbrook
    BlockDriverAIOCBSync *acb = opaque;
1108 ce1a14dc pbrook
    acb->common.cb(acb->common.opaque, acb->ret);
1109 ce1a14dc pbrook
    qemu_aio_release(acb);
1110 83f64091 bellard
}
1111 beac80cd bellard
1112 ce1a14dc pbrook
static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
1113 ce1a14dc pbrook
        int64_t sector_num, uint8_t *buf, int nb_sectors,
1114 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
1115 83f64091 bellard
{
1116 ce1a14dc pbrook
    BlockDriverAIOCBSync *acb;
1117 83f64091 bellard
    int ret;
1118 ce1a14dc pbrook
1119 ce1a14dc pbrook
    acb = qemu_aio_get(bs, cb, opaque);
1120 ce1a14dc pbrook
    if (!acb->bh)
1121 ce1a14dc pbrook
        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
1122 ce1a14dc pbrook
    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
1123 ce1a14dc pbrook
    acb->ret = ret;
1124 ce1a14dc pbrook
    qemu_bh_schedule(acb->bh);
1125 ce1a14dc pbrook
    return &acb->common;
1126 beac80cd bellard
}
1127 beac80cd bellard
1128 ce1a14dc pbrook
static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
1129 ce1a14dc pbrook
        int64_t sector_num, const uint8_t *buf, int nb_sectors,
1130 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
1131 beac80cd bellard
{
1132 ce1a14dc pbrook
    BlockDriverAIOCBSync *acb;
1133 83f64091 bellard
    int ret;
1134 83f64091 bellard
1135 ce1a14dc pbrook
    acb = qemu_aio_get(bs, cb, opaque);
1136 ce1a14dc pbrook
    if (!acb->bh)
1137 ce1a14dc pbrook
        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
1138 ce1a14dc pbrook
    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
1139 ce1a14dc pbrook
    acb->ret = ret;
1140 ce1a14dc pbrook
    qemu_bh_schedule(acb->bh);
1141 ce1a14dc pbrook
    return &acb->common;
1142 beac80cd bellard
}
1143 beac80cd bellard
1144 ce1a14dc pbrook
static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
1145 ea2384d3 bellard
{
1146 ce1a14dc pbrook
    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
1147 ce1a14dc pbrook
    qemu_bh_cancel(acb->bh);
1148 ce1a14dc pbrook
    qemu_aio_release(acb);
1149 83f64091 bellard
}
1150 83f64091 bellard
#endif /* !QEMU_TOOL */
1151 ea2384d3 bellard
1152 83f64091 bellard
/**************************************************************/
1153 83f64091 bellard
/* sync block device emulation */
1154 ea2384d3 bellard
1155 83f64091 bellard
static void bdrv_rw_em_cb(void *opaque, int ret)
1156 83f64091 bellard
{
1157 83f64091 bellard
    *(int *)opaque = ret;
1158 ea2384d3 bellard
}
1159 ea2384d3 bellard
1160 83f64091 bellard
#define NOT_DONE 0x7fffffff
1161 83f64091 bellard
1162 83f64091 bellard
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
1163 83f64091 bellard
                        uint8_t *buf, int nb_sectors)
1164 7a6cba61 pbrook
{
1165 ce1a14dc pbrook
    int async_ret;
1166 ce1a14dc pbrook
    BlockDriverAIOCB *acb;
1167 83f64091 bellard
1168 83f64091 bellard
    async_ret = NOT_DONE;
1169 83f64091 bellard
    qemu_aio_wait_start();
1170 ce1a14dc pbrook
    acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, 
1171 83f64091 bellard
                        bdrv_rw_em_cb, &async_ret);
1172 ce1a14dc pbrook
    if (acb == NULL) {
1173 83f64091 bellard
        qemu_aio_wait_end();
1174 ce1a14dc pbrook
        return -1;
1175 83f64091 bellard
    }
1176 83f64091 bellard
    while (async_ret == NOT_DONE) {
1177 83f64091 bellard
        qemu_aio_wait();
1178 83f64091 bellard
    }
1179 83f64091 bellard
    qemu_aio_wait_end();
1180 83f64091 bellard
    return async_ret;
1181 7a6cba61 pbrook
}
1182 7a6cba61 pbrook
1183 83f64091 bellard
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
1184 83f64091 bellard
                         const uint8_t *buf, int nb_sectors)
1185 83f64091 bellard
{
1186 ce1a14dc pbrook
    int async_ret;
1187 ce1a14dc pbrook
    BlockDriverAIOCB *acb;
1188 83f64091 bellard
1189 83f64091 bellard
    async_ret = NOT_DONE;
1190 83f64091 bellard
    qemu_aio_wait_start();
1191 ce1a14dc pbrook
    acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, 
1192 83f64091 bellard
                         bdrv_rw_em_cb, &async_ret);
1193 ce1a14dc pbrook
    if (acb == NULL) {
1194 83f64091 bellard
        qemu_aio_wait_end();
1195 ce1a14dc pbrook
        return -1;
1196 83f64091 bellard
    }
1197 83f64091 bellard
    while (async_ret == NOT_DONE) {
1198 83f64091 bellard
        qemu_aio_wait();
1199 83f64091 bellard
    }
1200 83f64091 bellard
    qemu_aio_wait_end();
1201 83f64091 bellard
    return async_ret;
1202 83f64091 bellard
}
1203 ea2384d3 bellard
1204 ea2384d3 bellard
void bdrv_init(void)
1205 ea2384d3 bellard
{
1206 ea2384d3 bellard
    bdrv_register(&bdrv_raw);
1207 19cb3738 bellard
    bdrv_register(&bdrv_host_device);
1208 ea2384d3 bellard
#ifndef _WIN32
1209 ea2384d3 bellard
    bdrv_register(&bdrv_cow);
1210 ea2384d3 bellard
#endif
1211 ea2384d3 bellard
    bdrv_register(&bdrv_qcow);
1212 ea2384d3 bellard
    bdrv_register(&bdrv_vmdk);
1213 3c56521b bellard
    bdrv_register(&bdrv_cloop);
1214 585d0ed9 bellard
    bdrv_register(&bdrv_dmg);
1215 a8753c34 bellard
    bdrv_register(&bdrv_bochs);
1216 6a0f9e82 bellard
    bdrv_register(&bdrv_vpc);
1217 712e7874 bellard
    bdrv_register(&bdrv_vvfat);
1218 faea38e7 bellard
    bdrv_register(&bdrv_qcow2);
1219 ea2384d3 bellard
}
1220 ce1a14dc pbrook
1221 ce1a14dc pbrook
void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
1222 ce1a14dc pbrook
                   void *opaque)
1223 ce1a14dc pbrook
{
1224 ce1a14dc pbrook
    BlockDriver *drv;
1225 ce1a14dc pbrook
    BlockDriverAIOCB *acb;
1226 ce1a14dc pbrook
1227 ce1a14dc pbrook
    drv = bs->drv;
1228 ce1a14dc pbrook
    if (drv->free_aiocb) {
1229 ce1a14dc pbrook
        acb = drv->free_aiocb;
1230 ce1a14dc pbrook
        drv->free_aiocb = acb->next;
1231 ce1a14dc pbrook
    } else {
1232 ce1a14dc pbrook
        acb = qemu_mallocz(drv->aiocb_size);
1233 ce1a14dc pbrook
        if (!acb)
1234 ce1a14dc pbrook
            return NULL;
1235 ce1a14dc pbrook
    }
1236 ce1a14dc pbrook
    acb->bs = bs;
1237 ce1a14dc pbrook
    acb->cb = cb;
1238 ce1a14dc pbrook
    acb->opaque = opaque;
1239 ce1a14dc pbrook
    return acb;
1240 ce1a14dc pbrook
}
1241 ce1a14dc pbrook
1242 ce1a14dc pbrook
void qemu_aio_release(void *p)
1243 ce1a14dc pbrook
{
1244 ce1a14dc pbrook
    BlockDriverAIOCB *acb = p;
1245 ce1a14dc pbrook
    BlockDriver *drv = acb->bs->drv;
1246 ce1a14dc pbrook
    acb->next = drv->free_aiocb;
1247 ce1a14dc pbrook
    drv->free_aiocb = acb;
1248 ce1a14dc pbrook
}
1249 19cb3738 bellard
1250 19cb3738 bellard
/**************************************************************/
1251 19cb3738 bellard
/* removable device support */
1252 19cb3738 bellard
1253 19cb3738 bellard
/**
1254 19cb3738 bellard
 * Return TRUE if the media is present
1255 19cb3738 bellard
 */
1256 19cb3738 bellard
int bdrv_is_inserted(BlockDriverState *bs)
1257 19cb3738 bellard
{
1258 19cb3738 bellard
    BlockDriver *drv = bs->drv;
1259 19cb3738 bellard
    int ret;
1260 19cb3738 bellard
    if (!drv)
1261 19cb3738 bellard
        return 0;
1262 19cb3738 bellard
    if (!drv->bdrv_is_inserted)
1263 19cb3738 bellard
        return 1;
1264 19cb3738 bellard
    ret = drv->bdrv_is_inserted(bs);
1265 19cb3738 bellard
    return ret;
1266 19cb3738 bellard
}
1267 19cb3738 bellard
1268 19cb3738 bellard
/**
1269 19cb3738 bellard
 * Return TRUE if the media changed since the last call to this
1270 19cb3738 bellard
 * function. It is currently only used for floppy disks 
1271 19cb3738 bellard
 */
1272 19cb3738 bellard
int bdrv_media_changed(BlockDriverState *bs)
1273 19cb3738 bellard
{
1274 19cb3738 bellard
    BlockDriver *drv = bs->drv;
1275 19cb3738 bellard
    int ret;
1276 19cb3738 bellard
1277 19cb3738 bellard
    if (!drv || !drv->bdrv_media_changed)
1278 19cb3738 bellard
        ret = -ENOTSUP;
1279 19cb3738 bellard
    else
1280 19cb3738 bellard
        ret = drv->bdrv_media_changed(bs);
1281 19cb3738 bellard
    if (ret == -ENOTSUP)
1282 19cb3738 bellard
        ret = bs->media_changed;
1283 19cb3738 bellard
    bs->media_changed = 0;
1284 19cb3738 bellard
    return ret;
1285 19cb3738 bellard
}
1286 19cb3738 bellard
1287 19cb3738 bellard
/**
1288 19cb3738 bellard
 * If eject_flag is TRUE, eject the media. Otherwise, close the tray
1289 19cb3738 bellard
 */
1290 19cb3738 bellard
void bdrv_eject(BlockDriverState *bs, int eject_flag)
1291 19cb3738 bellard
{
1292 19cb3738 bellard
    BlockDriver *drv = bs->drv;
1293 19cb3738 bellard
    int ret;
1294 19cb3738 bellard
1295 19cb3738 bellard
    if (!drv || !drv->bdrv_eject) {
1296 19cb3738 bellard
        ret = -ENOTSUP;
1297 19cb3738 bellard
    } else {
1298 19cb3738 bellard
        ret = drv->bdrv_eject(bs, eject_flag);
1299 19cb3738 bellard
    }
1300 19cb3738 bellard
    if (ret == -ENOTSUP) {
1301 19cb3738 bellard
        if (eject_flag)
1302 19cb3738 bellard
            bdrv_close(bs);
1303 19cb3738 bellard
    }
1304 19cb3738 bellard
}
1305 19cb3738 bellard
1306 19cb3738 bellard
int bdrv_is_locked(BlockDriverState *bs)
1307 19cb3738 bellard
{
1308 19cb3738 bellard
    return bs->locked;
1309 19cb3738 bellard
}
1310 19cb3738 bellard
1311 19cb3738 bellard
/**
1312 19cb3738 bellard
 * Lock or unlock the media (if it is locked, the user won't be able
1313 19cb3738 bellard
 * to eject it manually).
1314 19cb3738 bellard
 */
1315 19cb3738 bellard
void bdrv_set_locked(BlockDriverState *bs, int locked)
1316 19cb3738 bellard
{
1317 19cb3738 bellard
    BlockDriver *drv = bs->drv;
1318 19cb3738 bellard
1319 19cb3738 bellard
    bs->locked = locked;
1320 19cb3738 bellard
    if (drv && drv->bdrv_set_locked) {
1321 19cb3738 bellard
        drv->bdrv_set_locked(bs, locked);
1322 19cb3738 bellard
    }
1323 19cb3738 bellard
}