wok view qemu/stuff/cloop.u @ rev 17989

qemu: apply cloop.u
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Apr 23 13:30:18 2015 +0200 (2015-04-23)
parents 19bb7af3735f
children 9375c1de578d
line source
1 --- block/cloop.c
2 +++ block/cloop.c
3 @@ -29,11 +29,85 @@
4 /* Maximum compressed block size */
5 #define MAX_BLOCK_SIZE (64 * 1024 * 1024)
7 +typedef struct cloop_tail {
8 + uint32_t table_size;
9 + uint32_t index_size;
10 + uint32_t num_blocks;
11 +} cloop_tail;
12 +
13 +typedef struct block_info {
14 + uint64_t offset; /* 64-bit offsets of compressed block */
15 + uint32_t size; /* 32-bit compressed block size */
16 + uint32_t optidx; /* 32-bit index number */
17 +} block_info;
18 +
19 +static inline int build_index(block_info *offsets, unsigned long n)
20 +{
21 + uint32_t *ofs32 = (uint32_t *) offsets;
22 + uint64_t *ofs64 = (uint64_t *) offsets;
23 +
24 + if (ofs32[0] == 0) {
25 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
26 + while (n--) {
27 + offsets[n].offset = be64_to_cpu(offsets[n].offset);
28 + offsets[n].size = ntohl(offsets[n].size);
29 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
30 + return n+1;
31 + }
32 + }
33 + else { /* V2.0 */
34 + uint64_t last = be64_to_cpu(ofs64[n - 1]);
35 + while (n--) {
36 + offsets[n].size = last -
37 + (offsets[n].offset = be64_to_cpu(ofs64[n]));
38 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
39 + return n+1;
40 + last = offsets[n].offset;
41 + }
42 + }
43 + }
44 + else if (ofs32[1] == 0) { /* V1.0 */
45 + uint64_t last = le64_to_cpu(ofs64[n - 1]);
46 + while (n--) {
47 + offsets[n].size = last -
48 + (offsets[n].offset = le64_to_cpu(ofs64[n]));
49 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
50 + return n+1;
51 + last = offsets[n].offset;
52 + }
53 + }
54 + else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
55 + uint64_t last = ntohl(ofs32[n - 1]);
56 + while (n--) {
57 + offsets[n].size = last -
58 + (offsets[n].offset = ntohl(ofs32[n]));
59 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
60 + return n+1;
61 + last = offsets[n].offset;
62 + }
63 + }
64 + else { /* V3.0 */
65 + unsigned long i;
66 + uint64_t j;
67 +
68 + for (i = n; i-- > 0; ) {
69 + offsets[i].size = ntohl(ofs32[i]);
70 + if (offsets[i].size > 2 * MAX_BLOCK_SIZE)
71 + return i+1;
72 + }
73 + for (i = 0, j = 128 + 4 + 4; i < n; i++) {
74 + offsets[i].offset = j;
75 + j += offsets[i].size;
76 + }
77 + }
78 + return 0;
79 +}
80 +
81 typedef struct BDRVCloopState {
82 CoMutex lock;
83 uint32_t block_size;
84 uint32_t n_blocks;
85 - uint64_t *offsets;
86 + block_info *offsets;
87 uint32_t sectors_per_block;
88 uint32_t current_block;
89 uint8_t *compressed_block;
90 @@ -43,17 +117,21 @@
92 static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
93 {
94 - const char *magic_version_2_0 = "#!/bin/sh\n"
95 - "#V2.0 Format\n"
96 + static const uint8_t magic[] =
97 "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
98 - int length = strlen(magic_version_2_0);
99 - if (length > buf_size) {
100 - length = buf_size;
101 + int i, ret = 0, length = buf_size;
102 + uint8_t c;
103 +
104 + if (length > 127) {
105 + length = 127;
106 }
107 - if (!memcmp(magic_version_2_0, buf, length)) {
108 - return 2;
109 + for (i = 0; i < length - sizeof(magic) + 1; i++) {
110 + if (buf[i] != magic[0]) continue;
111 + if (strncmp(buf + i, magic, sizeof(magic) - 1)) continue;
112 + ret = 2;
113 + break;
114 }
115 - return 0;
116 + return ret;
117 }
119 static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
120 @@ -91,79 +169,104 @@
121 MAX_BLOCK_SIZE / (1024 * 1024));
122 return -EINVAL;
123 }
124 -
125 ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
126 if (ret < 0) {
127 return ret;
128 }
129 s->n_blocks = be32_to_cpu(s->n_blocks);
131 + /* initialize zlib engine */
132 + max_compressed_block_size = s->block_size + s->block_size/1000 + 12 + 4;
133 + s->compressed_block = g_malloc(max_compressed_block_size + 1);
134 + s->uncompressed_block = g_malloc(s->block_size);
135 +
136 + if (inflateInit(&s->zstream) != Z_OK) {
137 + ret = -EINVAL;
138 + goto fail;
139 + }
140 +
141 /* read offsets */
142 - if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
143 + if (s->n_blocks > (UINT32_MAX - 1) / sizeof(block_info)) {
144 /* Prevent integer overflow */
145 error_setg(errp, "n_blocks %u must be %zu or less",
146 s->n_blocks,
147 - (UINT32_MAX - 1) / sizeof(uint64_t));
148 + (UINT32_MAX - 1) / sizeof(block_info));
149 return -EINVAL;
150 }
151 - offsets_size = (s->n_blocks + 1) * sizeof(uint64_t);
152 - if (offsets_size > 512 * 1024 * 1024) {
153 - /* Prevent ridiculous offsets_size which causes memory allocation to
154 - * fail or overflows bdrv_pread() size. In practice the 512 MB
155 - * offsets[] limit supports 16 TB images at 256 KB block size.
156 - */
157 - error_setg(errp, "image requires too many offsets, "
158 - "try increasing block size");
159 - return -EINVAL;
160 - }
161 - s->offsets = g_malloc(offsets_size);
162 + if (s->n_blocks + 1 == 0) {
163 + cloop_tail tail;
164 + int64_t end = bdrv_getlength(bs->file);
165 + void *p;
166 + uint32_t toclen, len;
168 - ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
169 - if (ret < 0) {
170 - goto fail;
171 - }
172 -
173 - for (i = 0; i < s->n_blocks + 1; i++) {
174 - uint64_t size;
175 + ret = bdrv_pread(bs->file, end - sizeof(tail), &tail, sizeof(tail));
176 + if (ret < 0) {
177 + goto fail;
178 + }
180 - s->offsets[i] = be64_to_cpu(s->offsets[i]);
181 - if (i == 0) {
182 - continue;
183 + s->n_blocks = be32_to_cpu(tail.num_blocks);
184 + offsets_size = s->n_blocks * sizeof(block_info);
185 + if (offsets_size > 512 * 1024 * 1024) {
186 + /* Prevent ridiculous offsets_size which causes memory allocation to
187 + * fail or overflows bdrv_pread() size. In practice the 512 MB
188 + * offsets[] limit supports 16 TB images at 256 KB block size.
189 + */
190 + error_setg(errp, "image requires too many offsets, "
191 + "try increasing block size");
192 + return -EINVAL;
193 }
194 + len = be32_to_cpu(tail.table_size);
195 + toclen = (be32_to_cpu(tail.index_size) & 255) * s->n_blocks;
197 - if (s->offsets[i] < s->offsets[i - 1]) {
198 - error_setg(errp, "offsets not monotonically increasing at "
199 - "index %u, image file is corrupt", i);
200 + s->offsets = g_malloc(offsets_size);
201 + p = g_malloc(len);
202 +
203 + ret = bdrv_pread(bs->file, end - sizeof(tail) - len, p, len);
204 + if (ret < 0) {
205 + goto fail;
206 + }
207 + s->zstream.next_in = p;
208 + s->zstream.avail_in = len;
209 + s->zstream.next_out = s->offsets;
210 + s->zstream.avail_out = toclen;
211 + ret = inflateReset(&s->zstream);
212 + if (ret != Z_OK) {
213 ret = -EINVAL;
214 goto fail;
215 }
216 -
217 - size = s->offsets[i] - s->offsets[i - 1];
218 -
219 - /* Compressed blocks should be smaller than the uncompressed block size
220 - * but maybe compression performed poorly so the compressed block is
221 - * actually bigger. Clamp down on unrealistic values to prevent
222 - * ridiculous s->compressed_block allocation.
223 - */
224 - if (size > 2 * MAX_BLOCK_SIZE) {
225 - error_setg(errp, "invalid compressed block size at index %u, "
226 - "image file is corrupt", i);
227 + ret = inflate(&s->zstream, Z_FINISH);
228 + if (ret != Z_STREAM_END || s->zstream.total_out != toclen) {
229 ret = -EINVAL;
230 goto fail;
231 }
232 + g_free(p);
233 + }
234 + else {
235 + offsets_size = s->n_blocks * sizeof(block_info);
236 + if (offsets_size > 512 * 1024 * 1024) {
237 + /* Prevent ridiculous offsets_size which causes memory allocation to
238 + * fail or overflows bdrv_pread() size. In practice the 512 MB
239 + * offsets[] limit supports 16 TB images at 256 KB block size.
240 + */
241 + error_setg(errp, "image requires too many offsets, "
242 + "try increasing block size");
243 + return -EINVAL;
244 + }
245 + s->offsets = g_malloc(offsets_size);
247 - if (size > max_compressed_block_size) {
248 - max_compressed_block_size = size;
249 + ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
250 + if (ret < 0) {
251 + goto fail;
252 }
253 }
254 -
255 - /* initialize zlib engine */
256 - s->compressed_block = g_malloc(max_compressed_block_size + 1);
257 - s->uncompressed_block = g_malloc(s->block_size);
258 - if (inflateInit(&s->zstream) != Z_OK) {
259 + ret = build_index(s->offsets, s->n_blocks);
260 + if (ret) {
261 + error_setg(errp, "invalid compressed block size at index %u, "
262 + "image file is corrupt", ret-1);
263 ret = -EINVAL;
264 goto fail;
265 }
266 +
267 s->current_block = s->n_blocks;
269 s->sectors_per_block = s->block_size/512;
270 @@ -184,10 +287,10 @@
272 if (s->current_block != block_num) {
273 int ret;
274 - uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
275 + uint32_t bytes = s->offsets[block_num].size;
277 - ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
278 - bytes);
279 + ret = bdrv_pread(bs->file, s->offsets[block_num].offset,
280 + s->compressed_block, bytes);
281 if (ret != bytes) {
282 return -1;
283 }