wok diff qemu/stuff/cloop.u @ rev 17266
qemu: *any* cloop format support
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Thu Oct 23 11:06:43 2014 +0200 (2014-10-23) |
parents | |
children | 19bb7af3735f |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/qemu/stuff/cloop.u Thu Oct 23 11:06:43 2014 +0200 1.3 @@ -0,0 +1,212 @@ 1.4 +--- block/cloop.c 1.5 ++++ block/cloop.c 1.6 +@@ -26,11 +26,78 @@ 1.7 + #include "qemu/module.h" 1.8 + #include <zlib.h> 1.9 + 1.10 ++typedef struct cloop_tail { 1.11 ++ uint32_t table_size; 1.12 ++ uint32_t index_size; 1.13 ++ uint32_t num_blocks; 1.14 ++} cloop_tail; 1.15 ++ 1.16 ++typedef struct block_info { 1.17 ++ uint64_t offset; /* 64-bit offsets of compressed block */ 1.18 ++ uint32_t size; /* 32-bit compressed block size */ 1.19 ++ uint32_t optidx; /* 32-bit index number */ 1.20 ++} block_info; 1.21 ++ 1.22 ++static inline void build_index(block_info *offsets, unsigned long n) 1.23 ++{ 1.24 ++ uint32_t *ofs32 = (uint32_t *) offsets; 1.25 ++ uint64_t *ofs64 = (uint64_t *) offsets; 1.26 ++ 1.27 ++ if (ofs32[0] == 0) { 1.28 ++ if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */ 1.29 ++ while (n--) { 1.30 ++ offsets[n].offset = be64_to_cpu(offsets[n].offset); 1.31 ++ offsets[n].size = ntohl(offsets[n].size); 1.32 ++ } 1.33 ++ // return (char *) "128BE accelerated knoppix 1.0"; 1.34 ++ } 1.35 ++ else { /* V2.0 */ 1.36 ++ uint64_t last = be64_to_cpu(ofs64[n]); 1.37 ++ while (n--) { 1.38 ++ offsets[n].size = last - 1.39 ++ (offsets[n].offset = be64_to_cpu(ofs64[n])); 1.40 ++ last = offsets[n].offset; 1.41 ++ } 1.42 ++ // return (char *) "64BE v2.0"; 1.43 ++ } 1.44 ++ } 1.45 ++ else if (ofs32[1] == 0) { /* V1.0 */ 1.46 ++ uint64_t last = le64_to_cpu(ofs64[n]); 1.47 ++ while (n--) { 1.48 ++ offsets[n].size = last - 1.49 ++ (offsets[n].offset = le64_to_cpu(ofs64[n])); 1.50 ++ last = offsets[n].offset; 1.51 ++ } 1.52 ++ // return (char *) "64LE v1.0"; 1.53 ++ } 1.54 ++ else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 1.55 ++ uint64_t last = ntohl(ofs32[n]); 1.56 ++ while (n--) { 1.57 ++ offsets[n].size = last - 1.58 ++ (offsets[n].offset = ntohl(ofs32[n])); 1.59 ++ last = offsets[n].offset; 1.60 ++ } 1.61 ++ // return (char *) "32BE v0.68"; 1.62 ++ } 1.63 ++ else { /* V3.0 */ 1.64 ++ unsigned long i; 1.65 ++ uint64_t j; 1.66 ++ 1.67 ++ for (i = n; i-- > 0; ) 1.68 ++ offsets[i].size = ntohl(ofs32[i]); 1.69 ++ for (i = 0, j = 128 + 4 + 4; i < n; i++) { 1.70 ++ offsets[i].offset = j; 1.71 ++ j += offsets[i].size; 1.72 ++ } 1.73 ++ // return (char *) "32BE v3.0"; 1.74 ++ } 1.75 ++} 1.76 ++ 1.77 + typedef struct BDRVCloopState { 1.78 + CoMutex lock; 1.79 + uint32_t block_size; 1.80 + uint32_t n_blocks; 1.81 +- uint64_t *offsets; 1.82 ++ block_info *offsets; 1.83 + uint32_t sectors_per_block; 1.84 + uint32_t current_block; 1.85 + uint8_t *compressed_block; 1.86 +@@ -40,17 +107,21 @@ 1.87 + 1.88 + static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) 1.89 + { 1.90 +- const char *magic_version_2_0 = "#!/bin/sh\n" 1.91 +- "#V2.0 Format\n" 1.92 ++ static const uint8_t magic[] = 1.93 + "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n"; 1.94 +- int length = strlen(magic_version_2_0); 1.95 +- if (length > buf_size) { 1.96 +- length = buf_size; 1.97 ++ int i, ret = 0, length = buf_size; 1.98 ++ uint8_t c; 1.99 ++ 1.100 ++ if (length > 127) { 1.101 ++ length = 127; 1.102 + } 1.103 +- if (!memcmp(magic_version_2_0, buf, length)) { 1.104 +- return 2; 1.105 ++ for (i = 0; i < length - sizeof(magic) + 1; i++) { 1.106 ++ if (buf[i] != magic[0]) continue; 1.107 ++ if (strncmp(buf + i, magic, sizeof(magic) - 1)) continue; 1.108 ++ ret = 2; 1.109 ++ break; 1.110 + } 1.111 +- return 0; 1.112 ++ return ret; 1.113 + } 1.114 + 1.115 + static int cloop_open(BlockDriverState *bs, QDict *options, int flags) 1.116 +@@ -74,32 +145,67 @@ 1.117 + } 1.118 + s->n_blocks = be32_to_cpu(s->n_blocks); 1.119 + 1.120 +- /* read offsets */ 1.121 +- offsets_size = s->n_blocks * sizeof(uint64_t); 1.122 +- s->offsets = g_malloc(offsets_size); 1.123 ++ /* initialize zlib engine */ 1.124 ++ max_compressed_block_size = s->block_size + s->block_size/1000 + 12 + 4; 1.125 ++ s->compressed_block = g_malloc(max_compressed_block_size + 1); 1.126 ++ s->uncompressed_block = g_malloc(s->block_size); 1.127 + 1.128 +- ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size); 1.129 +- if (ret < 0) { 1.130 ++ if (inflateInit(&s->zstream) != Z_OK) { 1.131 ++ ret = -EINVAL; 1.132 + goto fail; 1.133 + } 1.134 + 1.135 +- for(i=0;i<s->n_blocks;i++) { 1.136 +- s->offsets[i] = be64_to_cpu(s->offsets[i]); 1.137 +- if (i > 0) { 1.138 +- uint32_t size = s->offsets[i] - s->offsets[i - 1]; 1.139 +- if (size > max_compressed_block_size) { 1.140 +- max_compressed_block_size = size; 1.141 +- } 1.142 ++ /* read offsets */ 1.143 ++ if (s->n_blocks + 1 == 0) { 1.144 ++ cloop_tail tail; 1.145 ++ int64_t end = bdrv_getlength(bs->file); 1.146 ++ void *p; 1.147 ++ uint32_t toclen, len; 1.148 ++ 1.149 ++ ret = bdrv_pread(bs->file, end - sizeof(tail), &tail, sizeof(tail)); 1.150 ++ if (ret < 0) { 1.151 ++ goto fail; 1.152 + } 1.153 ++ 1.154 ++ s->n_blocks = be32_to_cpu(tail.num_blocks); 1.155 ++ offsets_size = s->n_blocks * sizeof(block_info); 1.156 ++ len = be32_to_cpu(tail.table_size); 1.157 ++ toclen = (be32_to_cpu(tail.index_size) & 255) * s->n_blocks; 1.158 ++ 1.159 ++ s->offsets = g_malloc(offsets_size); 1.160 ++ p = g_malloc(len); 1.161 ++ 1.162 ++ ret = bdrv_pread(bs->file, end - sizeof(tail) - len, p, len); 1.163 ++ if (ret < 0) { 1.164 ++ goto fail; 1.165 ++ } 1.166 ++ s->zstream.next_in = p; 1.167 ++ s->zstream.avail_in = len; 1.168 ++ s->zstream.next_out = s->offsets; 1.169 ++ s->zstream.avail_out = toclen; 1.170 ++ ret = inflateReset(&s->zstream); 1.171 ++ if (ret != Z_OK) { 1.172 ++ ret = -EINVAL; 1.173 ++ goto fail; 1.174 ++ } 1.175 ++ ret = inflate(&s->zstream, Z_FINISH); 1.176 ++ if (ret != Z_STREAM_END || s->zstream.total_out != toclen) { 1.177 ++ ret = -EINVAL; 1.178 ++ goto fail; 1.179 ++ } 1.180 ++ g_free(p); 1.181 + } 1.182 ++ else { 1.183 ++ offsets_size = s->n_blocks * sizeof(block_info); 1.184 ++ s->offsets = g_malloc(offsets_size); 1.185 + 1.186 +- /* initialize zlib engine */ 1.187 +- s->compressed_block = g_malloc(max_compressed_block_size + 1); 1.188 +- s->uncompressed_block = g_malloc(s->block_size); 1.189 +- if (inflateInit(&s->zstream) != Z_OK) { 1.190 +- ret = -EINVAL; 1.191 +- goto fail; 1.192 ++ ret = bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size); 1.193 ++ if (ret < 0) { 1.194 ++ goto fail; 1.195 ++ } 1.196 + } 1.197 ++ build_index(s->offsets, s->n_blocks); 1.198 ++ 1.199 + s->current_block = s->n_blocks; 1.200 + 1.201 + s->sectors_per_block = s->block_size/512; 1.202 +@@ -120,10 +226,10 @@ 1.203 + 1.204 + if (s->current_block != block_num) { 1.205 + int ret; 1.206 +- uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num]; 1.207 ++ uint32_t bytes = s->offsets[block_num].size; 1.208 + 1.209 +- ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block, 1.210 +- bytes); 1.211 ++ ret = bdrv_pread(bs->file, s->offsets[block_num].offset, 1.212 ++ s->compressed_block, bytes); 1.213 + if (ret != bytes) { 1.214 + return -1; 1.215 + }