wok annotate qemu/stuff/cloop.u @ rev 25438

Update some web_site
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Sep 01 11:12:31 2022 +0000 (2022-09-01)
parents cea6e929d21e
children
rev   line source
pascal@23682 1 --- block/cloop.c
pascal@23682 2 +++ block/cloop.c
pascal@23680 3 @@ -25,33 +25,206 @@
pascal@23680 4 #include "block/block_int.h"
pascal@23680 5 #include "qemu/module.h"
pascal@23680 6 #include <zlib.h>
pascal@23680 7 +#include <lzma.h>
pascal@23680 8 +
pascal@23680 9 +#define CLOOP_COMPRESSOR_ZLIB 0x0
pascal@23680 10 +#define CLOOP_COMPRESSOR_NONE 0x1
pascal@23680 11 +#define CLOOP_COMPRESSOR_XZ 0x2
pascal@23680 12 +#define CLOOP_COMPRESSOR_LZ4 0x3
pascal@23680 13 +#define CLOOP_COMPRESSOR_LZO 0x4
pascal@23680 14 +#define CLOOP_COMPRESSOR_ZSTD 0x5
pascal@23680 15 +#define CLOOP_COMPRESSOR_LINK 0xF
pascal@23680 16 +
pascal@23680 17 +#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60))
pascal@23680 18 +#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU)
pascal@23680 19
pascal@17989 20 /* Maximum compressed block size */
pascal@17989 21 #define MAX_BLOCK_SIZE (64 * 1024 * 1024)
pascal@17266 22
pascal@17266 23 +typedef struct cloop_tail {
pascal@17266 24 + uint32_t table_size;
pascal@17266 25 + uint32_t index_size;
pascal@17266 26 + uint32_t num_blocks;
pascal@17266 27 +} cloop_tail;
pascal@17266 28 +
pascal@23680 29 +#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF))
pascal@23680 30 +#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4)
pascal@23680 31 +
pascal@17266 32 +typedef struct block_info {
pascal@17266 33 + uint64_t offset; /* 64-bit offsets of compressed block */
pascal@17266 34 + uint32_t size; /* 32-bit compressed block size */
pascal@23680 35 + uint32_t flags; /* 32-bit compression flags */
pascal@17266 36 +} block_info;
pascal@17266 37 +
pascal@23680 38 +static inline int build_index(struct block_info *offsets, unsigned long n,
pascal@23680 39 + unsigned long block_size, unsigned global_flags)
pascal@17266 40 +{
pascal@17266 41 + uint32_t *ofs32 = (uint32_t *) offsets;
pascal@23680 42 + loff_t *ofs64 = (loff_t *) offsets;
pascal@23680 43 +
pascal@23680 44 + /* v3 64bits bug: v1 assumed */
pascal@23685 45 + unsigned long v3_64=(n+1)/2;
pascal@23680 46 + loff_t prev;
pascal@23680 47 +
pascal@23680 48 + if (ofs32[0] != 0 && ofs32[1] == 0) {
pascal@23685 49 + for (prev=le64_to_cpu(ofs64[v3_64]);
pascal@23680 50 + v3_64 > 0 && le64_to_cpu(ofs64[--v3_64]) < prev;
pascal@23680 51 + prev=le64_to_cpu(ofs64[v3_64]));
pascal@23680 52 + }
pascal@23680 53 +
pascal@17266 54 + if (ofs32[0] == 0) {
pascal@17266 55 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
pascal@17266 56 + while (n--) {
pascal@17266 57 + offsets[n].offset = be64_to_cpu(offsets[n].offset);
pascal@23685 58 + offsets[n].size = be32_to_cpu(offsets[n].size);
pascal@23680 59 + offsets[n].flags = 0;
pascal@17989 60 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
pascal@17989 61 + return n+1;
pascal@17266 62 + }
pascal@17266 63 + }
pascal@23680 64 + else { /* V2.0/V4.0 */
pascal@23680 65 + loff_t last = CLOOP_BLOCK_OFFSET(be64_to_cpu(ofs64[n]));
pascal@23680 66 + uint32_t flags;
pascal@23680 67 + unsigned long i = n;
pascal@23680 68 +
pascal@23680 69 + for (flags = 0; n-- ;) {
pascal@23680 70 + loff_t data = be64_to_cpu(ofs64[n]);
pascal@23680 71 +
pascal@17266 72 + offsets[n].size = last -
pascal@23680 73 + (offsets[n].offset = CLOOP_BLOCK_OFFSET(data));
pascal@17989 74 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
pascal@17989 75 + return n+1;
pascal@17266 76 + last = offsets[n].offset;
pascal@23680 77 + offsets[n].flags = CLOOP_BLOCK_FLAGS(data);
pascal@23680 78 + flags |= 1 << offsets[n].flags;
pascal@23680 79 + }
pascal@23680 80 + if (flags > 1) {
pascal@23680 81 + while (i--) {
pascal@23680 82 + if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) {
pascal@23680 83 + offsets[i] = offsets[offsets[i].offset];
pascal@23680 84 + }
pascal@23680 85 + }
pascal@17266 86 + }
pascal@17266 87 + }
pascal@17266 88 + }
pascal@23680 89 + else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */
pascal@23680 90 + loff_t last = le64_to_cpu(ofs64[n]);
pascal@17266 91 + while (n--) {
pascal@17266 92 + offsets[n].size = last -
pascal@17266 93 + (offsets[n].offset = le64_to_cpu(ofs64[n]));
pascal@17989 94 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
pascal@17989 95 + return n+1;
pascal@17266 96 + last = offsets[n].offset;
pascal@23680 97 + offsets[n].flags = 0;
pascal@17266 98 + }
pascal@17266 99 + }
pascal@23685 100 + else if (be32_to_cpu(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
pascal@23685 101 + loff_t last = be32_to_cpu(ofs32[n]);
pascal@17266 102 + while (n--) {
pascal@17266 103 + offsets[n].size = last -
pascal@23685 104 + (offsets[n].offset = be32_to_cpu(ofs32[n]));
pascal@17989 105 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
pascal@17989 106 + return n+1;
pascal@17266 107 + last = offsets[n].offset;
pascal@23680 108 + offsets[n].flags = 0;
pascal@17266 109 + }
pascal@17266 110 + }
pascal@17266 111 + else { /* V3.0 */
pascal@17266 112 + unsigned long i;
pascal@23680 113 + loff_t j;
pascal@17266 114 +
pascal@23680 115 + v3_64 = (ofs32[1] == 0) ? 2 : 1;
pascal@17989 116 + for (i = n; i-- > 0; ) {
pascal@23685 117 + offsets[i].size = be32_to_cpu(ofs32[i*v3_64]);
pascal@23680 118 + if ((offsets[i].size & 0x80000000) == 0 &&
pascal@23680 119 + offsets[i].size > 2 * MAX_BLOCK_SIZE)
pascal@17989 120 + return i+1;
pascal@17989 121 + }
pascal@17266 122 + for (i = 0, j = 128 + 4 + 4; i < n; i++) {
pascal@17266 123 + offsets[i].offset = j;
pascal@23680 124 + offsets[i].flags = global_flags;
pascal@23680 125 + if (offsets[i].size == 0xFFFFFFFF) {
pascal@23680 126 + offsets[i].flags = CLOOP_COMPRESSOR_NONE;
pascal@23680 127 + offsets[i].size = block_size;
pascal@23680 128 + }
pascal@23680 129 + if ((offsets[i].size & 0x80000000) == 0) {
pascal@23680 130 + j += offsets[i].size;
pascal@23680 131 + }
pascal@23680 132 + }
pascal@23680 133 + for (i = 0; i < n; i++) {
pascal@18828 134 + if (offsets[i].size & 0x80000000) {
pascal@23680 135 + offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF];
pascal@18828 136 + }
pascal@17266 137 + }
pascal@17266 138 + }
pascal@17989 139 + return 0;
pascal@17266 140 +}
pascal@17266 141 +
pascal@17266 142 typedef struct BDRVCloopState {
pascal@17266 143 CoMutex lock;
pascal@17266 144 uint32_t block_size;
pascal@17266 145 uint32_t n_blocks;
pascal@17266 146 - uint64_t *offsets;
pascal@17266 147 + block_info *offsets;
pascal@17266 148 uint32_t sectors_per_block;
pascal@17266 149 uint32_t current_block;
pascal@17266 150 uint8_t *compressed_block;
pascal@23680 151 uint8_t *uncompressed_block;
pascal@23680 152 z_stream zstream;
pascal@23680 153 + int global_flags;
pascal@23680 154 } BDRVCloopState;
pascal@17266 155
pascal@17266 156 static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
pascal@17266 157 {
pascal@17266 158 - const char *magic_version_2_0 = "#!/bin/sh\n"
pascal@17266 159 - "#V2.0 Format\n"
pascal@17266 160 + static const uint8_t magic[] =
pascal@17266 161 "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
pascal@17266 162 - int length = strlen(magic_version_2_0);
pascal@17266 163 - if (length > buf_size) {
pascal@17266 164 - length = buf_size;
pascal@23685 165 + int ret = 0, length = buf_size;
pascal@23685 166 + int i;
pascal@17266 167 +
pascal@17266 168 + if (length > 127) {
pascal@17266 169 + length = 127;
pascal@23680 170 + }
pascal@17266 171 + for (i = 0; i < length - sizeof(magic) + 1; i++) {
pascal@17266 172 + if (buf[i] != magic[0]) continue;
pascal@23685 173 + if (memcmp(buf + i, magic, sizeof(magic) - 1)) continue;
pascal@17266 174 + ret = 2;
pascal@17266 175 + break;
pascal@17266 176 }
pascal@23680 177 - if (!memcmp(magic_version_2_0, buf, length)) {
pascal@23680 178 - return 2;
pascal@17266 179 + return ret;
pascal@23680 180 +}
pascal@23680 181 +
pascal@23685 182 +static uint32_t cloop_unpack(BDRVCloopState *s, int flag)
pascal@23680 183 +{
pascal@23680 184 + int ret;
pascal@23680 185 + size_t src_pos;
pascal@23680 186 + size_t dest_pos;
pascal@23680 187 + uint64_t memlimit;
pascal@23766 188 + uint32_t outlen = s->zstream.avail_out;
pascal@23680 189 +
pascal@23680 190 + switch (flag) {
pascal@23680 191 + case CLOOP_COMPRESSOR_ZLIB:
pascal@23680 192 + ret = inflateReset(&s->zstream);
pascal@23680 193 + if (ret != Z_OK) {
pascal@23680 194 + return 0;
pascal@23680 195 + }
pascal@23680 196 + ret = inflate(&s->zstream, Z_FINISH);
pascal@23680 197 + if (ret != Z_STREAM_END || s->zstream.total_out != outlen) {
pascal@23680 198 + return 0;
pascal@23680 199 + }
pascal@23680 200 + return outlen;
pascal@23680 201 + case CLOOP_COMPRESSOR_NONE:
pascal@23680 202 + memcpy(s->zstream.next_out, s->zstream.next_in, s->zstream.avail_in);
pascal@23680 203 + return s->zstream.avail_in;
pascal@23680 204 + case CLOOP_COMPRESSOR_XZ:
pascal@23680 205 + src_pos = 0;
pascal@23680 206 + dest_pos = 0;
pascal@23680 207 + memlimit = 32*1024*1024;
pascal@23680 208 + ret = lzma_stream_buffer_decode(&memlimit, 0, NULL, s->zstream.next_in, &src_pos,
pascal@23680 209 + s->zstream.avail_in, s->zstream.next_out, &dest_pos, s->zstream.total_out);
pascal@23680 210 +
pascal@23680 211 + if(ret != LZMA_OK || s->zstream.avail_in != (int) src_pos) {
pascal@23680 212 + return 0;
pascal@23680 213 + }
pascal@23680 214 + return dest_pos;
pascal@23680 215 }
pascal@23680 216 return 0;
pascal@17266 217 }
pascal@23696 218 @@ -60,7 +233,7 @@
pascal@23696 219 Error **errp)
pascal@23696 220 {
pascal@23696 221 BDRVCloopState *s = bs->opaque;
pascal@23696 222 - uint32_t offsets_size, max_compressed_block_size = 1, i;
pascal@23696 223 + uint32_t offsets_size, max_compressed_block_size = 1;
pascal@23696 224 int ret;
pascal@23696 225
pascal@23696 226 bs->read_only = 1;
pascal@23680 227 @@ -91,79 +264,92 @@
pascal@17989 228 MAX_BLOCK_SIZE / (1024 * 1024));
pascal@17989 229 return -EINVAL;
pascal@17989 230 }
pascal@17989 231 -
pascal@17989 232 ret = bdrv_pread(bs->file, 128 + 4, &s->n_blocks, 4);
pascal@17989 233 if (ret < 0) {
pascal@17989 234 return ret;
pascal@17266 235 }
pascal@17266 236 s->n_blocks = be32_to_cpu(s->n_blocks);
pascal@17266 237
pascal@17990 238 - /* read offsets */
pascal@17989 239 - if (s->n_blocks > (UINT32_MAX - 1) / sizeof(uint64_t)) {
pascal@17990 240 - /* Prevent integer overflow */
pascal@17990 241 - error_setg(errp, "n_blocks %u must be %zu or less",
pascal@17990 242 - s->n_blocks,
pascal@17989 243 - (UINT32_MAX - 1) / sizeof(uint64_t));
pascal@17990 244 - return -EINVAL;
pascal@17990 245 - }
pascal@17989 246 - offsets_size = (s->n_blocks + 1) * sizeof(uint64_t);
pascal@17989 247 - if (offsets_size > 512 * 1024 * 1024) {
pascal@17989 248 - /* Prevent ridiculous offsets_size which causes memory allocation to
pascal@17989 249 - * fail or overflows bdrv_pread() size. In practice the 512 MB
pascal@17989 250 - * offsets[] limit supports 16 TB images at 256 KB block size.
pascal@17989 251 - */
pascal@17989 252 - error_setg(errp, "image requires too many offsets, "
pascal@17989 253 - "try increasing block size");
pascal@17989 254 - return -EINVAL;
pascal@17989 255 - }
pascal@17989 256 - s->offsets = g_malloc(offsets_size);
pascal@17990 257 + /* initialize zlib engine */
pascal@17990 258 + max_compressed_block_size = s->block_size + s->block_size/1000 + 12 + 4;
pascal@17990 259 + s->compressed_block = g_malloc(max_compressed_block_size + 1);
pascal@17990 260 + s->uncompressed_block = g_malloc(s->block_size);
pascal@17990 261
pascal@17990 262 - ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
pascal@17990 263 - if (ret < 0) {
pascal@17990 264 + if (inflateInit(&s->zstream) != Z_OK) {
pascal@17990 265 + ret = -EINVAL;
pascal@17990 266 goto fail;
pascal@17990 267 }
pascal@17990 268
pascal@17990 269 - for (i = 0; i < s->n_blocks + 1; i++) {
pascal@17990 270 - uint64_t size;
pascal@17990 271 + /* read offsets */
pascal@17266 272 + if (s->n_blocks + 1 == 0) {
pascal@17266 273 + cloop_tail tail;
pascal@17266 274 + int64_t end = bdrv_getlength(bs->file);
pascal@17266 275 + void *p;
pascal@17266 276 + uint32_t toclen, len;
pascal@17989 277
pascal@17990 278 - s->offsets[i] = be64_to_cpu(s->offsets[i]);
pascal@17990 279 - if (i == 0) {
pascal@17990 280 - continue;
pascal@17266 281 + ret = bdrv_pread(bs->file, end - sizeof(tail), &tail, sizeof(tail));
pascal@17266 282 + if (ret < 0) {
pascal@17266 283 + goto fail;
pascal@17990 284 }
pascal@17989 285
pascal@17990 286 - if (s->offsets[i] < s->offsets[i - 1]) {
pascal@17990 287 - error_setg(errp, "offsets not monotonically increasing at "
pascal@17990 288 - "index %u, image file is corrupt", i);
pascal@17990 289 - ret = -EINVAL;
pascal@17990 290 - goto fail;
pascal@17266 291 + s->n_blocks = be32_to_cpu(tail.num_blocks);
pascal@17266 292 + offsets_size = s->n_blocks * sizeof(block_info);
pascal@17989 293 + if (offsets_size > 512 * 1024 * 1024) {
pascal@17989 294 + /* Prevent ridiculous offsets_size which causes memory allocation to
pascal@17989 295 + * fail or overflows bdrv_pread() size. In practice the 512 MB
pascal@17989 296 + * offsets[] limit supports 16 TB images at 256 KB block size.
pascal@17989 297 + */
pascal@17989 298 + error_setg(errp, "image requires too many offsets, "
pascal@17989 299 + "try increasing block size");
pascal@17989 300 + return -EINVAL;
pascal@17989 301 }
pascal@17266 302 + len = be32_to_cpu(tail.table_size);
pascal@23680 303 + toclen = CLOOP3_INDEX_SIZE(be32_to_cpu(tail.index_size)) * s->n_blocks;
pascal@23680 304 + s->global_flags = CLOOP3_BLOCKS_FLAGS(be32_to_cpu(tail.index_size));
pascal@17989 305
pascal@17990 306 - size = s->offsets[i] - s->offsets[i - 1];
pascal@17266 307 + s->offsets = g_malloc(offsets_size);
pascal@17266 308 + p = g_malloc(len);
pascal@17990 309
pascal@17990 310 - /* Compressed blocks should be smaller than the uncompressed block size
pascal@17990 311 - * but maybe compression performed poorly so the compressed block is
pascal@17990 312 - * actually bigger. Clamp down on unrealistic values to prevent
pascal@17990 313 - * ridiculous s->compressed_block allocation.
pascal@17990 314 - */
pascal@17990 315 - if (size > 2 * MAX_BLOCK_SIZE) {
pascal@17990 316 - error_setg(errp, "invalid compressed block size at index %u, "
pascal@17990 317 - "image file is corrupt", i);
pascal@17266 318 + ret = bdrv_pread(bs->file, end - sizeof(tail) - len, p, len);
pascal@17266 319 + if (ret < 0) {
pascal@17266 320 + goto fail;
pascal@17266 321 + }
pascal@17266 322 + s->zstream.next_in = p;
pascal@17266 323 + s->zstream.avail_in = len;
pascal@17266 324 + s->zstream.next_out = s->offsets;
pascal@17266 325 + s->zstream.avail_out = toclen;
pascal@23680 326 + if (cloop_unpack(s, s->global_flags) == 0) {
pascal@17989 327 ret = -EINVAL;
pascal@17989 328 goto fail;
pascal@17989 329 }
pascal@17266 330 + g_free(p);
pascal@23680 331 + }
pascal@17266 332 + else {
pascal@17266 333 + offsets_size = s->n_blocks * sizeof(block_info);
pascal@17989 334 + if (offsets_size > 512 * 1024 * 1024) {
pascal@17989 335 + /* Prevent ridiculous offsets_size which causes memory allocation to
pascal@17989 336 + * fail or overflows bdrv_pread() size. In practice the 512 MB
pascal@17989 337 + * offsets[] limit supports 16 TB images at 256 KB block size.
pascal@17989 338 + */
pascal@17989 339 + error_setg(errp, "image requires too many offsets, "
pascal@17989 340 + "try increasing block size");
pascal@17989 341 + return -EINVAL;
pascal@17989 342 + }
pascal@17266 343 + s->offsets = g_malloc(offsets_size);
pascal@17266 344
pascal@23680 345 - if (size > max_compressed_block_size) {
pascal@23680 346 - max_compressed_block_size = size;
pascal@23680 347 + ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size);
pascal@23680 348 + if (ret < 0) {
pascal@23680 349 + goto fail;
pascal@23680 350 }
pascal@23680 351 }
pascal@23680 352 -
pascal@17266 353 - /* initialize zlib engine */
pascal@17266 354 - s->compressed_block = g_malloc(max_compressed_block_size + 1);
pascal@17266 355 - s->uncompressed_block = g_malloc(s->block_size);
pascal@17266 356 - if (inflateInit(&s->zstream) != Z_OK) {
pascal@23680 357 + ret = build_index(s->offsets, s->n_blocks, s->block_size, s->global_flags);
pascal@17989 358 + if (ret) {
pascal@17989 359 + error_setg(errp, "invalid compressed block size at index %u, "
pascal@17989 360 + "image file is corrupt", ret-1);
pascal@17989 361 ret = -EINVAL;
pascal@17989 362 goto fail;
pascal@17266 363 }
pascal@17266 364 +
pascal@17266 365 s->current_block = s->n_blocks;
pascal@17266 366
pascal@17266 367 s->sectors_per_block = s->block_size/512;
pascal@23680 368 @@ -184,10 +370,10 @@
pascal@17266 369
pascal@17266 370 if (s->current_block != block_num) {
pascal@17266 371 int ret;
pascal@17266 372 - uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
pascal@17266 373 + uint32_t bytes = s->offsets[block_num].size;
pascal@17266 374
pascal@17266 375 - ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
pascal@17266 376 - bytes);
pascal@17266 377 + ret = bdrv_pread(bs->file, s->offsets[block_num].offset,
pascal@17266 378 + s->compressed_block, bytes);
pascal@17266 379 if (ret != bytes) {
pascal@17266 380 return -1;
pascal@17266 381 }
pascal@23680 382 @@ -196,12 +382,7 @@
pascal@23680 383 s->zstream.avail_in = bytes;
pascal@23680 384 s->zstream.next_out = s->uncompressed_block;
pascal@23680 385 s->zstream.avail_out = s->block_size;
pascal@23680 386 - ret = inflateReset(&s->zstream);
pascal@23680 387 - if (ret != Z_OK) {
pascal@23680 388 - return -1;
pascal@23680 389 - }
pascal@23680 390 - ret = inflate(&s->zstream, Z_FINISH);
pascal@23680 391 - if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) {
pascal@23680 392 + if (cloop_unpack(s, s->offsets[block_num].flags) == 0) {
pascal@23680 393 return -1;
pascal@23680 394 }
pascal@23680 395
pascal@23682 396 --- block/Makefile.objs
pascal@23682 397 +++ block/Makefile.objs
pascal@23680 398 @@ -35,5 +35,5 @@
pascal@23680 399 gluster.o-libs := $(GLUSTERFS_LIBS)
pascal@23680 400 ssh.o-cflags := $(LIBSSH2_CFLAGS)
pascal@23680 401 ssh.o-libs := $(LIBSSH2_LIBS)
pascal@23680 402 -qcow.o-libs := -lz
pascal@23680 403 +qcow.o-libs := -lz -llzma
pascal@23680 404 linux-aio.o-libs := -laio
pascal@23762 405 --- block/cloop.c
pascal@23762 406 +++ block/cloop.c
pascal@23762 407 @@ -48,7 +48,6 @@
pascal@23762 408 } cloop_tail;
pascal@23762 409
pascal@23762 410 #define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF))
pascal@23762 411 -#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4)
pascal@23762 412
pascal@23762 413 typedef struct block_info {
pascal@23762 414 uint64_t offset; /* 64-bit offsets of compressed block */
pascal@23762 415 @@ -57,7 +56,7 @@
pascal@23762 416 } block_info;
pascal@23762 417
pascal@23762 418 static inline int build_index(struct block_info *offsets, unsigned long n,
pascal@23762 419 - unsigned long block_size, unsigned global_flags)
pascal@23762 420 + unsigned long block_size)
pascal@23762 421 {
pascal@23762 422 uint32_t *ofs32 = (uint32_t *) offsets;
pascal@23762 423 loff_t *ofs64 = (loff_t *) offsets;
pascal@23762 424 @@ -118,42 +117,44 @@
pascal@23762 425 offsets[n].flags = 0;
pascal@23762 426 }
pascal@23762 427 }
pascal@23762 428 - else if (be32_to_cpu(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
pascal@23762 429 - loff_t last = be32_to_cpu(ofs32[n]);
pascal@23762 430 - while (n--) {
pascal@23762 431 - offsets[n].size = last -
pascal@23762 432 - (offsets[n].offset = be32_to_cpu(ofs32[n]));
pascal@23762 433 - if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
pascal@23762 434 - return n+1;
pascal@23762 435 - last = offsets[n].offset;
pascal@23762 436 - offsets[n].flags = 0;
pascal@23762 437 - }
pascal@23762 438 - }
pascal@23762 439 - else { /* V3.0 */
pascal@23762 440 + else { /* V3.0 or V0.68 */
pascal@23762 441 unsigned long i;
pascal@23762 442 loff_t j;
pascal@23762 443
pascal@23762 444 - v3_64 = (ofs32[1] == 0) ? 2 : 1;
pascal@23762 445 + for (i = 0; i < n && be32_to_cpu(ofs32[i]) < be32_to_cpu(ofs32[i+1]); i++);
pascal@23762 446 + if (i == n && be32_to_cpu(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
pascal@23762 447 + loff_t last = be32_to_cpu(ofs32[n]);
pascal@23762 448 + while (n--) {
pascal@23762 449 + offsets[n].size = last -
pascal@23762 450 + (offsets[n].offset = be32_to_cpu(ofs32[n]));
pascal@23762 451 + if (offsets[n].size > 2 * MAX_BLOCK_SIZE)
pascal@23762 452 + return n+1;
pascal@23762 453 + last = offsets[n].offset;
pascal@23762 454 + offsets[n].flags = 0;
pascal@23762 455 + }
pascal@23762 456 + return 0;
pascal@23762 457 + }
pascal@23762 458 +
pascal@23762 459 + v3_64 = (ofs32[1] == 0);
pascal@23762 460 for (i = n; i-- > 0; ) {
pascal@23762 461 - offsets[i].size = be32_to_cpu(ofs32[i*v3_64]);
pascal@23762 462 - if ((offsets[i].size & 0x80000000) == 0 &&
pascal@23762 463 - offsets[i].size > 2 * MAX_BLOCK_SIZE)
pascal@23762 464 + offsets[i].size = be32_to_cpu(ofs32[i << v3_64]);
pascal@23762 465 + if (offsets[i].size == 0xFFFFFFFF) {
pascal@23762 466 + offsets[i].size = 0x10000000 | block_size;
pascal@23762 467 + }
pascal@23762 468 + offsets[i].flags = (offsets[i].size >> 28);
pascal@23762 469 + offsets[i].size &= 0x0FFFFFFF;
pascal@23762 470 + if (offsets[i].size > 2 * MAX_BLOCK_SIZE)
pascal@23762 471 return i+1;
pascal@23762 472 }
pascal@23762 473 for (i = 0, j = 128 + 4 + 4; i < n; i++) {
pascal@23762 474 offsets[i].offset = j;
pascal@23762 475 - offsets[i].flags = global_flags;
pascal@23762 476 - if (offsets[i].size == 0xFFFFFFFF) {
pascal@23762 477 - offsets[i].flags = CLOOP_COMPRESSOR_NONE;
pascal@23762 478 - offsets[i].size = block_size;
pascal@23762 479 - }
pascal@23762 480 - if ((offsets[i].size & 0x80000000) == 0) {
pascal@23762 481 + if (offsets[i].flags < 8) {
pascal@23762 482 j += offsets[i].size;
pascal@23762 483 }
pascal@23762 484 }
pascal@23762 485 for (i = 0; i < n; i++) {
pascal@23762 486 - if (offsets[i].size & 0x80000000) {
pascal@23762 487 - offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF];
pascal@23762 488 + if (offsets[i].flags >= 8) {
pascal@23762 489 + offsets[i] = offsets[offsets[i].size];
pascal@23762 490 }
pascal@23762 491 }
pascal@23762 492 }
pascal@23762 493 @@ -170,7 +171,6 @@
pascal@23762 494 uint8_t *compressed_block;
pascal@23762 495 uint8_t *uncompressed_block;
pascal@23762 496 z_stream zstream;
pascal@23762 497 - int global_flags;
pascal@23762 498 } BDRVCloopState;
pascal@23762 499
pascal@23762 500 static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
pascal@23762 501 @@ -305,7 +305,6 @@
pascal@23762 502 }
pascal@23762 503 len = be32_to_cpu(tail.table_size);
pascal@23762 504 toclen = CLOOP3_INDEX_SIZE(be32_to_cpu(tail.index_size)) * s->n_blocks;
pascal@23762 505 - s->global_flags = CLOOP3_BLOCKS_FLAGS(be32_to_cpu(tail.index_size));
pascal@23762 506
pascal@23762 507 s->offsets = g_malloc(offsets_size);
pascal@23762 508 p = g_malloc(len);
pascal@23762 509 @@ -316,9 +315,9 @@
pascal@23762 510 }
pascal@23762 511 s->zstream.next_in = p;
pascal@23762 512 s->zstream.avail_in = len;
pascal@23762 513 - s->zstream.next_out = s->offsets;
pascal@23762 514 + s->zstream.next_out = (void *) s->offsets;
pascal@23762 515 s->zstream.avail_out = toclen;
pascal@23762 516 - if (cloop_unpack(s, s->global_flags) == 0) {
pascal@23762 517 + if (cloop_unpack(s, CLOOP_COMPRESSOR_ZLIB) == 0) {
pascal@23762 518 ret = -EINVAL;
pascal@23762 519 goto fail;
pascal@23762 520 }
pascal@23762 521 @@ -342,7 +341,7 @@
pascal@23762 522 goto fail;
pascal@23762 523 }
pascal@23762 524 }
pascal@23762 525 - ret = build_index(s->offsets, s->n_blocks, s->block_size, s->global_flags);
pascal@23762 526 + ret = build_index(s->offsets, s->n_blocks, s->block_size);
pascal@23762 527 if (ret) {
pascal@23762 528 error_setg(errp, "invalid compressed block size at index %u, "
pascal@23762 529 "image file is corrupt", ret-1);