root / block / cloop.c @ d2d979c6
History | View | Annotate | Download (4.9 kB)
1 | 3c56521b | bellard | /*
|
---|---|---|---|
2 | 585d0ed9 | bellard | * QEMU Block driver for CLOOP images
|
3 | 5fafdf24 | ths | *
|
4 | 3c56521b | bellard | * Copyright (c) 2004 Johannes E. Schindelin
|
5 | 5fafdf24 | ths | *
|
6 | 3c56521b | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 3c56521b | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | 3c56521b | bellard | * in the Software without restriction, including without limitation the rights
|
9 | 3c56521b | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 3c56521b | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | 3c56521b | bellard | * furnished to do so, subject to the following conditions:
|
12 | 3c56521b | bellard | *
|
13 | 3c56521b | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | 3c56521b | bellard | * all copies or substantial portions of the Software.
|
15 | 3c56521b | bellard | *
|
16 | 3c56521b | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 3c56521b | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 3c56521b | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 3c56521b | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 3c56521b | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 3c56521b | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 3c56521b | bellard | * THE SOFTWARE.
|
23 | 3c56521b | bellard | */
|
24 | faf07963 | pbrook | #include "qemu-common.h" |
25 | 3c56521b | bellard | #include "block_int.h" |
26 | 5efa9d5a | Anthony Liguori | #include "module.h" |
27 | 3c56521b | bellard | #include <zlib.h> |
28 | 3c56521b | bellard | |
29 | 3c56521b | bellard | typedef struct BDRVCloopState { |
30 | 3c56521b | bellard | uint32_t block_size; |
31 | 3c56521b | bellard | uint32_t n_blocks; |
32 | 3c56521b | bellard | uint64_t* offsets; |
33 | 3c56521b | bellard | uint32_t sectors_per_block; |
34 | 3c56521b | bellard | uint32_t current_block; |
35 | 28a5c9c8 | bellard | uint8_t *compressed_block; |
36 | 28a5c9c8 | bellard | uint8_t *uncompressed_block; |
37 | 3c56521b | bellard | z_stream zstream; |
38 | 3c56521b | bellard | } BDRVCloopState; |
39 | 3c56521b | bellard | |
40 | 3c56521b | bellard | static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) |
41 | 3c56521b | bellard | { |
42 | 3c56521b | bellard | const char* magic_version_2_0="#!/bin/sh\n" |
43 | 3c56521b | bellard | "#V2.0 Format\n"
|
44 | 3c56521b | bellard | "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
|
45 | 3c56521b | bellard | int length=strlen(magic_version_2_0);
|
46 | 3c56521b | bellard | if(length>buf_size)
|
47 | 3c56521b | bellard | length=buf_size; |
48 | 3c56521b | bellard | if(!memcmp(magic_version_2_0,buf,length))
|
49 | 3c56521b | bellard | return 2; |
50 | 3c56521b | bellard | return 0; |
51 | 3c56521b | bellard | } |
52 | 3c56521b | bellard | |
53 | 20be49e4 | Christoph Hellwig | static int cloop_open(BlockDriverState *bs, int flags) |
54 | 3c56521b | bellard | { |
55 | 3c56521b | bellard | BDRVCloopState *s = bs->opaque; |
56 | 3c56521b | bellard | uint32_t offsets_size,max_compressed_block_size=1,i;
|
57 | 3c56521b | bellard | |
58 | 3c56521b | bellard | bs->read_only = 1;
|
59 | 3c56521b | bellard | |
60 | 3c56521b | bellard | /* read header */
|
61 | 20be49e4 | Christoph Hellwig | if (bdrv_pread(bs->file, 128, &s->block_size, 4) < 4) { |
62 | c94304be | Christoph Hellwig | goto cloop_close;
|
63 | 3c56521b | bellard | } |
64 | c94304be | Christoph Hellwig | s->block_size = be32_to_cpu(s->block_size); |
65 | c94304be | Christoph Hellwig | |
66 | 20be49e4 | Christoph Hellwig | if (bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4) < 4) { |
67 | c94304be | Christoph Hellwig | goto cloop_close;
|
68 | c94304be | Christoph Hellwig | } |
69 | c94304be | Christoph Hellwig | s->n_blocks = be32_to_cpu(s->n_blocks); |
70 | 3c56521b | bellard | |
71 | 3c56521b | bellard | /* read offsets */
|
72 | c94304be | Christoph Hellwig | offsets_size = s->n_blocks * sizeof(uint64_t);
|
73 | c94304be | Christoph Hellwig | s->offsets = qemu_malloc(offsets_size); |
74 | 20be49e4 | Christoph Hellwig | if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) < |
75 | 20be49e4 | Christoph Hellwig | offsets_size) { |
76 | 3c56521b | bellard | goto cloop_close;
|
77 | c94304be | Christoph Hellwig | } |
78 | 3c56521b | bellard | for(i=0;i<s->n_blocks;i++) { |
79 | 3c56521b | bellard | s->offsets[i]=be64_to_cpu(s->offsets[i]); |
80 | 3c56521b | bellard | if(i>0) { |
81 | 3c56521b | bellard | uint32_t size=s->offsets[i]-s->offsets[i-1];
|
82 | 3c56521b | bellard | if(size>max_compressed_block_size)
|
83 | 3c56521b | bellard | max_compressed_block_size=size; |
84 | 3c56521b | bellard | } |
85 | 3c56521b | bellard | } |
86 | 3c56521b | bellard | |
87 | 3c56521b | bellard | /* initialize zlib engine */
|
88 | 3ec88e80 | aliguori | s->compressed_block = qemu_malloc(max_compressed_block_size+1);
|
89 | 3ec88e80 | aliguori | s->uncompressed_block = qemu_malloc(s->block_size); |
90 | 3c56521b | bellard | if(inflateInit(&s->zstream) != Z_OK)
|
91 | 3c56521b | bellard | goto cloop_close;
|
92 | 3c56521b | bellard | s->current_block=s->n_blocks; |
93 | 3b46e624 | ths | |
94 | 3c56521b | bellard | s->sectors_per_block = s->block_size/512;
|
95 | 3c56521b | bellard | bs->total_sectors = s->n_blocks*s->sectors_per_block; |
96 | 3c56521b | bellard | return 0; |
97 | c94304be | Christoph Hellwig | |
98 | c94304be | Christoph Hellwig | cloop_close:
|
99 | c94304be | Christoph Hellwig | return -1; |
100 | 3c56521b | bellard | } |
101 | 3c56521b | bellard | |
102 | 20be49e4 | Christoph Hellwig | static inline int cloop_read_block(BlockDriverState *bs, int block_num) |
103 | 3c56521b | bellard | { |
104 | 20be49e4 | Christoph Hellwig | BDRVCloopState *s = bs->opaque; |
105 | 20be49e4 | Christoph Hellwig | |
106 | 3c56521b | bellard | if(s->current_block != block_num) {
|
107 | 3c56521b | bellard | int ret;
|
108 | 3c56521b | bellard | uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
|
109 | 3b46e624 | ths | |
110 | 20be49e4 | Christoph Hellwig | ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block, |
111 | 20be49e4 | Christoph Hellwig | bytes); |
112 | 5fafdf24 | ths | if (ret != bytes)
|
113 | 3c56521b | bellard | return -1; |
114 | 5fafdf24 | ths | |
115 | 3c56521b | bellard | s->zstream.next_in = s->compressed_block; |
116 | 3c56521b | bellard | s->zstream.avail_in = bytes; |
117 | 3c56521b | bellard | s->zstream.next_out = s->uncompressed_block; |
118 | 3c56521b | bellard | s->zstream.avail_out = s->block_size; |
119 | 3c56521b | bellard | ret = inflateReset(&s->zstream); |
120 | 3c56521b | bellard | if(ret != Z_OK)
|
121 | 3c56521b | bellard | return -1; |
122 | 3c56521b | bellard | ret = inflate(&s->zstream, Z_FINISH); |
123 | 3c56521b | bellard | if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
|
124 | 3c56521b | bellard | return -1; |
125 | 5fafdf24 | ths | |
126 | 3c56521b | bellard | s->current_block = block_num; |
127 | 3c56521b | bellard | } |
128 | 3c56521b | bellard | return 0; |
129 | 3c56521b | bellard | } |
130 | 3c56521b | bellard | |
131 | 5fafdf24 | ths | static int cloop_read(BlockDriverState *bs, int64_t sector_num, |
132 | 3c56521b | bellard | uint8_t *buf, int nb_sectors)
|
133 | 3c56521b | bellard | { |
134 | 3c56521b | bellard | BDRVCloopState *s = bs->opaque; |
135 | 3c56521b | bellard | int i;
|
136 | 3c56521b | bellard | |
137 | 3c56521b | bellard | for(i=0;i<nb_sectors;i++) { |
138 | 3c56521b | bellard | uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block), |
139 | 3c56521b | bellard | block_num=(sector_num+i)/s->sectors_per_block; |
140 | 20be49e4 | Christoph Hellwig | if(cloop_read_block(bs, block_num) != 0) |
141 | 3c56521b | bellard | return -1; |
142 | 3c56521b | bellard | memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512); |
143 | 3c56521b | bellard | } |
144 | 3c56521b | bellard | return 0; |
145 | 3c56521b | bellard | } |
146 | 3c56521b | bellard | |
147 | 3c56521b | bellard | static void cloop_close(BlockDriverState *bs) |
148 | 3c56521b | bellard | { |
149 | 3c56521b | bellard | BDRVCloopState *s = bs->opaque; |
150 | 585d0ed9 | bellard | if(s->n_blocks>0) |
151 | 585d0ed9 | bellard | free(s->offsets); |
152 | 3c56521b | bellard | free(s->compressed_block); |
153 | 3c56521b | bellard | free(s->uncompressed_block); |
154 | 3c56521b | bellard | inflateEnd(&s->zstream); |
155 | 3c56521b | bellard | } |
156 | 3c56521b | bellard | |
157 | 5efa9d5a | Anthony Liguori | static BlockDriver bdrv_cloop = {
|
158 | e60f469c | aurel32 | .format_name = "cloop",
|
159 | e60f469c | aurel32 | .instance_size = sizeof(BDRVCloopState),
|
160 | e60f469c | aurel32 | .bdrv_probe = cloop_probe, |
161 | 20be49e4 | Christoph Hellwig | .bdrv_open = cloop_open, |
162 | e60f469c | aurel32 | .bdrv_read = cloop_read, |
163 | e60f469c | aurel32 | .bdrv_close = cloop_close, |
164 | 3c56521b | bellard | }; |
165 | 5efa9d5a | Anthony Liguori | |
166 | 5efa9d5a | Anthony Liguori | static void bdrv_cloop_init(void) |
167 | 5efa9d5a | Anthony Liguori | { |
168 | 5efa9d5a | Anthony Liguori | bdrv_register(&bdrv_cloop); |
169 | 5efa9d5a | Anthony Liguori | } |
170 | 5efa9d5a | Anthony Liguori | |
171 | 5efa9d5a | Anthony Liguori | block_init(bdrv_cloop_init); |