# HG changeset patch # User Pascal Bellard # Date 1414055203 -7200 # Node ID 1f00b27b3afbd14f6e4343ba73db84549de9afa0 # Parent 02f2b070806641e7eb31281d0417915b0090659e qemu: *any* cloop format support diff -r 02f2b0708066 -r 1f00b27b3afb qemu/receipt --- a/qemu/receipt Wed Oct 22 22:35:43 2014 +0300 +++ b/qemu/receipt Thu Oct 23 11:06:43 2014 +0200 @@ -12,7 +12,7 @@ TAGS="virtualization emulator" DEPENDS="alsa-lib gnutls libsdl bluez libtasn1 libsasl vde2 libcurl \ -attr util-linux-uuid libgio glib" +attr util-linux-uuid libgio glib libusb" BUILD_DEPENDS="gettext perl alsa-lib-dev gnutls-dev libsdl-dev bluez-dev \ libtasn1-dev vde2-dev curl-dev attr-dev util-linux-uuid-dev libgio-dev \ glib-dev autoconf automake libtool bison flex libusb-dev" @@ -20,7 +20,7 @@ # Rules to configure and make the package. compile_rules() { - cd $src + patch -p0 < $stuff/cloop.u TARGET="i386-softmmu, x86_64-softmmu, \ arm-softmmu, ppc-softmmu, mips-softmmu" diff -r 02f2b0708066 -r 1f00b27b3afb qemu/stuff/cloop.u --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qemu/stuff/cloop.u Thu Oct 23 11:06:43 2014 +0200 @@ -0,0 +1,212 @@ +--- block/cloop.c ++++ block/cloop.c +@@ -26,11 +26,78 @@ + #include "qemu/module.h" + #include + ++typedef struct cloop_tail { ++ uint32_t table_size; ++ uint32_t index_size; ++ uint32_t num_blocks; ++} cloop_tail; ++ ++typedef struct block_info { ++ uint64_t offset; /* 64-bit offsets of compressed block */ ++ uint32_t size; /* 32-bit compressed block size */ ++ uint32_t optidx; /* 32-bit index number */ ++} block_info; ++ ++static inline void build_index(block_info *offsets, unsigned long n) ++{ ++ uint32_t *ofs32 = (uint32_t *) offsets; ++ uint64_t *ofs64 = (uint64_t *) offsets; ++ ++ if (ofs32[0] == 0) { ++ if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */ ++ while (n--) { ++ offsets[n].offset = be64_to_cpu(offsets[n].offset); ++ offsets[n].size = ntohl(offsets[n].size); ++ } ++ // return (char *) "128BE accelerated knoppix 1.0"; ++ } ++ else { /* V2.0 */ ++ uint64_t last = be64_to_cpu(ofs64[n]); ++ while (n--) { ++ offsets[n].size = last - ++ (offsets[n].offset = be64_to_cpu(ofs64[n])); ++ last = offsets[n].offset; ++ } ++ // return (char *) "64BE v2.0"; ++ } ++ } ++ else if (ofs32[1] == 0) { /* V1.0 */ ++ uint64_t last = le64_to_cpu(ofs64[n]); ++ while (n--) { ++ offsets[n].size = last - ++ (offsets[n].offset = le64_to_cpu(ofs64[n])); ++ last = offsets[n].offset; ++ } ++ // return (char *) "64LE v1.0"; ++ } ++ else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ ++ uint64_t last = ntohl(ofs32[n]); ++ while (n--) { ++ offsets[n].size = last - ++ (offsets[n].offset = ntohl(ofs32[n])); ++ last = offsets[n].offset; ++ } ++ // return (char *) "32BE v0.68"; ++ } ++ else { /* V3.0 */ ++ unsigned long i; ++ uint64_t j; ++ ++ for (i = n; i-- > 0; ) ++ offsets[i].size = ntohl(ofs32[i]); ++ for (i = 0, j = 128 + 4 + 4; i < n; i++) { ++ offsets[i].offset = j; ++ j += offsets[i].size; ++ } ++ // return (char *) "32BE v3.0"; ++ } ++} ++ + typedef struct BDRVCloopState { + CoMutex lock; + uint32_t block_size; + uint32_t n_blocks; +- uint64_t *offsets; ++ block_info *offsets; + uint32_t sectors_per_block; + uint32_t current_block; + uint8_t *compressed_block; +@@ -40,17 +107,21 @@ + + static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) + { +- const char *magic_version_2_0 = "#!/bin/sh\n" +- "#V2.0 Format\n" ++ static const uint8_t magic[] = + "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n"; +- int length = strlen(magic_version_2_0); +- if (length > buf_size) { +- length = buf_size; ++ int i, ret = 0, length = buf_size; ++ uint8_t c; ++ ++ if (length > 127) { ++ length = 127; + } +- if (!memcmp(magic_version_2_0, buf, length)) { +- return 2; ++ for (i = 0; i < length - sizeof(magic) + 1; i++) { ++ if (buf[i] != magic[0]) continue; ++ if (strncmp(buf + i, magic, sizeof(magic) - 1)) continue; ++ ret = 2; ++ break; + } +- return 0; ++ return ret; + } + + static int cloop_open(BlockDriverState *bs, QDict *options, int flags) +@@ -74,32 +145,67 @@ + } + s->n_blocks = be32_to_cpu(s->n_blocks); + +- /* read offsets */ +- offsets_size = s->n_blocks * sizeof(uint64_t); +- s->offsets = g_malloc(offsets_size); ++ /* initialize zlib engine */ ++ max_compressed_block_size = s->block_size + s->block_size/1000 + 12 + 4; ++ s->compressed_block = g_malloc(max_compressed_block_size + 1); ++ s->uncompressed_block = g_malloc(s->block_size); + +- ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size); +- if (ret < 0) { ++ if (inflateInit(&s->zstream) != Z_OK) { ++ ret = -EINVAL; + goto fail; + } + +- for(i=0;in_blocks;i++) { +- s->offsets[i] = be64_to_cpu(s->offsets[i]); +- if (i > 0) { +- uint32_t size = s->offsets[i] - s->offsets[i - 1]; +- if (size > max_compressed_block_size) { +- max_compressed_block_size = size; +- } ++ /* read offsets */ ++ if (s->n_blocks + 1 == 0) { ++ cloop_tail tail; ++ int64_t end = bdrv_getlength(bs->file); ++ void *p; ++ uint32_t toclen, len; ++ ++ ret = bdrv_pread(bs->file, end - sizeof(tail), &tail, sizeof(tail)); ++ if (ret < 0) { ++ goto fail; + } ++ ++ s->n_blocks = be32_to_cpu(tail.num_blocks); ++ offsets_size = s->n_blocks * sizeof(block_info); ++ len = be32_to_cpu(tail.table_size); ++ toclen = (be32_to_cpu(tail.index_size) & 255) * s->n_blocks; ++ ++ s->offsets = g_malloc(offsets_size); ++ p = g_malloc(len); ++ ++ ret = bdrv_pread(bs->file, end - sizeof(tail) - len, p, len); ++ if (ret < 0) { ++ goto fail; ++ } ++ s->zstream.next_in = p; ++ s->zstream.avail_in = len; ++ s->zstream.next_out = s->offsets; ++ s->zstream.avail_out = toclen; ++ ret = inflateReset(&s->zstream); ++ if (ret != Z_OK) { ++ ret = -EINVAL; ++ goto fail; ++ } ++ ret = inflate(&s->zstream, Z_FINISH); ++ if (ret != Z_STREAM_END || s->zstream.total_out != toclen) { ++ ret = -EINVAL; ++ goto fail; ++ } ++ g_free(p); + } ++ else { ++ offsets_size = s->n_blocks * sizeof(block_info); ++ s->offsets = g_malloc(offsets_size); + +- /* initialize zlib engine */ +- s->compressed_block = g_malloc(max_compressed_block_size + 1); +- s->uncompressed_block = g_malloc(s->block_size); +- if (inflateInit(&s->zstream) != Z_OK) { +- ret = -EINVAL; +- goto fail; ++ ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size); ++ if (ret < 0) { ++ goto fail; ++ } + } ++ build_index(s->offsets, s->n_blocks); ++ + s->current_block = s->n_blocks; + + s->sectors_per_block = s->block_size/512; +@@ -120,10 +226,10 @@ + + if (s->current_block != block_num) { + int ret; +- uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num]; ++ uint32_t bytes = s->offsets[block_num].size; + +- ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block, +- bytes); ++ ret = bdrv_pread(bs->file, s->offsets[block_num].offset, ++ s->compressed_block, bytes); + if (ret != bytes) { + return -1; + }