wok-current rev 23679
fusecloop: add v4 support
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sun Apr 26 10:50:29 2020 +0000 (2020-04-26) |
parents | ff210fc49547 |
children | 5f55920ffb7e |
files | cloop-utils/receipt fusecloop/receipt fusecloop/stuff/v4.u |
line diff
1.1 --- a/cloop-utils/receipt Sun Apr 26 10:56:37 2020 +0100 1.2 +++ b/cloop-utils/receipt Sun Apr 26 10:50:29 2020 +0000 1.3 @@ -9,7 +9,7 @@ 1.4 WEB_SITE="http://fusecloop.sourceforge.net/" 1.5 WANTED="fusecloop" 1.6 1.7 -DEPENDS="zlib gcc-lib-base" 1.8 +DEPENDS="zlib liblzma lz4-lib lzo zstd gcc-lib-base" 1.9 1.10 # Rules to gen a SliTaz package suitable for Tazpkg. 1.11 genpkg_rules()
2.1 --- a/fusecloop/receipt Sun Apr 26 10:56:37 2020 +0100 2.2 +++ b/fusecloop/receipt Sun Apr 26 10:50:29 2020 +0000 2.3 @@ -14,8 +14,8 @@ 2.4 ADVANCECOMP_URL="$SF_MIRROR/advancemame/$ADVANCECOMP_TARBALL" 2.5 EXTRA_SOURCE_FILES="$ADVANCECOMP_TARBALL" 2.6 2.7 -DEPENDS="fuse zlib gcc-lib-base" 2.8 -BUILD_DEPENDS="fuse-dev zlib-dev automake" 2.9 +DEPENDS="fuse zlib liblzma lz4-lib lzo zstd gcc-lib-base" 2.10 +BUILD_DEPENDS="fuse-dev zlib-dev xz-dev liblzma lz4-dev lzo-dev zstd-dev automake" 2.11 SUGGESTED="fuseiso cloop-utils" 2.12 2.13 # Rules to configure and make the package. 2.14 @@ -26,12 +26,13 @@ 2.15 tar xzf $SOURCES_REPOSITORY/$ADVANCECOMP_TARBALL 2.16 sed -i 's/dprintf/d_printf/g' *.h *.c 2.17 patch -p0 < $stuff/fusecloop.u 2.18 + patch -p0 < $stuff/v4.u 2.19 ADVANCECOMP=advancecomp-$ADVANCECOMP_VERSION 2.20 cp *.h *.c $ADVANCECOMP 2.21 cp create_compressed_fs.c $ADVANCECOMP/redef.cc 2.22 sed -i 's/Z_BEST_COMPRESSION/Z_BEST_SPEED/' create_compressed_fs.c 2.23 sed -i 's/def FIND_BEST_COMPRESSION/ 1/' $ADVANCECOMP/redef.cc 2.24 - sed -i 's|\( -lz\)\(.*\)$|\2\1|' Makefile 2.25 + sed -i 's|\( -lz\)\(.*\)$|\2\1 -llzma -llz4 -llzo2 -lzstd|' Makefile 2.26 sed -i 's|\( \$.FUSELDFLAGS.\)\(.*\)$|\2\1|' Makefile 2.27 ./configure --prefix=/usr --infodir=/usr/share/info \ 2.28 --mandir=/usr/share/man $CONFIGURE_ARGS && 2.29 @@ -39,8 +40,9 @@ 2.30 cd $ADVANCECOMP && 2.31 ./autogen.sh 2.32 automake --add-missing 2.33 - ./configure --prefix=/usr --infodir=/usr/share/info \ 2.34 - --mandir=/usr/share/man $CONFIGURE_ARGS && 2.35 + ./configure LIBS="-llzma -llz4" \ 2.36 + --prefix=/usr --infodir=/usr/share/info \ 2.37 + --mandir=/usr/share/man $CONFIGURE_ARGS && 2.38 make advdef 2.39 } 2.40
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/fusecloop/stuff/v4.u Sun Apr 26 10:50:29 2020 +0000 3.3 @@ -0,0 +1,921 @@ 3.4 +--- compressed_loop.h 3.5 ++++ compressed_loop.h 3.6 +@@ -30,6 +30,54 @@ 3.7 + /* ...padding up to CLOOP_HEADROOM... */ 3.8 + /* block_size (32bit number, network order) */ 3.9 + /* num_blocks (32bit number, network order) */ 3.10 ++/* 3.11 ++* Starting with Format V4.0 (cloop version 4.x), cloop can now have two * 3.12 ++* alternative structures: * 3.13 ++* 1. Header first: * 3.14 ++* +---------------------------- FIXED SIZE ---------------------------+ * 3.15 ++* |Signature (128 bytes) | * 3.16 ++* |block_size (32bit number, network order) | * 3.17 ++* |num_blocks (32bit number, network order) | * 3.18 ++* +--------------------------- VARIABLE SIZE -------------------------+ * 3.19 ++* |num_blocks * FlagsOffset (upper 4 bits flags, lower 60 bits offset)| * 3.20 ++* |compressed data blocks of variable size ... | * 3.21 ++* +-------------------------------------------------------------------+ * 3.22 ++* * 3.23 ++* 2. Footer (header last): * 3.24 ++* +--------------------------- VARIABLE SIZE -------------------------+ * 3.25 ++* |compressed data blocks of variable size ... | * 3.26 ++* |num_blocks * FlagsOffset (upper 4 bits flags, lower 60 bits offset)| * 3.27 ++* +---------------------------- FIXED SIZE ---------------------------+ * 3.28 ++* |Signature (128 bytes) | * 3.29 ++* |block_size (32bit number, network order) | * 3.30 ++* |num_blocks (32bit number, network order) | * 3.31 ++* +-------------------------------------------------------------------+ * 3.32 ++* * 3.33 ++* Offsets are always relative to beginning of file, in all formats. * 3.34 ++* The block index contains num_blocks+1 offsets, followed (1) or * 3.35 ++* preceded (2) by the compressed blocks. * 3.36 ++* * 3.37 ++* CLOOP4 flags for each compressed block * 3.38 ++* Value Meaning * 3.39 ++* 0 GZIP/7ZIP compression (compatible with V2.0 Format) * 3.40 ++* 1 no compression (incompressible data) * 3.41 ++* 2 xz compression (currently best space saver) * 3.42 ++* 3 lz4 compression * 3.43 ++* 4 lzo compression (fastest) * 3.44 ++* 15 block link * 3.45 ++*/ 3.46 ++/* Get value of first 4 bits */ 3.47 ++#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60)) 3.48 ++/* Get value of last 60 bits */ 3.49 ++#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU) 3.50 ++ 3.51 ++#define CLOOP_COMPRESSOR_ZLIB 0x0 3.52 ++#define CLOOP_COMPRESSOR_NONE 0x1 3.53 ++#define CLOOP_COMPRESSOR_XZ 0x2 3.54 ++#define CLOOP_COMPRESSOR_LZ4 0x3 3.55 ++#define CLOOP_COMPRESSOR_LZO 0x4 3.56 ++#define CLOOP_COMPRESSOR_LINK 0xF 3.57 ++ 3.58 + 3.59 + struct cloop_head 3.60 + { 3.61 +@@ -43,47 +91,86 @@ 3.62 + 3.63 + struct cloop_tail 3.64 + { 3.65 +- u_int32_t table_size; 3.66 +- u_int32_t index_size; 3.67 ++ u_int32_t table_size; 3.68 ++ u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 3.69 ++#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 3.70 ++#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 3.71 ++#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 3.72 ++#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 3.73 + u_int32_t num_blocks; 3.74 + }; 3.75 + 3.76 ++#define GZIP_MAX_BUFFER(n) ((n) + (n)/1000 + 12) 3.77 ++ 3.78 + struct block_info 3.79 + { 3.80 + loff_t offset; /* 64-bit offsets of compressed block */ 3.81 + u_int32_t size; /* 32-bit compressed block size */ 3.82 +- u_int32_t optidx; /* 32-bit index number */ 3.83 ++ u_int32_t flags; /* 32-bit compression flags */ 3.84 ++ 3.85 + }; 3.86 + 3.87 +-static inline char *build_index(struct block_info *offsets, unsigned long n) 3.88 ++static inline char *build_index(struct block_info *offsets, unsigned long n, 3.89 ++ unsigned long block_size, unsigned global_flags) 3.90 + { 3.91 + u_int32_t *ofs32 = (u_int32_t *) offsets; 3.92 + loff_t *ofs64 = (loff_t *) offsets; 3.93 +- 3.94 ++ 3.95 ++ /* v3 64bits bug: v1 assumed */ 3.96 ++ unsigned long v3_64; 3.97 ++ loff_t prev; 3.98 ++ 3.99 ++ if (ofs32[0] != 0 && ofs32[1] == 0) { 3.100 ++ for (v3_64=(n+1)/2, prev=__le64_to_cpu(ofs64[v3_64]); 3.101 ++ v3_64 > 0 && __le64_to_cpu(ofs64[--v3_64]) < prev; 3.102 ++ prev=__le64_to_cpu(ofs64[v3_64])); 3.103 ++ } 3.104 ++ 3.105 + if (ofs32[0] == 0) { 3.106 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */ 3.107 + while (n--) { 3.108 + offsets[n].offset = __be64_to_cpu(offsets[n].offset); 3.109 + offsets[n].size = ntohl(offsets[n].size); 3.110 ++ offsets[n].flags = 0; 3.111 + } 3.112 + return (char *) "128BE accelerated knoppix 1.0"; 3.113 + } 3.114 +- else { /* V2.0 */ 3.115 +- loff_t last = __be64_to_cpu(ofs64[n]); 3.116 +- while (n--) { 3.117 ++ else { /* V2.0/V4.0 */ 3.118 ++ loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 3.119 ++ u_int32_t flags; 3.120 ++ static char v4[11]; 3.121 ++ unsigned long i = n; 3.122 ++ 3.123 ++ for (flags = 0; n-- ;) { 3.124 ++ loff_t data = __be64_to_cpu(ofs64[n]); 3.125 ++ 3.126 + offsets[n].size = last - 3.127 +- (offsets[n].offset = __be64_to_cpu(ofs64[n])); 3.128 ++ (offsets[n].offset = CLOOP_BLOCK_OFFSET(data)); 3.129 + last = offsets[n].offset; 3.130 ++ offsets[n].flags = CLOOP_BLOCK_FLAGS(data); 3.131 ++ flags |= 1 << offsets[n].flags; 3.132 ++ } 3.133 ++ if (flags < 2) return (char *) "64BE v2.0"; 3.134 ++ while (i--) { 3.135 ++ if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) { 3.136 ++ offsets[i] = offsets[offsets[i].offset]; 3.137 ++ } 3.138 ++ } 3.139 ++ strcpy(v4, (char *) "64BE v4.0a"); 3.140 ++ v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 3.141 ++ if (flags > 0x10) { // with links ? 3.142 ++ v4[10] += 'A' - 'a'; 3.143 + } 3.144 +- return (char *) "64BE v2.0"; 3.145 ++ return v4; 3.146 + } 3.147 + } 3.148 +- else if (ofs32[1] == 0) { /* V1.0 */ 3.149 ++ else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 3.150 + loff_t last = __le64_to_cpu(ofs64[n]); 3.151 + while (n--) { 3.152 + offsets[n].size = last - 3.153 + (offsets[n].offset = __le64_to_cpu(ofs64[n])); 3.154 + last = offsets[n].offset; 3.155 ++ offsets[n].flags = 0; 3.156 + } 3.157 + return (char *) "64LE v1.0"; 3.158 + } 3.159 +@@ -93,25 +180,37 @@ 3.160 + offsets[n].size = last - 3.161 + (offsets[n].offset = ntohl(ofs32[n])); 3.162 + last = offsets[n].offset; 3.163 ++ offsets[n].flags = 0; 3.164 + } 3.165 + return (char *) "32BE v0.68"; 3.166 + } 3.167 + else { /* V3.0 */ 3.168 + unsigned long i; 3.169 + loff_t j; 3.170 ++ static char v3[11]; 3.171 + 3.172 ++ v3_64 = (ofs32[1] == 0) ? 2 : 1; 3.173 + for (i = n; i-- != 0; ) 3.174 +- offsets[i].size = ntohl(ofs32[i]); 3.175 ++ offsets[i].size = ntohl(ofs32[i*v3_64]); 3.176 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 3.177 + offsets[i].offset = j; 3.178 ++ offsets[i].flags = global_flags; 3.179 ++ if ((offsets[i].size & 0x80000000) == 0) { 3.180 ++ j += offsets[i].size; 3.181 ++ } 3.182 ++ else if (offsets[i].size == 0xFFFFFFFF) { 3.183 ++ offsets[i].flags = CLOOP_COMPRESSOR_NONE; 3.184 ++ j += offsets[i].size = block_size; 3.185 ++ } 3.186 ++ } 3.187 ++ for (i = 0; i < n; i++) { 3.188 + if (offsets[i].size & 0x80000000) { 3.189 +- unsigned long k = offsets[i].size & 0x7FFFFFFF; 3.190 +- offsets[i].offset = offsets[k].offset; 3.191 +- offsets[i].size = offsets[k].size; 3.192 ++ offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 3.193 + } 3.194 +- else j += offsets[i].size; 3.195 + } 3.196 +- return (char *) "32BE v3.0"; 3.197 ++ strcpy(v3, (char *) (--v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 3.198 ++ v3[10] += global_flags; 3.199 ++ return v3; 3.200 + } 3.201 + } 3.202 + 3.203 +--- cloopreader.c 3.204 ++++ cloopreader.c 3.205 +@@ -25,6 +25,8 @@ 3.206 + #include "debug.h" 3.207 + #include "cloopreader.h" 3.208 + 3.209 ++#include "cloopunpack.c" 3.210 ++ 3.211 + int read_all(int fh, void* block, size_t size){ 3.212 + bfuncinfo("fh=%d block=0x%lx size=0x%lx", 3.213 + fh,(ulong)block,(ulong)size); 3.214 +@@ -50,18 +52,29 @@ 3.215 + bfuncinfo("fh=%d",fh); 3.216 + c->fh=fh; 3.217 + struct cloop_head head; 3.218 +- OP(read_all(c->fh,&head,sizeof head)); /* read Header */ 3.219 ++ int v4_header_last, flags; 3.220 ++ loff_t end; 3.221 ++ 3.222 ++ for (v4_header_last=0;;v4_header_last++) { 3.223 ++ OP(read_all(c->fh,&head,sizeof head)); /* read Header */ 3.224 ++ if (!memcmp(&head,"#!/bin/sh",9)) break; 3.225 ++ if (v4_header_last) exit(1); 3.226 ++ end = lseek(c->fh, 0, SEEK_END); 3.227 ++ OP(lseek(c->fh, end - sizeof(head), SEEK_SET)); 3.228 ++ } 3.229 + 3.230 + c->numblocks=ntohl(head.num_blocks); 3.231 + c->blocksize=ntohl(head.block_size); 3.232 + 3.233 + bprintf("block_size=%lx num_blocks=%x\n", c->blocksize, c->numblocks); 3.234 ++ if (v4_header_last) 3.235 ++ OP(lseek(c->fh, end - sizeof(head) - (sizeof(*c->toc) * c->numblocks), SEEK_SET)); 3.236 + 3.237 + ALLOC(c->pblock,c->blocksize); 3.238 + 3.239 + if (c->numblocks + 1 == 0) { 3.240 + struct cloop_tail tail; 3.241 +- loff_t end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */ 3.242 ++ end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */ 3.243 + void *p; 3.244 + ulong toclen, len; 3.245 + 3.246 +@@ -70,21 +83,23 @@ 3.247 + c->numblocks = ntohl(tail.num_blocks); 3.248 + c->tocsize = sizeof(*c->toc) * c->numblocks; 3.249 + len = ntohl(tail.table_size); 3.250 +- toclen = (ntohl(tail.index_size) & 255) * c->numblocks; 3.251 ++ flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 3.252 ++ toclen = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * c->numblocks; 3.253 + OP(lseek(c->fh, end - sizeof(tail) - len, SEEK_SET)); 3.254 + ALLOC(c->toc, sizeof(*c->toc) * c->numblocks); 3.255 + ALLOC(p,len); 3.256 + OP(read_all(c->fh,p,len)); /* read Data Index */ 3.257 +- if (uncompress((void *)c->toc,&toclen,p,len) != Z_OK) 3.258 ++ if (unpack[flags]((void *)c->toc,&toclen,p,len) != Z_OK) 3.259 + exit(1); 3.260 + free(p); 3.261 + } 3.262 + else { 3.263 ++ flags = 0; 3.264 + c->tocsize = sizeof(*c->toc) * c->numblocks; 3.265 + ALLOC(c->toc,c->tocsize); 3.266 + OP(read_all(c->fh,c->toc,c->tocsize)); /* read Data Index */ 3.267 + } 3.268 +- build_index(c->toc, c->numblocks); 3.269 ++ build_index(c->toc, c->numblocks, c->blocksize, flags); 3.270 + c->cblocksizecur=0; 3.271 + c->curblock=-1; 3.272 + return 0; 3.273 +@@ -121,7 +136,8 @@ 3.274 + "pblock=0x%lx &destlen=0x%lx cblock=0x%lx cblocksize=%lu\n", 3.275 + (ulong)c->pblock,(ulong)&destlen,(ulong)c->cblock,c->cblocksize 3.276 + ); 3.277 +- switch(uncompress(c->pblock,&destlen,c->cblock,c->cblocksize)){ 3.278 ++ if(c->toc[page].flags <= CLOOP_COMPRESSOR_MAX){ 3.279 ++ switch(unpack[c->toc[page].flags](c->pblock,&destlen,c->cblock,c->cblocksize)){ 3.280 + case Z_OK: break; 3.281 + #define entry(x)\ 3.282 + case x: bprintf( #x"\n"); break; 3.283 +@@ -130,7 +146,9 @@ 3.284 + entry(Z_DATA_ERROR) 3.285 + #undef entry 3.286 + default: bprintf("Z_UNKNOWN_ERROR\n"); 3.287 ++ } 3.288 + } 3.289 ++ else bprintf("Unsuppoted compression type\n"); 3.290 + if(destlen!=c->blocksize)bprintf("Size mismatch\n"); 3.291 + return 0; 3.292 + } 3.293 +--- /dev/null 3.294 ++++ cloopunpack.c 3.295 +@@ -0,0 +1,74 @@ 3.296 ++ 3.297 ++static int none_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLongf sourceLen) 3.298 ++{ 3.299 ++ memcpy(dest,source,*destLen = sourceLen); 3.300 ++ return Z_OK; 3.301 ++} 3.302 ++ 3.303 ++#include <lzma.h> 3.304 ++static int xz_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLongf sourceLen) 3.305 ++{ 3.306 ++ size_t src_pos = 0; 3.307 ++ size_t dest_pos = 0; 3.308 ++ uint64_t memlimit = 32*1024*1024; 3.309 ++ 3.310 ++ lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL, 3.311 ++ source, &src_pos, sourceLen, dest, &dest_pos, *destLen); 3.312 ++ 3.313 ++ if(res == LZMA_OK && sourceLen == (int) src_pos) { 3.314 ++ *destLen = dest_pos; 3.315 ++ return Z_OK; 3.316 ++ } 3.317 ++ else return Z_ERRNO; 3.318 ++} 3.319 ++ 3.320 ++#include <lz4.h> 3.321 ++static int lz4_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLongf sourceLen) 3.322 ++{ 3.323 ++ long size = LZ4_decompress_safe((const char *) source, (char *) dest, sourceLen, *destLen); 3.324 ++ 3.325 ++ if (size < 0) return Z_ERRNO; 3.326 ++ *destLen = size; 3.327 ++ return Z_OK; 3.328 ++} 3.329 ++ 3.330 ++#include <lzo/lzo1x.h> 3.331 ++static int lzo_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLongf sourceLen) 3.332 ++{ 3.333 ++ lzo_uint outlen = *destLen; 3.334 ++ 3.335 ++ if (lzo1x_decompress_safe(source, sourceLen, dest, &outlen, NULL) == LZO_E_OK) { 3.336 ++ *destLen = outlen; 3.337 ++ return Z_OK; 3.338 ++ } 3.339 ++ else return Z_ERRNO; 3.340 ++} 3.341 ++ 3.342 ++#include <zstd.h> 3.343 ++static int zstd_uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLongf sourceLen) 3.344 ++{ 3.345 ++ const size_t res = ZSTD_decompress(dest, *destLen, source, sourceLen); 3.346 ++ 3.347 ++ if (ZSTD_isError(res)) { 3.348 ++ return Z_ERRNO; 3.349 ++ } 3.350 ++ 3.351 ++ *destLen = res; 3.352 ++ return Z_OK; 3.353 ++} 3.354 ++ 3.355 ++#define CLOOP_COMPRESSOR_ZSTD 0x5 3.356 ++ 3.357 ++#define CLOOP_COMPRESSOR_MAX CLOOP_COMPRESSOR_ZSTD 3.358 ++ 3.359 ++#define CLOOP_COMPRESSOR_NAMES "gzip","copy","xz","lz4","lzo","zstd" 3.360 ++ 3.361 ++static int (*unpack[CLOOP_COMPRESSOR_MAX+1])(Bytef *dest, uLongf *destLen, const Bytef *source, uLongf sourceLen) = { 3.362 ++ uncompress, 3.363 ++ none_uncompress, 3.364 ++ xz_uncompress, 3.365 ++ lz4_uncompress, 3.366 ++ lzo_uncompress, 3.367 ++ zstd_uncompress 3.368 ++}; 3.369 ++ 3.370 +--- extract_compressed_fs.c 3.371 ++++ extract_compressed_fs.c 3.372 +@@ -3,14 +3,19 @@ 3.373 + #include "common_header.h" 3.374 + #define CLOOP_PREAMBLE "#!/bin/sh\n" "#V2.0 Format\n" "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n" 3.375 + 3.376 ++#include "cloopunpack.c" 3.377 ++static char *packnames[CLOOP_COMPRESSOR_MAX+1] = { CLOOP_COMPRESSOR_NAMES }; 3.378 ++ 3.379 + int main(int argc, char *argv[]) 3.380 + { 3.381 +- int handle; 3.382 ++ int handle, err; 3.383 + struct cloop_head head; 3.384 +- unsigned int i; 3.385 +- unsigned long num_blocks, block_size, zblock_maxsize, lastlen = 0; 3.386 ++ unsigned int i, v4_header_last, global_flags; 3.387 ++ unsigned long n, num_blocks, block_size, zblock_maxsize, len; 3.388 ++ uLongf ulen; 3.389 + unsigned char *buffer, *clear_buffer; 3.390 + struct block_info *offsets; 3.391 ++ loff_t end; 3.392 + 3.393 + if (argc < 2 || argv[1][0] == '-') { 3.394 + fprintf(stderr, "Usage: extract_compressed_fs file [--convert-to-v2] > output\n"); 3.395 +@@ -23,23 +28,35 @@ 3.396 + exit(1); 3.397 + } 3.398 + 3.399 +- if (read(handle, &head, sizeof(head)) != sizeof(head)) { 3.400 +- perror("Reading compressed file header\n"); 3.401 ++ for (v4_header_last=0;; v4_header_last++) { 3.402 ++ if (read(handle, &head, sizeof(head)) != sizeof(head)) { 3.403 ++ perror("Reading compressed file header\n"); 3.404 ++ exit(1); 3.405 ++ } 3.406 ++ if (!memcmp(&head,"#!/bin/sh",9)) break; 3.407 ++ end = lseek64(handle, 0, SEEK_END); 3.408 ++ lseek64(handle, end - sizeof(head), SEEK_SET); 3.409 ++ if (v4_header_last == 0) continue; 3.410 ++ perror("Not a cloop file\n"); 3.411 + exit(1); 3.412 + } 3.413 + 3.414 + num_blocks = ntohl(head.num_blocks); 3.415 + block_size = ntohl(head.block_size); 3.416 +- zblock_maxsize = block_size + block_size/1000 + 12 + 4; 3.417 ++ zblock_maxsize = GZIP_MAX_BUFFER(block_size); 3.418 + buffer = malloc(zblock_maxsize); 3.419 + clear_buffer = malloc(block_size); 3.420 + 3.421 ++ if (v4_header_last) { 3.422 ++ lseek64(handle, end - ((num_blocks+1) * sizeof(loff_t)) - sizeof(head), SEEK_SET); 3.423 ++ } 3.424 ++ 3.425 + if (num_blocks == 0xFFFFFFFF) { 3.426 + void *table; 3.427 + struct cloop_tail tail; 3.428 +- unsigned long len, table_size; 3.429 +- loff_t end = lseek64(handle, 0, SEEK_END); 3.430 ++ unsigned long table_size; 3.431 + 3.432 ++ end = lseek64(handle, 0, SEEK_END); 3.433 + if (lseek64(handle, end - sizeof(tail), SEEK_SET) < 0 || 3.434 + read(handle, &tail, sizeof(tail)) != sizeof(tail) || 3.435 + lseek64(handle, end - sizeof(tail) - 3.436 +@@ -51,60 +68,91 @@ 3.437 + num_blocks = ntohl(head.num_blocks); 3.438 + table_size = ntohl(tail.table_size); 3.439 + table = malloc(table_size); 3.440 +- len = i = num_blocks * (ntohl(tail.index_size) & 255); 3.441 +- lastlen = ntohl(tail.index_size) / 256; 3.442 +- offsets = malloc(num_blocks * sizeof(*offsets)); 3.443 +- if (!table || !offsets || 3.444 +- read(handle, table, table_size) != table_size || 3.445 +- uncompress((void *)offsets, &len, table, table_size) != Z_OK || 3.446 +- len != i) { 3.447 ++ len = num_blocks * CLOOP3_INDEX_SIZE(ntohl(tail.index_size)); 3.448 ++ global_flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 3.449 ++ if (global_flags > CLOOP_COMPRESSOR_MAX) { 3.450 ++ fprintf(stderr, "Unsupported compression %d\n", 3.451 ++ global_flags); 3.452 ++ exit(1); 3.453 ++ } 3.454 ++ ulen = num_blocks * sizeof(*offsets); 3.455 ++ offsets = malloc(ulen); 3.456 ++ if (!table || !offsets || !buffer || !clear_buffer) { 3.457 ++ fprintf(stderr,"Out of memory\n"); 3.458 ++ exit(1); 3.459 ++ } 3.460 ++ if (read(handle, table, table_size) != table_size) { 3.461 + perror("Reading index\n"); 3.462 + exit(1); 3.463 + } 3.464 ++ err = unpack[global_flags]((void *) offsets, &ulen, table, table_size); 3.465 ++ if (err != Z_OK) { 3.466 ++ fprintf(stderr, "Unpack %s index error %d\n", 3.467 ++ packnames[global_flags],err); 3.468 ++ exit(1); 3.469 ++ } 3.470 + free(table); 3.471 + } 3.472 + else { 3.473 +- offsets = malloc(i = num_blocks * sizeof(*offsets)); 3.474 +- if (!offsets || read(handle, offsets, i) != i) { 3.475 ++ global_flags = 0; 3.476 ++ len = num_blocks * sizeof(*offsets); 3.477 ++ offsets = malloc(len); 3.478 ++ if (v4_header_last) { 3.479 ++ len = (num_blocks+1) * sizeof(loff_t); 3.480 ++ } 3.481 ++ if (!offsets || !buffer || !clear_buffer) { 3.482 ++ fprintf(stderr,"Out of memory\n"); 3.483 ++ exit(1); 3.484 ++ } 3.485 ++ if (read(handle, offsets, len) != len) { 3.486 + perror("Reading index\n"); 3.487 + exit(1); 3.488 + } 3.489 + } 3.490 + 3.491 ++ if (v4_header_last) { 3.492 ++ lseek64(handle, 0, SEEK_SET); 3.493 ++ } 3.494 ++ 3.495 + fprintf(stderr, "%lu blocks of size %lu. Preamble:\n%s\n", 3.496 + num_blocks, block_size, head.preamble); 3.497 +- fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks)); 3.498 ++#if 1 3.499 ++ if (getenv("CLOOP_INDEX") != NULL) { 3.500 ++ fprintf(stderr, "CLOOP_INDEX: binary\n"); 3.501 ++ write(STDOUT_FILENO, offsets, len); 3.502 ++ exit(0); 3.503 ++ } 3.504 ++#endif 3.505 ++ fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks, block_size, global_flags)); 3.506 + 3.507 ++#if 1 3.508 ++ if (getenv("CLOOP_TABLE") != NULL) { 3.509 ++ fprintf(stderr, "CLOOP_TABLE ascii: offset, size, flags\n"); 3.510 ++ for (i = 0; i < num_blocks; i++) { 3.511 ++ printf("%llu %u %u\n", 3.512 ++ offsets[i].offset, 3.513 ++ offsets[i].size, 3.514 ++ offsets[i].flags); 3.515 ++ } 3.516 ++ exit(0); 3.517 ++ } 3.518 ++#endif 3.519 ++ 3.520 + if (argc > 2) { 3.521 +- unsigned n; 3.522 +- loff_t data, offset = ((num_blocks + 1) * sizeof(offset)) + sizeof(head); 3.523 ++ loff_t data, ofs = ((num_blocks + 1) * sizeof(ofs)) + sizeof(head); 3.524 + 3.525 + strcpy(head.preamble, CLOOP_PREAMBLE); 3.526 + write(STDOUT_FILENO, &head, n = sizeof(head)); 3.527 +- for (i = 0; i < num_blocks; i++) { 3.528 +- data = __be64_to_cpu(offset); 3.529 ++ for (i = 0; i <= num_blocks; i++) { 3.530 ++ data = __be64_to_cpu(ofs); 3.531 + write(STDOUT_FILENO, &data, sizeof(data)); 3.532 + n += sizeof(data); 3.533 +- offset += offsets[i].size; 3.534 ++ ofs += offsets[i].size; 3.535 + } 3.536 +- data = __be64_to_cpu(offset); 3.537 +- write(STDOUT_FILENO, &data, sizeof(data)); 3.538 +- for (i = 0; i < num_blocks && lseek64(handle, offsets[i].offset, SEEK_SET) >= 0; i++) { 3.539 +- read(handle, buffer, offsets[i].size); 3.540 +- write(STDOUT_FILENO, buffer, offsets[i].size); 3.541 +- n += offsets[i].size; 3.542 +- } 3.543 +- n &= 0x1FF; 3.544 +- if (n) { 3.545 +- memset(buffer, 0, 512); 3.546 +- write(STDOUT_FILENO, buffer, 512 - n); 3.547 +- } 3.548 +- return 0; 3.549 + } 3.550 +- 3.551 + for (i = 0; i < num_blocks; i++) { 3.552 +- unsigned long destlen = block_size; 3.553 +- unsigned int size = offsets[i].size; 3.554 ++ unsigned char *out; 3.555 ++ int flags = offsets[i].flags; 3.556 + 3.557 + if (lseek64(handle, offsets[i].offset, SEEK_SET) < 0) { 3.558 + fprintf(stderr, "lseek to %Lu: %s\n", 3.559 +@@ -112,44 +160,61 @@ 3.560 + exit(1); 3.561 + } 3.562 + 3.563 +- if (size > zblock_maxsize) { 3.564 ++ len = offsets[i].size; 3.565 ++ if (len > zblock_maxsize) { 3.566 + fprintf(stderr, 3.567 + "Size %u for block %u (offset %Lu) too big\n", 3.568 +- size, i, offsets[i].offset); 3.569 ++ len, i, offsets[i].offset); 3.570 + exit(1); 3.571 + } 3.572 +- read(handle, buffer, size); 3.573 +- 3.574 +- fprintf(stderr, "Block %u at %llu length %u", 3.575 +- i, offsets[i].offset, size); 3.576 +- switch (uncompress(clear_buffer, &destlen, 3.577 +- buffer, size)) { 3.578 +- case Z_OK: 3.579 +- break; 3.580 + 3.581 +- case Z_MEM_ERROR: 3.582 +- fprintf(stderr, "Uncomp: oom block %u\n", i); 3.583 +- exit(1); 3.584 +- 3.585 +- case Z_BUF_ERROR: 3.586 +- fprintf(stderr, "Uncomp: not enough out room %u\n", i); 3.587 +- exit(1); 3.588 +- 3.589 +- case Z_DATA_ERROR: 3.590 +- fprintf(stderr, "Uncomp: input corrupt %u\n", i); 3.591 ++ if (argc <= 2) { 3.592 ++ fprintf(stderr, "Block %u at %llu length %lu ", 3.593 ++ i, offsets[i].offset, len); 3.594 ++ } 3.595 ++ 3.596 ++ read(handle, out = buffer, ulen = len); 3.597 ++ 3.598 ++ if (flags > CLOOP_COMPRESSOR_MAX) { 3.599 ++ fprintf(stderr, "Block %u: unsupported compression %d \n", 3.600 ++ i, flags); 3.601 + exit(1); 3.602 ++ } 3.603 + 3.604 +- default: 3.605 +- fprintf(stderr, "Uncomp: unknown error %u\n", i); 3.606 +- exit(1); 3.607 ++ if (flags != CLOOP_COMPRESSOR_ZLIB || argc <= 2) { 3.608 ++ ulen = block_size; 3.609 ++ err = unpack[flags](out = clear_buffer, &ulen, buffer, len); 3.610 ++ if (err != Z_OK) { 3.611 ++ fprintf(stderr, "Unpack %s block %u error %d \n", 3.612 ++ packnames[flags], i, err); 3.613 ++ exit(1); 3.614 ++ } 3.615 ++ if (argc > 2) { 3.616 ++ err = compress2(out = buffer, &ulen, clear_buffer, ulen, Z_BEST_SPEED); 3.617 ++ if (err != Z_OK) { 3.618 ++ fprintf(stderr, "Compress %s block %u error %d \n", 3.619 ++ packnames[flags], i, err); 3.620 ++ exit(1); 3.621 ++ } 3.622 ++ } 3.623 ++ else { 3.624 ++ fprintf(stderr, "=> %lu\n", ulen); 3.625 ++ if (ulen != block_size && i != num_blocks - 1) { 3.626 ++ fprintf(stderr, "Uncomp %s: bad len %u (%lu not %lu)\n", 3.627 ++ packnames[flags], i, ulen, block_size); 3.628 ++ exit(1); 3.629 ++ } 3.630 ++ } 3.631 + } 3.632 +- fprintf(stderr, " => %lu\n", destlen); 3.633 +- if (destlen != block_size && i != num_blocks - 1) { 3.634 +- fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i, 3.635 +- destlen, block_size); 3.636 +- exit(1); 3.637 ++ write(STDOUT_FILENO, out, ulen); 3.638 ++ n += ulen; 3.639 ++ } 3.640 ++ if (argc > 2) { 3.641 ++ n &= 0x1FF; 3.642 ++ if (n) { 3.643 ++ memset(buffer, 0, 512); 3.644 ++ write(STDOUT_FILENO, buffer, 512 - n); 3.645 + } 3.646 +- write(STDOUT_FILENO, clear_buffer, (lastlen != 0 && (i+1) == num_blocks) ? lastlen : block_size); 3.647 + } 3.648 + return 0; 3.649 + } 3.650 +--- create_compressed_fs.c 3.651 ++++ create_compressed_fs.c 3.652 +@@ -7,10 +7,11 @@ 3.653 + #define ZMAX 9 3.654 + static shrink_t level; 3.655 + static int pass, iter; 3.656 +-static int best_compress(unsigned char *compressed, 3.657 +- unsigned long *compressed_len, 3.658 +- unsigned char *uncompressed, 3.659 +- unsigned long uncompressed_len) 3.660 ++static int best_compress(Bytef *compressed, 3.661 ++ uLongf *compressed_len, 3.662 ++ const Bytef *uncompressed, 3.663 ++ uLong uncompressed_len, 3.664 ++ int dummy) 3.665 + { 3.666 + int i, j, err; 3.667 + unsigned char *buf[2]; 3.668 +@@ -19,6 +20,7 @@ 3.669 + static unsigned char *buffer; 3.670 + static unsigned long buffersz; 3.671 + 3.672 ++ (void) dummy; 3.673 + if (buffersz < *compressed_len) { 3.674 + if (buffer) free(buffer); 3.675 + buffer = (unsigned char *) malloc(buffersz = *compressed_len); 3.676 +@@ -50,9 +52,95 @@ 3.677 + memcpy(compressed, buffer, best); 3.678 + return err; 3.679 + } 3.680 +-#define compress2(a,b,c,d,e) best_compress(a,b,c,d) 3.681 ++#else 3.682 ++#include <stdlib.h> 3.683 ++#include <string.h> 3.684 ++#include <zlib.h> 3.685 + #endif 3.686 ++ 3.687 ++#include <lzma.h> 3.688 ++static int xz_compress(Bytef *compressed, 3.689 ++ uLongf *compressed_len, 3.690 ++ const Bytef *uncompressed, 3.691 ++ uLong uncompressed_len, 3.692 ++ int level) 3.693 ++{ 3.694 ++ int res = Z_ERRNO; 3.695 ++ lzma_stream strm = LZMA_STREAM_INIT; 3.696 ++ 3.697 ++ if (lzma_easy_encoder(&strm, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC32) == LZMA_OK) { 3.698 ++ 3.699 ++ strm.next_in = uncompressed; 3.700 ++ strm.avail_in = uncompressed_len; 3.701 ++ strm.next_out = compressed; 3.702 ++ strm.avail_out = *compressed_len; 3.703 ++ 3.704 ++ if (lzma_code(&strm, LZMA_FINISH) == LZMA_STREAM_END) { 3.705 ++ 3.706 ++ *compressed_len -= strm.avail_out; 3.707 ++ res = Z_OK; 3.708 ++ } 3.709 ++ } 3.710 ++ lzma_end(&strm); 3.711 ++ return res; 3.712 ++} 3.713 ++ 3.714 ++#include <lz4.h> 3.715 ++#include <lz4hc.h> 3.716 ++#ifndef LZ4HC_CLEVEL_MAX 3.717 ++#define LZ4HC_CLEVEL_MAX 12 3.718 ++#endif 3.719 ++static int lz4_compress(Bytef *compressed, 3.720 ++ uLongf *compressed_len, 3.721 ++ const Bytef *uncompressed, 3.722 ++ uLong uncompressed_len, 3.723 ++ int level) 3.724 ++{ 3.725 ++ int res = LZ4_compress_HC((const char *) uncompressed, (char *) compressed, 3.726 ++ uncompressed_len, *compressed_len, LZ4HC_CLEVEL_MAX); 3.727 ++ (void) level; 3.728 ++ if (res <= 0) return Z_ERRNO; 3.729 ++ *compressed_len = res; 3.730 ++ return Z_OK; 3.731 ++} 3.732 ++ 3.733 ++static int setup_compress(Bytef *compressed, 3.734 ++ uLongf *compressed_len, 3.735 ++ const Bytef *uncompressed, 3.736 ++ uLong uncompressed_len, 3.737 ++ int level); 3.738 ++ 3.739 ++static int (*compress3)(Bytef *compressed, 3.740 ++ uLongf *compressed_len, 3.741 ++ const Bytef *uncompressed, 3.742 ++ uLong uncompressed_len, 3.743 ++ int level) = setup_compress; 3.744 + 3.745 ++static int setup_compress(Bytef *compressed, 3.746 ++ uLongf *compressed_len, 3.747 ++ const Bytef *uncompressed, 3.748 ++ uLong uncompressed_len, 3.749 ++ int level) 3.750 ++{ 3.751 ++ char *s = getenv("CLOOP_COMP"); 3.752 ++ if (s && !strcmp(s,"XZ")) { 3.753 ++ compress3 = xz_compress; 3.754 ++ } 3.755 ++ else if (s && !strcmp(s,"LZ4")) { 3.756 ++ compress3 = lz4_compress; 3.757 ++ } 3.758 ++ else 3.759 ++#ifdef FIND_BEST_COMPRESSION 3.760 ++ if (s && !strcmp(s,"GZIP")) { 3.761 ++ compress3 = compress2; 3.762 ++ } 3.763 ++ compress3 = best_compress; 3.764 ++#else 3.765 ++ compress3 = compress2; 3.766 ++#endif 3.767 ++ return compress3(compressed,compressed_len,uncompressed,uncompressed_len,level); 3.768 ++} 3.769 ++ 3.770 + #include <signal.h> 3.771 + 3.772 + /* Creates a compressed file */ 3.773 +@@ -82,9 +170,7 @@ 3.774 + return i; 3.775 + } 3.776 + 3.777 +-#ifdef FIND_BEST_COMPRESSION 3.778 + #include "md5sum.c" 3.779 +-#endif 3.780 + 3.781 + static unsigned n; 3.782 + static unsigned long lastlen, pos; 3.783 +@@ -96,15 +182,23 @@ 3.784 + static char padding[512]; 3.785 + struct cloop_tail tail; 3.786 + unsigned long len; 3.787 ++ int flags = 0; 3.788 + 3.789 +- fprintf(stderr, "Write index for %lu blocks\n", n); 3.790 ++ fprintf(stderr, "Write index for %u blocks\n", n); 3.791 + if (block_size >= 0x1000000) lastlen = 0; 3.792 +- tail.index_size = ntohl(sizeof(*block_index) + 256*(lastlen % 0xFFffFF)); 3.793 ++ if (sig) flags = 0x80; 3.794 ++ if (compress3 == xz_compress) { 3.795 ++ flags |= (CLOOP_COMPRESSOR_XZ << 4); 3.796 ++ } 3.797 ++ if (compress3 == lz4_compress) { 3.798 ++ flags |= (CLOOP_COMPRESSOR_LZ4 << 4); 3.799 ++ } 3.800 ++ tail.index_size = ntohl(sizeof(*block_index) + flags + 256*(lastlen % 0xFFffFF)); 3.801 + tail.num_blocks = ntohl(n); 3.802 + n *= sizeof(*block_index); 3.803 +- len = n + n/1000 + 12; 3.804 ++ len = GZIP_MAX_BUFFER(n); 3.805 + compressed = (unsigned char *) realloc(compressed, len); 3.806 +- if (!compressed || compress2(compressed, &len, (unsigned char *) block_index, 3.807 ++ if (!compressed || compress3(compressed, &len, (unsigned char *) block_index, 3.808 + n, Z_BEST_SPEED) != Z_OK) 3.809 + quit("Index compression failed"); 3.810 + tail.table_size = ntohl(len); 3.811 +@@ -122,11 +216,10 @@ 3.812 + unsigned char *uncompressed; 3.813 + unsigned long len; 3.814 + unsigned indexmax, zlenmax; 3.815 +-#ifdef FIND_BEST_COMPRESSION 3.816 +- unsigned i, j, hashmax; 3.817 ++ unsigned i, j, hashmax, domd5; 3.818 + md5hash *hash; 3.819 +-#endif 3.820 + 3.821 ++ domd5 = getenv("CLOOP_NOMD5") == NULL; 3.822 + #ifdef FIND_BEST_COMPRESSION 3.823 + while (argc > 1) { 3.824 + if (argv[1][0] == '-') { 3.825 +@@ -141,11 +234,11 @@ 3.826 + } 3.827 + argc--; 3.828 + if (argv[1][0] < '0' || argv[1][0] > '9') 3.829 +- quit("Usage : create_compressed_fs [-n <pass>][ -i <iter>] [block size] < input > output"); 3.830 ++ quit("Usage : [CLOOP_COMP=XZ|GZIP|LZ4] [CLOOP_NOMD5] create_compressed_fs [-n <pass>][ -i <iter>] [block size] < input > output"); 3.831 + #else 3.832 + if (argc > 1) { 3.833 + if (argv[1][0] < '0' || argv[1][0] > '9') 3.834 +- quit("Usage : create_compressed_fs [block size] < input > output"); 3.835 ++ quit("Usage : [CLOOP_COMP=XZ|LZ4] [CLOOP_NOMD5=1] create_compressed_fs [block size] < input > output"); 3.836 + #endif 3.837 + block_size = atoi(argv[1]); 3.838 + } 3.839 +@@ -164,12 +257,8 @@ 3.840 + compressed = (unsigned char *) malloc(zlenmax); 3.841 + uncompressed = (unsigned char *) malloc(block_size); 3.842 + block_index = (u_int32_t *) malloc(indexmax = CHUNK); 3.843 +-#ifdef FIND_BEST_COMPRESSION 3.844 + hash = (md5hash *) malloc(hashmax = CHUNK); 3.845 + if (!compressed || !uncompressed || !block_index || !hash) 3.846 +-#else 3.847 +- if (!compressed || !uncompressed || !block_index) 3.848 +-#endif 3.849 + quit("Malloc failed"); 3.850 + 3.851 + signal(SIGINT,flush_index); 3.852 +@@ -184,39 +273,42 @@ 3.853 + if (!block_index) 3.854 + quit("Realloc"); 3.855 + } 3.856 +-#ifdef FIND_BEST_COMPRESSION 3.857 +- if (n * sizeof(*hash) >= hashmax) { 3.858 +- hash = (md5hash *) realloc(hash, hashmax += CHUNK); 3.859 +- if (!hash) 3.860 +- quit("Realloc hash"); 3.861 +- } 3.862 +- hash[n] = md5sum(uncompressed, len); 3.863 +- j = 0x7FFFFFFF; 3.864 +- if (n < j) 3.865 +- j = n; 3.866 +- for (i = 0; i < j; i++) { 3.867 +- if (* (uint32_t *) &hash[i] == * (uint32_t *) &hash[n] 3.868 +- && !memcmp(&hash[i],&hash[n],sizeof(*hash))) 3.869 +- break; 3.870 +- } 3.871 +- if (i != j) { 3.872 +- block_index[n] = ntohl(0x80000000 | i); 3.873 +- fprintf(stderr, "Block %u length %lu => duplicate %lu\n", 3.874 +- n, block_size, i); 3.875 ++ if (domd5) { 3.876 ++ if (n * sizeof(*hash) >= hashmax) { 3.877 ++ hash = (md5hash *) realloc(hash, hashmax += CHUNK); 3.878 ++ if (!hash) 3.879 ++ quit("Realloc hash"); 3.880 ++ } 3.881 ++ hash[n] = md5sum(uncompressed, len); 3.882 ++ j = 0x7FFFFFFF; 3.883 ++ if (n < j) 3.884 ++ j = n; 3.885 ++ for (i = 0; i < j; i++) { 3.886 ++ if (* (uint32_t *) &hash[i] == * (uint32_t *) &hash[n] 3.887 ++ && !memcmp(&hash[i],&hash[n],sizeof(*hash))) 3.888 ++ break; 3.889 ++ } 3.890 ++ if (i != j) { 3.891 ++ block_index[n] = ntohl(0x80000000 | i); 3.892 ++ fprintf(stderr, "Block %u length %lu => duplicate %u\n", 3.893 ++ n, block_size, i); 3.894 ++ continue; 3.895 ++ } 3.896 + } 3.897 +- else 3.898 +-#endif 3.899 +- { 3.900 +- len = zlenmax; 3.901 +- if (compress2(compressed, &len, uncompressed, lastlen, 3.902 +- Z_BEST_SPEED) != Z_OK) 3.903 +- quit("Compression failed"); 3.904 +- fprintf(stderr, "Block %u length %lu => %lu\n", 3.905 +- n, block_size, len); 3.906 +- write(STDOUT_FILENO, compressed, len); 3.907 +- pos += len; 3.908 ++ len = zlenmax; 3.909 ++ if (compress3(compressed, &len, uncompressed, lastlen, 3.910 ++ Z_BEST_SPEED) != Z_OK || len >= lastlen) { 3.911 ++ len = lastlen; 3.912 ++ block_index[n] = ntohl(0xFFFFFFFF); 3.913 ++ write(STDOUT_FILENO, uncompressed, len); 3.914 ++ } 3.915 ++ else { 3.916 + block_index[n] = ntohl(len); 3.917 ++ write(STDOUT_FILENO, compressed, len); 3.918 + } 3.919 ++ fprintf(stderr, "Block %u length %lu => %lu\n", 3.920 ++ n, block_size, len); 3.921 ++ pos += len; 3.922 + } 3.923 + flush_index(0); 3.924 + return 0;