0.6.2-alt1.1
[qemu] / qemu-snapshot-2004-11-28_23 / block.c
1 /*
2  * QEMU System Emulator block driver
3  * 
4  * Copyright (c) 2003 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25 #include "block_int.h"
26
27 static BlockDriverState *bdrv_first;
28 static BlockDriver *first_drv;
29
30 void bdrv_register(BlockDriver *bdrv)
31 {
32     bdrv->next = first_drv;
33     first_drv = bdrv;
34 }
35
36 /* create a new block device (by default it is empty) */
37 BlockDriverState *bdrv_new(const char *device_name)
38 {
39     BlockDriverState **pbs, *bs;
40
41     bs = qemu_mallocz(sizeof(BlockDriverState));
42     if(!bs)
43         return NULL;
44     pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
45     if (device_name[0] != '\0') {
46         /* insert at the end */
47         pbs = &bdrv_first;
48         while (*pbs != NULL)
49             pbs = &(*pbs)->next;
50         *pbs = bs;
51     }
52     return bs;
53 }
54
55 BlockDriver *bdrv_find_format(const char *format_name)
56 {
57     BlockDriver *drv1;
58     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
59         if (!strcmp(drv1->format_name, format_name))
60             return drv1;
61     }
62     return NULL;
63 }
64
65 int bdrv_create(BlockDriver *drv, 
66                 const char *filename, int64_t size_in_sectors,
67                 const char *backing_file, int flags)
68 {
69     if (!drv->bdrv_create)
70         return -ENOTSUP;
71     return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
72 }
73
74 #ifdef _WIN32
75 static void get_tmp_filename(char *filename, int size)
76 {
77     /* XXX: find a better function */
78     tmpnam(filename);
79 }
80 #else
81 static void get_tmp_filename(char *filename, int size)
82 {
83     int fd;
84     /* XXX: race condition possible */
85     pstrcpy(filename, size, "/tmp/vl.XXXXXX");
86     fd = mkstemp(filename);
87     close(fd);
88 }
89 #endif
90
91 static BlockDriver *find_image_format(const char *filename)
92 {
93     int fd, ret, score, score_max;
94     BlockDriver *drv1, *drv;
95     uint8_t buf[1024];
96
97     fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
98     if (fd < 0)
99         return NULL;
100     ret = read(fd, buf, sizeof(buf));
101     if (ret < 0) {
102         close(fd);
103         return NULL;
104     }
105     close(fd);
106     
107     drv = NULL;
108     score_max = 0;
109     for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
110         score = drv1->bdrv_probe(buf, ret, filename);
111         if (score > score_max) {
112             score_max = score;
113             drv = drv1;
114         }
115     }
116     return drv;
117 }
118
119 int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
120 {
121     return bdrv_open2(bs, filename, snapshot, NULL);
122 }
123
124 int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
125                BlockDriver *drv)
126 {
127     int ret;
128     char tmp_filename[1024];
129     
130     bs->read_only = 0;
131     bs->is_temporary = 0;
132     bs->encrypted = 0;
133     
134     if (snapshot) {
135         BlockDriverState *bs1;
136         int64_t total_size;
137         
138         /* if snapshot, we create a temporary backing file and open it
139            instead of opening 'filename' directly */
140
141         /* if there is a backing file, use it */
142         bs1 = bdrv_new("");
143         if (!bs1) {
144             return -1;
145         }
146         if (bdrv_open(bs1, filename, 0) < 0) {
147             bdrv_delete(bs1);
148             return -1;
149         }
150         total_size = bs1->total_sectors;
151         bdrv_delete(bs1);
152         
153         get_tmp_filename(tmp_filename, sizeof(tmp_filename));
154         /* XXX: use cow for linux as it is more efficient ? */
155         if (bdrv_create(&bdrv_qcow, tmp_filename, 
156                         total_size, filename, 0) < 0) {
157             return -1;
158         }
159         filename = tmp_filename;
160         bs->is_temporary = 1;
161     }
162     
163     pstrcpy(bs->filename, sizeof(bs->filename), filename);
164     if (!drv) {
165         drv = find_image_format(filename);
166         if (!drv)
167             return -1;
168     }
169     bs->drv = drv;
170     bs->opaque = qemu_mallocz(drv->instance_size);
171     if (bs->opaque == NULL && drv->instance_size > 0)
172         return -1;
173     
174     ret = drv->bdrv_open(bs, filename);
175     if (ret < 0) {
176         qemu_free(bs->opaque);
177         return -1;
178     }
179 #ifndef _WIN32
180     if (bs->is_temporary) {
181         unlink(filename);
182     }
183 #endif
184     if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
185         /* if there is a backing file, use it */
186         bs->backing_hd = bdrv_new("");
187         if (!bs->backing_hd) {
188         fail:
189             bdrv_close(bs);
190             return -1;
191         }
192         if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
193             goto fail;
194     }
195
196     bs->inserted = 1;
197
198     /* call the change callback */
199     if (bs->change_cb)
200         bs->change_cb(bs->change_opaque);
201
202     return 0;
203 }
204
205 void bdrv_close(BlockDriverState *bs)
206 {
207     if (bs->inserted) {
208         if (bs->backing_hd)
209             bdrv_delete(bs->backing_hd);
210         bs->drv->bdrv_close(bs);
211         qemu_free(bs->opaque);
212 #ifdef _WIN32
213         if (bs->is_temporary) {
214             unlink(bs->filename);
215         }
216 #endif
217         bs->opaque = NULL;
218         bs->drv = NULL;
219         bs->inserted = 0;
220
221         /* call the change callback */
222         if (bs->change_cb)
223             bs->change_cb(bs->change_opaque);
224     }
225 }
226
227 void bdrv_delete(BlockDriverState *bs)
228 {
229     /* XXX: remove the driver list */
230     bdrv_close(bs);
231     qemu_free(bs);
232 }
233
234 /* commit COW file into the raw image */
235 int bdrv_commit(BlockDriverState *bs)
236 {
237     int64_t i;
238     int n, j;
239     unsigned char sector[512];
240
241     if (!bs->inserted)
242         return -ENOENT;
243
244     if (bs->read_only) {
245         return -EACCES;
246     }
247
248     if (!bs->backing_hd) {
249         return -ENOTSUP;
250     }
251
252     for (i = 0; i < bs->total_sectors;) {
253         if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
254             for(j = 0; j < n; j++) {
255                 if (bdrv_read(bs, i, sector, 1) != 0) {
256                     return -EIO;
257                 }
258
259                 if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
260                     return -EIO;
261                 }
262                 i++;
263             }
264         } else {
265             i += n;
266         }
267     }
268     return 0;
269 }
270
271 /* return -1 if error */
272 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
273               uint8_t *buf, int nb_sectors)
274 {
275     int ret, n;
276     BlockDriver *drv = bs->drv;
277
278     if (!bs->inserted)
279         return -1;
280
281     while (nb_sectors > 0) {
282         if (sector_num == 0 && bs->boot_sector_enabled) {
283             memcpy(buf, bs->boot_sector_data, 512);
284             n = 1;
285         } else if (bs->backing_hd) {
286             if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
287                 ret = drv->bdrv_read(bs, sector_num, buf, n);
288                 if (ret < 0)
289                     return -1;
290             } else {
291                 /* read from the base image */
292                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
293                 if (ret < 0)
294                     return -1;
295             }
296         } else {
297             ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
298             if (ret < 0)
299                 return -1;
300             /* no need to loop */
301             break;
302         }
303         nb_sectors -= n;
304         sector_num += n;
305         buf += n * 512;
306     }
307     return 0;
308 }
309
310 /* return -1 if error */
311 int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
312                const uint8_t *buf, int nb_sectors)
313 {
314     if (!bs->inserted)
315         return -1;
316     if (bs->read_only)
317         return -1;
318     return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
319 }
320
321 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
322 {
323     *nb_sectors_ptr = bs->total_sectors;
324 }
325
326 /* force a given boot sector. */
327 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
328 {
329     bs->boot_sector_enabled = 1;
330     if (size > 512)
331         size = 512;
332     memcpy(bs->boot_sector_data, data, size);
333     memset(bs->boot_sector_data + size, 0, 512 - size);
334 }
335
336 void bdrv_set_geometry_hint(BlockDriverState *bs, 
337                             int cyls, int heads, int secs)
338 {
339     bs->cyls = cyls;
340     bs->heads = heads;
341     bs->secs = secs;
342 }
343
344 void bdrv_set_type_hint(BlockDriverState *bs, int type)
345 {
346     bs->type = type;
347     bs->removable = ((type == BDRV_TYPE_CDROM ||
348                       type == BDRV_TYPE_FLOPPY));
349 }
350
351 void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
352 {
353     bs->translation = translation;
354 }
355
356 void bdrv_get_geometry_hint(BlockDriverState *bs, 
357                             int *pcyls, int *pheads, int *psecs)
358 {
359     *pcyls = bs->cyls;
360     *pheads = bs->heads;
361     *psecs = bs->secs;
362 }
363
364 int bdrv_get_type_hint(BlockDriverState *bs)
365 {
366     return bs->type;
367 }
368
369 int bdrv_get_translation_hint(BlockDriverState *bs)
370 {
371     return bs->translation;
372 }
373
374 int bdrv_is_removable(BlockDriverState *bs)
375 {
376     return bs->removable;
377 }
378
379 int bdrv_is_read_only(BlockDriverState *bs)
380 {
381     return bs->read_only;
382 }
383
384 int bdrv_is_inserted(BlockDriverState *bs)
385 {
386     return bs->inserted;
387 }
388
389 int bdrv_is_locked(BlockDriverState *bs)
390 {
391     return bs->locked;
392 }
393
394 void bdrv_set_locked(BlockDriverState *bs, int locked)
395 {
396     bs->locked = locked;
397 }
398
399 void bdrv_set_change_cb(BlockDriverState *bs, 
400                         void (*change_cb)(void *opaque), void *opaque)
401 {
402     bs->change_cb = change_cb;
403     bs->change_opaque = opaque;
404 }
405
406 int bdrv_is_encrypted(BlockDriverState *bs)
407 {
408     if (bs->backing_hd && bs->backing_hd->encrypted)
409         return 1;
410     return bs->encrypted;
411 }
412
413 int bdrv_set_key(BlockDriverState *bs, const char *key)
414 {
415     int ret;
416     if (bs->backing_hd && bs->backing_hd->encrypted) {
417         ret = bdrv_set_key(bs->backing_hd, key);
418         if (ret < 0)
419             return ret;
420         if (!bs->encrypted)
421             return 0;
422     }
423     if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
424         return -1;
425     return bs->drv->bdrv_set_key(bs, key);
426 }
427
428 void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
429 {
430     if (!bs->inserted || !bs->drv) {
431         buf[0] = '\0';
432     } else {
433         pstrcpy(buf, buf_size, bs->drv->format_name);
434     }
435 }
436
437 void bdrv_iterate_format(void (*it)(void *opaque, const char *name), 
438                          void *opaque)
439 {
440     BlockDriver *drv;
441
442     for (drv = first_drv; drv != NULL; drv = drv->next) {
443         it(opaque, drv->format_name);
444     }
445 }
446
447 BlockDriverState *bdrv_find(const char *name)
448 {
449     BlockDriverState *bs;
450
451     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
452         if (!strcmp(name, bs->device_name))
453             return bs;
454     }
455     return NULL;
456 }
457
458 void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
459 {
460     BlockDriverState *bs;
461
462     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
463         it(opaque, bs->device_name);
464     }
465 }
466
467 const char *bdrv_get_device_name(BlockDriverState *bs)
468 {
469     return bs->device_name;
470 }
471
472 void bdrv_info(void)
473 {
474     BlockDriverState *bs;
475
476     for (bs = bdrv_first; bs != NULL; bs = bs->next) {
477         term_printf("%s:", bs->device_name);
478         term_printf(" type=");
479         switch(bs->type) {
480         case BDRV_TYPE_HD:
481             term_printf("hd");
482             break;
483         case BDRV_TYPE_CDROM:
484             term_printf("cdrom");
485             break;
486         case BDRV_TYPE_FLOPPY:
487             term_printf("floppy");
488             break;
489         }
490         term_printf(" removable=%d", bs->removable);
491         if (bs->removable) {
492             term_printf(" locked=%d", bs->locked);
493         }
494         if (bs->inserted) {
495             term_printf(" file=%s", bs->filename);
496             if (bs->backing_file[0] != '\0')
497                 term_printf(" backing_file=%s", bs->backing_file);
498             term_printf(" ro=%d", bs->read_only);
499             term_printf(" drv=%s", bs->drv->format_name);
500             if (bs->encrypted)
501                 term_printf(" encrypted");
502         } else {
503             term_printf(" [not inserted]");
504         }
505         term_printf("\n");
506     }
507 }
508
509
510 /**************************************************************/
511 /* RAW block driver */
512
513 typedef struct BDRVRawState {
514     int fd;
515 } BDRVRawState;
516
517 static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
518 {
519     return 1; /* maybe */
520 }
521
522 static int raw_open(BlockDriverState *bs, const char *filename)
523 {
524     BDRVRawState *s = bs->opaque;
525     int fd;
526     int64_t size;
527
528     fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
529     if (fd < 0) {
530         fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
531         if (fd < 0)
532             return -1;
533         bs->read_only = 1;
534     }
535     size = lseek(fd, 0, SEEK_END);
536     bs->total_sectors = size / 512;
537     s->fd = fd;
538     return 0;
539 }
540
541 static int raw_read(BlockDriverState *bs, int64_t sector_num, 
542                     uint8_t *buf, int nb_sectors)
543 {
544     BDRVRawState *s = bs->opaque;
545     int ret;
546     
547     lseek(s->fd, sector_num * 512, SEEK_SET);
548     ret = read(s->fd, buf, nb_sectors * 512);
549     if (ret != nb_sectors * 512) 
550         return -1;
551     return 0;
552 }
553
554 static int raw_write(BlockDriverState *bs, int64_t sector_num, 
555                      const uint8_t *buf, int nb_sectors)
556 {
557     BDRVRawState *s = bs->opaque;
558     int ret;
559     
560     lseek(s->fd, sector_num * 512, SEEK_SET);
561     ret = write(s->fd, buf, nb_sectors * 512);
562     if (ret != nb_sectors * 512) 
563         return -1;
564     return 0;
565 }
566
567 static void raw_close(BlockDriverState *bs)
568 {
569     BDRVRawState *s = bs->opaque;
570     close(s->fd);
571 }
572
573 static int raw_create(const char *filename, int64_t total_size,
574                       const char *backing_file, int flags)
575 {
576     int fd;
577
578     if (flags || backing_file)
579         return -ENOTSUP;
580
581     fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
582               0644);
583     if (fd < 0)
584         return -EIO;
585     ftruncate(fd, total_size * 512);
586     close(fd);
587     return 0;
588 }
589
590 BlockDriver bdrv_raw = {
591     "raw",
592     sizeof(BDRVRawState),
593     raw_probe,
594     raw_open,
595     raw_read,
596     raw_write,
597     raw_close,
598     raw_create,
599 };
600
601 void bdrv_init(void)
602 {
603     bdrv_register(&bdrv_raw);
604 #ifndef _WIN32
605     bdrv_register(&bdrv_cow);
606 #endif
607     bdrv_register(&bdrv_qcow);
608     bdrv_register(&bdrv_vmdk);
609     bdrv_register(&bdrv_cloop);
610 }