wok rev 23696

Up libtcplay (3.3)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Apr 27 09:29:39 2020 +0000 (2020-04-27)
parents 1722e3893bac
children 7397cb36a387
files accessx/receipt fusecloop/receipt fusecloop/stuff/fusecloop.u fusecloop/stuff/v4.u libtcplay-dev/receipt libtcplay/receipt lz4-dev/receipt lz4-lib/receipt lz4/receipt qemu/stuff/cloop.u
line diff
     1.1 --- a/accessx/receipt	Mon Apr 27 07:35:16 2020 +0100
     1.2 +++ b/accessx/receipt	Mon Apr 27 09:29:39 2020 +0000
     1.3 @@ -7,7 +7,7 @@
     1.4  MAINTAINER="paul@slitaz.org"
     1.5  LICENSE="GPL2"
     1.6  TARBALL="$PACKAGE${VERSION//./}.tar.gz"
     1.7 -WEB_SITE="http://cita.disability.uiuc.edu/software/accessx/freewareaccessx.php"
     1.8 +WEB_SITE="https://web.archive.org/web/20150801144644/http://cita.disability.uiuc.edu/software/accessx/freewareaccessx.php"
     1.9  WGET_URL="$(dirname $WEB_SITE)/files/$TARBALL"
    1.10  
    1.11  DEPENDS="tk tcl"
     2.1 --- a/fusecloop/receipt	Mon Apr 27 07:35:16 2020 +0100
     2.2 +++ b/fusecloop/receipt	Mon Apr 27 09:29:39 2020 +0000
     2.3 @@ -26,7 +26,6 @@
     2.4  	tar xzf $SOURCES_REPOSITORY/$ADVANCECOMP_TARBALL
     2.5  	sed -i 's/dprintf/d_printf/g' *.h *.c
     2.6  	patch -p0 < $stuff/fusecloop.u
     2.7 -	patch -p0 < $stuff/v4.u
     2.8  	ADVANCECOMP=advancecomp-$ADVANCECOMP_VERSION
     2.9  	cp *.h *.c $ADVANCECOMP
    2.10  	cp create_compressed_fs.c $ADVANCECOMP/redef.cc
     3.1 --- a/fusecloop/stuff/fusecloop.u	Mon Apr 27 07:35:16 2020 +0100
     3.2 +++ b/fusecloop/stuff/fusecloop.u	Mon Apr 27 09:29:39 2020 +0000
     3.3 @@ -1,3 +1,4 @@
     3.4 +=== Add v3 support
     3.5  --- compressed_loop.h
     3.6  +++ compressed_loop.h
     3.7  @@ -41,6 +41,80 @@
     3.8 @@ -858,3 +859,926 @@
     3.9       /*
    3.10       stbuf->st_mode = S_IFREG | 0444;
    3.11       stbuf->st_nlink = 1;
    3.12 +
    3.13 +=== Add v4 support
    3.14 +--- compressed_loop.h
    3.15 ++++ compressed_loop.h
    3.16 +@@ -30,6 +30,54 @@
    3.17 + /* ...padding up to CLOOP_HEADROOM...                 */
    3.18 + /* block_size (32bit number, network order)           */
    3.19 + /* num_blocks (32bit number, network order)           */
    3.20 ++/*
    3.21 ++* Starting with Format V4.0 (cloop version 4.x), cloop can now have two   *
    3.22 ++* alternative structures:                                                 *
    3.23 ++* 1. Header first:                                                        *
    3.24 ++*   +---------------------------- FIXED SIZE ---------------------------+ *
    3.25 ++*   |Signature (128 bytes)                                              | *
    3.26 ++*   |block_size (32bit number, network order)                           | *
    3.27 ++*   |num_blocks (32bit number, network order)                           | *
    3.28 ++*   +--------------------------- VARIABLE SIZE -------------------------+ *
    3.29 ++*   |num_blocks * FlagsOffset (upper 4 bits flags, lower 60 bits offset)| *
    3.30 ++*   |compressed data blocks of variable size ...                        | *
    3.31 ++*   +-------------------------------------------------------------------+ *
    3.32 ++*                                                                         *
    3.33 ++* 2. Footer (header last):                                                *
    3.34 ++*   +--------------------------- VARIABLE SIZE -------------------------+ *
    3.35 ++*   |compressed data blocks of variable size ...                        | *
    3.36 ++*   |num_blocks * FlagsOffset (upper 4 bits flags, lower 60 bits offset)| *
    3.37 ++*   +---------------------------- FIXED SIZE ---------------------------+ *
    3.38 ++*   |Signature (128 bytes)                                              | *
    3.39 ++*   |block_size (32bit number, network order)                           | *
    3.40 ++*   |num_blocks (32bit number, network order)                           | *
    3.41 ++*   +-------------------------------------------------------------------+ *
    3.42 ++*                                                                         *
    3.43 ++* Offsets are always relative to beginning of file, in all formats.       *
    3.44 ++* The block index contains num_blocks+1 offsets, followed (1) or          *
    3.45 ++* preceded (2) by the compressed blocks.                                  *
    3.46 ++*                                                                         *
    3.47 ++*  CLOOP4 flags for each compressed block                                 *
    3.48 ++*  Value   Meaning                                                        *
    3.49 ++*    0     GZIP/7ZIP compression (compatible with V2.0 Format)            *
    3.50 ++*    1     no compression (incompressible data)                           *
    3.51 ++*    2     xz compression (currently best space saver)                    *
    3.52 ++*    3     lz4 compression                                                *
    3.53 ++*    4     lzo compression (fastest)                                      *
    3.54 ++*   15     block link                                                     *
    3.55 ++*/
    3.56 ++/* Get value of first 4 bits */
    3.57 ++#define CLOOP_BLOCK_FLAGS(x)  ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60))
    3.58 ++/* Get value of last 60 bits */
    3.59 ++#define CLOOP_BLOCK_OFFSET(x)  ((x) & 0x0fffffffffffffffLLU)
    3.60 ++
    3.61 ++#define CLOOP_COMPRESSOR_ZLIB  0x0
    3.62 ++#define CLOOP_COMPRESSOR_NONE  0x1
    3.63 ++#define CLOOP_COMPRESSOR_XZ    0x2
    3.64 ++#define CLOOP_COMPRESSOR_LZ4   0x3
    3.65 ++#define CLOOP_COMPRESSOR_LZO   0x4
    3.66 ++#define CLOOP_COMPRESSOR_LINK  0xF
    3.67 ++
    3.68 + 
    3.69 + struct cloop_head
    3.70 + {
    3.71 +@@ -43,47 +91,86 @@
    3.72 + 
    3.73 + struct cloop_tail
    3.74 + {
    3.75 +-	u_int32_t table_size;
    3.76 +-	u_int32_t index_size;
    3.77 ++	u_int32_t table_size; 
    3.78 ++	u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */
    3.79 ++#define CLOOP3_INDEX_SIZE(x)    ((unsigned int)((x) & 0xF))
    3.80 ++#define CLOOP3_BLOCKS_FLAGS(x)  ((unsigned int)((x) & 0x70) >> 4)
    3.81 ++#define CLOOP3_TRUNCATED(x)     ((unsigned int)((x) & 0x80) >> 7)
    3.82 ++#define CLOOP3_LASTLEN(x)       (unsigned int)((x) >> 8)
    3.83 + 	u_int32_t num_blocks;
    3.84 + };
    3.85 + 
    3.86 ++#define GZIP_MAX_BUFFER(n)	((n) + (n)/1000 + 12)
    3.87 ++
    3.88 + struct block_info
    3.89 + {
    3.90 + 	loff_t offset;		/* 64-bit offsets of compressed block */
    3.91 + 	u_int32_t size;		/* 32-bit compressed block size */
    3.92 +-	u_int32_t optidx;	/* 32-bit index number */
    3.93 ++	u_int32_t flags;	/* 32-bit compression flags */
    3.94 ++
    3.95 + };
    3.96 + 
    3.97 +-static inline char *build_index(struct block_info *offsets, unsigned long n)
    3.98 ++static inline char *build_index(struct block_info *offsets, unsigned long n, 
    3.99 ++			unsigned long block_size, unsigned global_flags)
   3.100 + {
   3.101 + 	u_int32_t *ofs32 = (u_int32_t *) offsets;
   3.102 + 	loff_t    *ofs64 = (loff_t *) offsets;
   3.103 +-	
   3.104 ++
   3.105 ++	/* v3 64bits bug: v1 assumed */
   3.106 ++	unsigned long	v3_64;
   3.107 ++	loff_t	prev;
   3.108 ++
   3.109 ++	if (ofs32[0] != 0 && ofs32[1] == 0) {
   3.110 ++		for (v3_64=(n+1)/2, prev=__le64_to_cpu(ofs64[v3_64]);
   3.111 ++		     v3_64 > 0 && __le64_to_cpu(ofs64[--v3_64]) < prev;
   3.112 ++		     prev=__le64_to_cpu(ofs64[v3_64]));
   3.113 ++	}
   3.114 ++
   3.115 + 	if (ofs32[0] == 0) {
   3.116 + 		if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
   3.117 + 			while (n--) {
   3.118 + 				offsets[n].offset = __be64_to_cpu(offsets[n].offset);
   3.119 + 				offsets[n].size = ntohl(offsets[n].size);
   3.120 ++				offsets[n].flags = 0;
   3.121 + 			}
   3.122 + 			return (char *) "128BE accelerated knoppix 1.0";
   3.123 + 		}
   3.124 +-		else { /* V2.0 */
   3.125 +-			loff_t last = __be64_to_cpu(ofs64[n]);
   3.126 +-			while (n--) {
   3.127 ++		else { /* V2.0/V4.0 */
   3.128 ++			loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n]));
   3.129 ++			u_int32_t flags;
   3.130 ++			static char v4[11];
   3.131 ++			unsigned long i = n;
   3.132 ++
   3.133 ++			for (flags = 0; n-- ;) {
   3.134 ++				loff_t data = __be64_to_cpu(ofs64[n]); 
   3.135 ++
   3.136 + 				offsets[n].size = last - 
   3.137 +-					(offsets[n].offset = __be64_to_cpu(ofs64[n])); 
   3.138 ++					(offsets[n].offset = CLOOP_BLOCK_OFFSET(data)); 
   3.139 + 				last = offsets[n].offset;
   3.140 ++				offsets[n].flags = CLOOP_BLOCK_FLAGS(data); 
   3.141 ++				flags |= 1 << offsets[n].flags;
   3.142 ++			}
   3.143 ++			if (flags < 2) return (char *) "64BE v2.0";
   3.144 ++			while (i--) {
   3.145 ++				if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) {
   3.146 ++					offsets[i] = offsets[offsets[i].offset];
   3.147 ++				}
   3.148 ++			}
   3.149 ++			strcpy(v4, (char *) "64BE v4.0a");
   3.150 ++			v4[10] = 'a' + ((flags-1) & 0xF);	// compressors used
   3.151 ++			if (flags > 0x10) {			// with links ?
   3.152 ++				v4[10] += 'A' - 'a';
   3.153 + 			}
   3.154 +-			return (char *) "64BE v2.0";
   3.155 ++			return v4;
   3.156 + 		}
   3.157 + 	}
   3.158 +-	else if (ofs32[1] == 0) { /* V1.0 */
   3.159 ++	else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */
   3.160 + 		loff_t last = __le64_to_cpu(ofs64[n]);
   3.161 + 		while (n--) {
   3.162 + 			offsets[n].size = last - 
   3.163 + 				(offsets[n].offset = __le64_to_cpu(ofs64[n])); 
   3.164 + 			last = offsets[n].offset;
   3.165 ++			offsets[n].flags = 0;
   3.166 + 		}
   3.167 + 		return (char *) "64LE v1.0";
   3.168 + 	}
   3.169 +@@ -93,25 +180,37 @@
   3.170 + 			offsets[n].size = last - 
   3.171 + 				(offsets[n].offset = ntohl(ofs32[n])); 
   3.172 + 			last = offsets[n].offset;
   3.173 ++			offsets[n].flags = 0;
   3.174 + 		}
   3.175 + 		return (char *) "32BE v0.68";
   3.176 + 	}
   3.177 + 	else { /* V3.0 */
   3.178 + 		unsigned long i;
   3.179 + 		loff_t j;
   3.180 ++		static char v3[11];
   3.181 + 		
   3.182 ++		v3_64 = (ofs32[1] == 0) ? 2 : 1;
   3.183 + 		for (i = n; i-- != 0; )
   3.184 +-			offsets[i].size = ntohl(ofs32[i]); 
   3.185 ++			offsets[i].size = ntohl(ofs32[i*v3_64]); 
   3.186 + 		for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
   3.187 + 			offsets[i].offset = j;
   3.188 ++			offsets[i].flags = global_flags;
   3.189 ++			if ((offsets[i].size & 0x80000000) == 0) {
   3.190 ++				j += offsets[i].size;
   3.191 ++			}
   3.192 ++			else if (offsets[i].size == 0xFFFFFFFF) {
   3.193 ++				offsets[i].flags = CLOOP_COMPRESSOR_NONE;
   3.194 ++				j += offsets[i].size = block_size;
   3.195 ++			}
   3.196 ++		}
   3.197 ++		for (i = 0; i < n; i++) {
   3.198 + 			if (offsets[i].size & 0x80000000) {
   3.199 +-				unsigned long k = offsets[i].size & 0x7FFFFFFF;
   3.200 +-				offsets[i].offset = offsets[k].offset;
   3.201 +-				offsets[i].size = offsets[k].size;
   3.202 ++				offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF];
   3.203 + 			}
   3.204 +-			else j += offsets[i].size;
   3.205 + 		}
   3.206 +-		return (char *) "32BE v3.0";
   3.207 ++		strcpy(v3, (char *) (--v3_64) ? "64BE v3.0a" : "32BE v3.0a");
   3.208 ++		v3[10] += global_flags;
   3.209 ++		return v3;
   3.210 + 	}
   3.211 + }
   3.212 + 
   3.213 +--- cloopreader.c
   3.214 ++++ cloopreader.c
   3.215 +@@ -25,6 +25,8 @@
   3.216 + #include "debug.h"
   3.217 + #include "cloopreader.h"
   3.218 + 
   3.219 ++#include "cloopunpack.c"
   3.220 ++
   3.221 + int read_all(int fh, void* block, size_t size){
   3.222 +     bfuncinfo("fh=%d block=0x%lx size=0x%lx",
   3.223 + 	    fh,(ulong)block,(ulong)size);
   3.224 +@@ -50,18 +52,29 @@
   3.225 +     bfuncinfo("fh=%d",fh);
   3.226 +     c->fh=fh;
   3.227 +     struct cloop_head head;
   3.228 +-    OP(read_all(c->fh,&head,sizeof head));   /* read Header */
   3.229 ++    int v4_header_last, flags;
   3.230 ++    loff_t end;
   3.231 ++
   3.232 ++    for (v4_header_last=0;;v4_header_last++) {
   3.233 ++	OP(read_all(c->fh,&head,sizeof head));   /* read Header */
   3.234 ++	if (!memcmp(&head,"#!/bin/sh",9)) break;
   3.235 ++        if (v4_header_last) exit(1);
   3.236 ++	end = lseek(c->fh, 0, SEEK_END); 
   3.237 ++	OP(lseek(c->fh, end - sizeof(head), SEEK_SET)); 
   3.238 ++    }
   3.239 + 
   3.240 +     c->numblocks=ntohl(head.num_blocks);
   3.241 +     c->blocksize=ntohl(head.block_size);
   3.242 + 
   3.243 +     bprintf("block_size=%lx  num_blocks=%x\n", c->blocksize, c->numblocks);
   3.244 ++    if (v4_header_last)
   3.245 ++	OP(lseek(c->fh, end - sizeof(head) - (sizeof(*c->toc) * c->numblocks), SEEK_SET)); 
   3.246 + 
   3.247 +     ALLOC(c->pblock,c->blocksize);
   3.248 + 
   3.249 +     if (c->numblocks + 1 == 0) {
   3.250 + 	struct cloop_tail tail;
   3.251 +-	loff_t end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
   3.252 ++	end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
   3.253 + 	void *p;
   3.254 + 	ulong toclen, len; 
   3.255 + 
   3.256 +@@ -70,21 +83,23 @@
   3.257 + 	c->numblocks = ntohl(tail.num_blocks);
   3.258 + 	c->tocsize = sizeof(*c->toc) * c->numblocks;
   3.259 + 	len = ntohl(tail.table_size);
   3.260 +-	toclen = (ntohl(tail.index_size) & 255) * c->numblocks;
   3.261 ++	flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size));
   3.262 ++	toclen = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * c->numblocks;
   3.263 + 	OP(lseek(c->fh, end - sizeof(tail) - len, SEEK_SET));
   3.264 +         ALLOC(c->toc, sizeof(*c->toc) * c->numblocks);
   3.265 +         ALLOC(p,len);
   3.266 +         OP(read_all(c->fh,p,len));  /* read Data Index */
   3.267 +-	if (uncompress((void *)c->toc,&toclen,p,len) != Z_OK)
   3.268 ++	if (unpack[flags]((void *)c->toc,&toclen,p,len) != Z_OK)
   3.269 + 		exit(1);
   3.270 + 	free(p);
   3.271 +     }
   3.272 +     else {
   3.273 ++	flags = 0;
   3.274 + 	c->tocsize = sizeof(*c->toc) * c->numblocks;
   3.275 +         ALLOC(c->toc,c->tocsize);
   3.276 +         OP(read_all(c->fh,c->toc,c->tocsize));  /* read Data Index */
   3.277 +     }
   3.278 +-    build_index(c->toc, c->numblocks);
   3.279 ++    build_index(c->toc, c->numblocks, c->blocksize, flags);
   3.280 +     c->cblocksizecur=0;
   3.281 +     c->curblock=-1;
   3.282 +     return 0;
   3.283 +@@ -121,7 +136,8 @@
   3.284 + 	    "pblock=0x%lx &destlen=0x%lx cblock=0x%lx cblocksize=%lu\n",
   3.285 + 	    (ulong)c->pblock,(ulong)&destlen,(ulong)c->cblock,c->cblocksize
   3.286 + 	    );
   3.287 +-    switch(uncompress(c->pblock,&destlen,c->cblock,c->cblocksize)){
   3.288 ++    if(c->toc[page].flags <= CLOOP_COMPRESSOR_MAX){
   3.289 ++      switch(unpack[c->toc[page].flags](c->pblock,&destlen,c->cblock,c->cblocksize)){
   3.290 + 	case Z_OK: break;
   3.291 + 	#define entry(x)\
   3.292 + 	case x: bprintf( #x"\n"); break; 
   3.293 +@@ -130,7 +146,9 @@
   3.294 + 	entry(Z_DATA_ERROR)
   3.295 + 	#undef entry
   3.296 + 	default: bprintf("Z_UNKNOWN_ERROR\n");
   3.297 ++      }
   3.298 +     }
   3.299 ++    else bprintf("Unsuppoted compression type\n");
   3.300 +     if(destlen!=c->blocksize)bprintf("Size mismatch\n");
   3.301 +     return 0;
   3.302 + }
   3.303 +--- /dev/null
   3.304 ++++ cloopunpack.c
   3.305 +@@ -0,0 +1,74 @@
   3.306 ++
   3.307 ++static int none_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   3.308 ++{
   3.309 ++	memcpy(dest,source,*destLen = sourceLen);
   3.310 ++	return Z_OK;
   3.311 ++}
   3.312 ++
   3.313 ++#include <lzma.h>
   3.314 ++static int xz_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   3.315 ++{
   3.316 ++        size_t src_pos = 0;
   3.317 ++        size_t dest_pos = 0;
   3.318 ++        uint64_t memlimit = 32*1024*1024;
   3.319 ++
   3.320 ++        lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,
   3.321 ++                        source, &src_pos, sourceLen, dest, &dest_pos, *destLen);
   3.322 ++
   3.323 ++        if(res == LZMA_OK && sourceLen == (int) src_pos) {
   3.324 ++                *destLen = dest_pos;
   3.325 ++		return Z_OK;
   3.326 ++	}
   3.327 ++        else return Z_ERRNO;
   3.328 ++}
   3.329 ++
   3.330 ++#include <lz4.h>
   3.331 ++static int lz4_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   3.332 ++{
   3.333 ++	long size = LZ4_decompress_safe((const char *) source, (char *) dest, sourceLen, *destLen);
   3.334 ++
   3.335 ++	if (size < 0) return Z_ERRNO;
   3.336 ++        *destLen = size;
   3.337 ++	return Z_OK;
   3.338 ++}
   3.339 ++
   3.340 ++#include <lzo/lzo1x.h>
   3.341 ++static int lzo_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   3.342 ++{
   3.343 ++	lzo_uint outlen = *destLen;
   3.344 ++
   3.345 ++	if (lzo1x_decompress_safe(source, sourceLen, dest, &outlen, NULL) == LZO_E_OK) {
   3.346 ++                *destLen = outlen;
   3.347 ++		return Z_OK;
   3.348 ++	}
   3.349 ++        else return Z_ERRNO;
   3.350 ++}
   3.351 ++
   3.352 ++#include <zstd.h>
   3.353 ++static int zstd_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   3.354 ++{
   3.355 ++        const size_t res = ZSTD_decompress(dest, *destLen, source, sourceLen);
   3.356 ++
   3.357 ++        if (ZSTD_isError(res)) {
   3.358 ++                return Z_ERRNO;
   3.359 ++        }
   3.360 ++
   3.361 ++	*destLen = res;
   3.362 ++        return Z_OK;
   3.363 ++}
   3.364 ++
   3.365 ++#define CLOOP_COMPRESSOR_ZSTD  0x5
   3.366 ++
   3.367 ++#define CLOOP_COMPRESSOR_MAX CLOOP_COMPRESSOR_ZSTD
   3.368 ++
   3.369 ++#define CLOOP_COMPRESSOR_NAMES	"gzip","copy","xz","lz4","lzo","zstd"
   3.370 ++
   3.371 ++static int (*unpack[CLOOP_COMPRESSOR_MAX+1])(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen) = {
   3.372 ++	uncompress,
   3.373 ++	none_uncompress,
   3.374 ++	xz_uncompress,
   3.375 ++	lz4_uncompress,
   3.376 ++	lzo_uncompress,
   3.377 ++	zstd_uncompress
   3.378 ++};
   3.379 ++
   3.380 +--- extract_compressed_fs.c
   3.381 ++++ extract_compressed_fs.c
   3.382 +@@ -3,14 +3,19 @@
   3.383 + #include "common_header.h"
   3.384 + #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.385 + 
   3.386 ++#include "cloopunpack.c"
   3.387 ++static char *packnames[CLOOP_COMPRESSOR_MAX+1] = { CLOOP_COMPRESSOR_NAMES };
   3.388 ++
   3.389 + int main(int argc, char *argv[])
   3.390 + {
   3.391 +-	int handle;
   3.392 ++	int handle, err;
   3.393 + 	struct cloop_head head;
   3.394 +-	unsigned int i;
   3.395 +-	unsigned long num_blocks, block_size, zblock_maxsize, lastlen = 0;
   3.396 ++	unsigned int i, v4_header_last, global_flags;
   3.397 ++	unsigned long n, num_blocks, block_size, zblock_maxsize, len;
   3.398 ++	uLongf ulen;
   3.399 + 	unsigned char *buffer, *clear_buffer;
   3.400 + 	struct block_info *offsets;
   3.401 ++	loff_t end;
   3.402 + 
   3.403 + 	if (argc < 2 || argv[1][0] == '-') {
   3.404 + 		fprintf(stderr, "Usage: extract_compressed_fs file [--convert-to-v2] > output\n");
   3.405 +@@ -23,23 +28,35 @@
   3.406 + 		exit(1);
   3.407 + 	}
   3.408 + 
   3.409 +-	if (read(handle, &head, sizeof(head)) != sizeof(head)) {
   3.410 +-		perror("Reading compressed file header\n");
   3.411 ++	for (v4_header_last=0;; v4_header_last++) {
   3.412 ++		if (read(handle, &head, sizeof(head)) != sizeof(head)) {
   3.413 ++			perror("Reading compressed file header\n");
   3.414 ++			exit(1);
   3.415 ++		}
   3.416 ++		if (!memcmp(&head,"#!/bin/sh",9)) break;
   3.417 ++		end = lseek64(handle, 0, SEEK_END);
   3.418 ++		lseek64(handle, end - sizeof(head), SEEK_SET);
   3.419 ++		if (v4_header_last == 0) continue;
   3.420 ++		perror("Not a cloop file\n");
   3.421 + 		exit(1);
   3.422 + 	}
   3.423 + 
   3.424 + 	num_blocks = ntohl(head.num_blocks);
   3.425 + 	block_size = ntohl(head.block_size);
   3.426 +-	zblock_maxsize =  block_size + block_size/1000 + 12 + 4;
   3.427 ++	zblock_maxsize = GZIP_MAX_BUFFER(block_size);
   3.428 + 	buffer = malloc(zblock_maxsize);
   3.429 + 	clear_buffer = malloc(block_size);
   3.430 + 
   3.431 ++	if (v4_header_last) {
   3.432 ++		lseek64(handle, end - ((num_blocks+1) * sizeof(loff_t)) - sizeof(head), SEEK_SET);
   3.433 ++	}
   3.434 ++
   3.435 + 	if (num_blocks == 0xFFFFFFFF) {
   3.436 + 		void *table;
   3.437 + 		struct cloop_tail tail;
   3.438 +-		unsigned long len, table_size;
   3.439 +-		loff_t end = lseek64(handle, 0, SEEK_END);
   3.440 ++		unsigned long table_size;
   3.441 + 		
   3.442 ++		end = lseek64(handle, 0, SEEK_END);
   3.443 + 		if (lseek64(handle, end - sizeof(tail), SEEK_SET) < 0 ||
   3.444 + 		    read(handle, &tail, sizeof(tail)) != sizeof(tail) ||
   3.445 + 		    lseek64(handle, end - sizeof(tail) - 
   3.446 +@@ -51,60 +68,91 @@
   3.447 + 		num_blocks = ntohl(head.num_blocks);
   3.448 + 		table_size = ntohl(tail.table_size);
   3.449 + 		table = malloc(table_size);
   3.450 +-		len = i = num_blocks * (ntohl(tail.index_size) & 255);
   3.451 +-		lastlen = ntohl(tail.index_size) / 256;
   3.452 +-		offsets = malloc(num_blocks * sizeof(*offsets));
   3.453 +-		if (!table || !offsets || 
   3.454 +-		    read(handle, table, table_size) != table_size ||
   3.455 +-		    uncompress((void *)offsets, &len, table, table_size) != Z_OK ||
   3.456 +-		    len != i) {
   3.457 ++		len = num_blocks * CLOOP3_INDEX_SIZE(ntohl(tail.index_size));
   3.458 ++		global_flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size));
   3.459 ++		if (global_flags > CLOOP_COMPRESSOR_MAX) {
   3.460 ++			fprintf(stderr, "Unsupported compression %d\n",
   3.461 ++				global_flags);
   3.462 ++			exit(1);
   3.463 ++		}
   3.464 ++		ulen = num_blocks * sizeof(*offsets);
   3.465 ++		offsets = malloc(ulen);
   3.466 ++		if (!table || !offsets || !buffer || !clear_buffer) {
   3.467 ++			fprintf(stderr,"Out of memory\n");
   3.468 ++			exit(1);
   3.469 ++		}
   3.470 ++		if (read(handle, table, table_size) != table_size) {
   3.471 + 			perror("Reading index\n");
   3.472 + 			exit(1);
   3.473 + 		}
   3.474 ++		err = unpack[global_flags]((void *) offsets, &ulen, table, table_size);
   3.475 ++		if (err != Z_OK) {
   3.476 ++			fprintf(stderr, "Unpack %s index error %d\n",
   3.477 ++				packnames[global_flags],err);
   3.478 ++			exit(1);
   3.479 ++		}
   3.480 + 		free(table);
   3.481 + 	}
   3.482 + 	else {
   3.483 +-		offsets = malloc(i = num_blocks * sizeof(*offsets));
   3.484 +-		if (!offsets || read(handle, offsets, i) != i) {
   3.485 ++		global_flags = 0;
   3.486 ++		len = num_blocks * sizeof(*offsets);
   3.487 ++		offsets = malloc(len);
   3.488 ++		if (v4_header_last) {
   3.489 ++			len = (num_blocks+1) * sizeof(loff_t);
   3.490 ++		}
   3.491 ++		if (!offsets || !buffer || !clear_buffer) {
   3.492 ++			fprintf(stderr,"Out of memory\n");
   3.493 ++			exit(1);
   3.494 ++		}
   3.495 ++		if (read(handle, offsets, len) != len) {
   3.496 + 			perror("Reading index\n");
   3.497 + 			exit(1);
   3.498 + 		}
   3.499 + 	}
   3.500 + 	
   3.501 ++	if (v4_header_last) {
   3.502 ++		lseek64(handle, 0, SEEK_SET);
   3.503 ++	}
   3.504 ++
   3.505 + 	fprintf(stderr, "%lu blocks of size %lu. Preamble:\n%s\n", 
   3.506 + 		num_blocks, block_size, head.preamble);
   3.507 +-	fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks));
   3.508 ++#if 1
   3.509 ++	if (getenv("CLOOP_INDEX") != NULL) {
   3.510 ++		fprintf(stderr, "CLOOP_INDEX: binary\n");
   3.511 ++		write(STDOUT_FILENO, offsets, len);
   3.512 ++		exit(0);
   3.513 ++	}
   3.514 ++#endif
   3.515 ++	fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks, block_size, global_flags));
   3.516 + 	
   3.517 ++#if 1
   3.518 ++	if (getenv("CLOOP_TABLE") != NULL) {
   3.519 ++		fprintf(stderr, "CLOOP_TABLE ascii: offset, size, flags\n");
   3.520 ++		for (i = 0; i < num_blocks; i++) {
   3.521 ++			printf("%llu  %u  %u\n",
   3.522 ++				offsets[i].offset,
   3.523 ++				offsets[i].size,
   3.524 ++				offsets[i].flags);
   3.525 ++		}
   3.526 ++		exit(0);
   3.527 ++	}
   3.528 ++#endif
   3.529 ++
   3.530 + 	if (argc > 2) {
   3.531 +-		unsigned n;
   3.532 +-		loff_t data, offset = ((num_blocks + 1) * sizeof(offset)) + sizeof(head);
   3.533 ++		loff_t data, ofs = ((num_blocks + 1) * sizeof(ofs)) + sizeof(head);
   3.534 + 		
   3.535 + 		strcpy(head.preamble, CLOOP_PREAMBLE);
   3.536 + 		write(STDOUT_FILENO, &head, n = sizeof(head));
   3.537 +-		for (i = 0; i < num_blocks; i++) {
   3.538 +-			data = __be64_to_cpu(offset);
   3.539 ++		for (i = 0; i <= num_blocks; i++) {
   3.540 ++			data = __be64_to_cpu(ofs);
   3.541 + 			write(STDOUT_FILENO, &data, sizeof(data));
   3.542 + 			n += sizeof(data);
   3.543 +-			offset += offsets[i].size;
   3.544 ++			ofs += offsets[i].size;
   3.545 + 		}
   3.546 +-		data = __be64_to_cpu(offset);
   3.547 +-		write(STDOUT_FILENO, &data, sizeof(data));
   3.548 +-		for (i = 0; i < num_blocks && lseek64(handle, offsets[i].offset, SEEK_SET) >= 0; i++) {
   3.549 +-			read(handle, buffer, offsets[i].size);
   3.550 +-			write(STDOUT_FILENO, buffer, offsets[i].size);
   3.551 +-			n += offsets[i].size;
   3.552 +-		}
   3.553 +-		n &= 0x1FF;
   3.554 +-		if (n) {
   3.555 +-			memset(buffer, 0, 512);
   3.556 +-			write(STDOUT_FILENO, buffer, 512 - n);
   3.557 +-		}
   3.558 +-		return 0;
   3.559 + 	}
   3.560 +-	
   3.561 + 	for (i = 0; i < num_blocks; i++) {
   3.562 +-		unsigned long destlen = block_size;
   3.563 +-		unsigned int size = offsets[i].size;
   3.564 ++		unsigned char *out;
   3.565 ++		int flags = offsets[i].flags;
   3.566 + 
   3.567 + 		if (lseek64(handle, offsets[i].offset, SEEK_SET) < 0) {
   3.568 + 			fprintf(stderr, "lseek to %Lu: %s\n",
   3.569 +@@ -112,44 +160,61 @@
   3.570 + 			exit(1);
   3.571 + 		}
   3.572 +                 
   3.573 +-		if (size > zblock_maxsize) {
   3.574 ++		len = offsets[i].size;
   3.575 ++		if (len > zblock_maxsize) {
   3.576 + 			fprintf(stderr, 
   3.577 + 				"Size %u for block %u (offset %Lu) too big\n",
   3.578 +-				size, i, offsets[i].offset);
   3.579 ++				len, i, offsets[i].offset);
   3.580 + 			exit(1);
   3.581 + 		}
   3.582 +-		read(handle, buffer, size);
   3.583 +-
   3.584 +-		fprintf(stderr, "Block %u at %llu length %u",
   3.585 +-			i, offsets[i].offset, size);
   3.586 +-		switch (uncompress(clear_buffer, &destlen,
   3.587 +-				   buffer, size)) {
   3.588 +-		case Z_OK:
   3.589 +-			break;
   3.590 + 
   3.591 +-		case Z_MEM_ERROR:
   3.592 +-			fprintf(stderr, "Uncomp: oom block %u\n", i);
   3.593 +-			exit(1);
   3.594 +-
   3.595 +-		case Z_BUF_ERROR:
   3.596 +-			fprintf(stderr, "Uncomp: not enough out room %u\n", i);
   3.597 +-			exit(1);
   3.598 +-
   3.599 +-		case Z_DATA_ERROR:
   3.600 +-			fprintf(stderr, "Uncomp: input corrupt %u\n", i);
   3.601 ++		if (argc <= 2) {
   3.602 ++			fprintf(stderr, "Block %u at %llu length %lu ",
   3.603 ++				i, offsets[i].offset, len);
   3.604 ++		}
   3.605 ++
   3.606 ++		read(handle, out = buffer, ulen = len);
   3.607 ++
   3.608 ++		if (flags > CLOOP_COMPRESSOR_MAX) {
   3.609 ++			fprintf(stderr, "Block %u: unsupported compression %d \n",
   3.610 ++				i, flags);
   3.611 + 			exit(1);
   3.612 ++		}
   3.613 + 
   3.614 +-		default:
   3.615 +-			fprintf(stderr, "Uncomp: unknown error %u\n", i);
   3.616 +-			exit(1);
   3.617 ++		if (flags != CLOOP_COMPRESSOR_ZLIB || argc <= 2) {
   3.618 ++			ulen = block_size;
   3.619 ++			err = unpack[flags](out = clear_buffer, &ulen, buffer, len);
   3.620 ++			if (err != Z_OK) {
   3.621 ++				fprintf(stderr, "Unpack %s block %u error %d \n",
   3.622 ++					packnames[flags], i, err);
   3.623 ++				exit(1);
   3.624 ++			}
   3.625 ++			if (argc > 2) {
   3.626 ++				err = compress2(out = buffer, &ulen, clear_buffer, ulen, Z_BEST_SPEED);
   3.627 ++				if (err != Z_OK) {
   3.628 ++					fprintf(stderr, "Compress %s block %u error %d \n",
   3.629 ++						packnames[flags], i, err);
   3.630 ++					exit(1);
   3.631 ++				}
   3.632 ++			}
   3.633 ++			else {
   3.634 ++				fprintf(stderr, "=> %lu\n", ulen);
   3.635 ++				if (ulen != block_size && i != num_blocks - 1) {
   3.636 ++					fprintf(stderr, "Uncomp %s: bad len %u (%lu not %lu)\n",
   3.637 ++						packnames[flags], i, ulen, block_size);
   3.638 ++					exit(1);
   3.639 ++				}
   3.640 ++			}
   3.641 + 		}
   3.642 +-		fprintf(stderr, " => %lu\n", destlen);
   3.643 +-		if (destlen != block_size && i != num_blocks - 1) {
   3.644 +-			fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i,
   3.645 +-				destlen, block_size);
   3.646 +-			exit(1);
   3.647 ++		write(STDOUT_FILENO, out, ulen);
   3.648 ++		n += ulen;
   3.649 ++	}
   3.650 ++	if (argc > 2) {
   3.651 ++		n &= 0x1FF;
   3.652 ++		if (n) {
   3.653 ++			memset(buffer, 0, 512);
   3.654 ++			write(STDOUT_FILENO, buffer, 512 - n);
   3.655 + 		}
   3.656 +-		write(STDOUT_FILENO, clear_buffer, (lastlen != 0 && (i+1) == num_blocks) ? lastlen : block_size);
   3.657 + 	}
   3.658 + 	return 0;
   3.659 + }
   3.660 +--- create_compressed_fs.c
   3.661 ++++ create_compressed_fs.c
   3.662 +@@ -7,10 +7,11 @@
   3.663 + #define ZMAX 9
   3.664 + static shrink_t level;
   3.665 + static int pass, iter;
   3.666 +-static int best_compress(unsigned char *compressed,
   3.667 +-			 unsigned long *compressed_len,
   3.668 +-			 unsigned char *uncompressed,
   3.669 +-			 unsigned long uncompressed_len)
   3.670 ++static int best_compress(Bytef *compressed,
   3.671 ++			uLongf *compressed_len,
   3.672 ++			const Bytef *uncompressed,
   3.673 ++			uLong uncompressed_len,
   3.674 ++			int dummy)
   3.675 + {
   3.676 + 	int i, j, err;
   3.677 + 	unsigned char *buf[2];
   3.678 +@@ -19,6 +20,7 @@
   3.679 + 	static unsigned char *buffer;
   3.680 + 	static unsigned long buffersz;
   3.681 + 
   3.682 ++	(void) dummy;
   3.683 + 	if (buffersz < *compressed_len) {
   3.684 + 		if (buffer) free(buffer);
   3.685 + 		buffer = (unsigned char *)  malloc(buffersz = *compressed_len);
   3.686 +@@ -50,9 +52,95 @@
   3.687 + 		memcpy(compressed, buffer, best);
   3.688 + 	return err;
   3.689 + }
   3.690 +-#define compress2(a,b,c,d,e) best_compress(a,b,c,d)
   3.691 ++#else
   3.692 ++#include <stdlib.h>
   3.693 ++#include <string.h>
   3.694 ++#include <zlib.h>
   3.695 + #endif
   3.696 ++
   3.697 ++#include <lzma.h>
   3.698 ++static int xz_compress(Bytef *compressed,
   3.699 ++			uLongf *compressed_len,
   3.700 ++			const Bytef *uncompressed,
   3.701 ++			uLong uncompressed_len,
   3.702 ++			int level)
   3.703 ++{
   3.704 ++	int res = Z_ERRNO;
   3.705 ++	lzma_stream strm = LZMA_STREAM_INIT;
   3.706 ++
   3.707 ++	if (lzma_easy_encoder(&strm, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC32) == LZMA_OK) {
   3.708 ++
   3.709 ++		strm.next_in = uncompressed;
   3.710 ++		strm.avail_in = uncompressed_len;
   3.711 ++		strm.next_out = compressed;
   3.712 ++		strm.avail_out = *compressed_len;
   3.713 ++
   3.714 ++		if (lzma_code(&strm, LZMA_FINISH) == LZMA_STREAM_END) {
   3.715 ++
   3.716 ++			*compressed_len -= strm.avail_out;
   3.717 ++			res = Z_OK;
   3.718 ++		}
   3.719 ++	}
   3.720 ++	lzma_end(&strm);
   3.721 ++	return res;
   3.722 ++}
   3.723 ++
   3.724 ++#include <lz4.h>
   3.725 ++#include <lz4hc.h>
   3.726 ++#ifndef LZ4HC_CLEVEL_MAX
   3.727 ++#define LZ4HC_CLEVEL_MAX 12
   3.728 ++#endif
   3.729 ++static int lz4_compress(Bytef *compressed,
   3.730 ++			uLongf *compressed_len,
   3.731 ++			const Bytef *uncompressed,
   3.732 ++			uLong uncompressed_len,
   3.733 ++			int level)
   3.734 ++{
   3.735 ++	int res = LZ4_compress_HC((const char *) uncompressed, (char *) compressed,
   3.736 ++			 uncompressed_len, *compressed_len, LZ4HC_CLEVEL_MAX);
   3.737 ++	(void) level;
   3.738 ++	if (res <= 0) return Z_ERRNO;
   3.739 ++	*compressed_len = res;
   3.740 ++	return Z_OK;
   3.741 ++}
   3.742 ++
   3.743 ++static int setup_compress(Bytef *compressed,
   3.744 ++			uLongf *compressed_len,
   3.745 ++			const Bytef *uncompressed,
   3.746 ++			uLong uncompressed_len,
   3.747 ++			int level);
   3.748 ++
   3.749 ++static int (*compress3)(Bytef *compressed,
   3.750 ++			uLongf *compressed_len,
   3.751 ++			const Bytef *uncompressed,
   3.752 ++			uLong uncompressed_len,
   3.753 ++			int level) = setup_compress;
   3.754 +                         
   3.755 ++static int setup_compress(Bytef *compressed,
   3.756 ++			uLongf *compressed_len,
   3.757 ++			const Bytef *uncompressed,
   3.758 ++			uLong uncompressed_len,
   3.759 ++			int level)
   3.760 ++{
   3.761 ++	char *s = getenv("CLOOP_COMP");
   3.762 ++	if (s && !strcmp(s,"XZ")) {
   3.763 ++		compress3 = xz_compress;
   3.764 ++	}
   3.765 ++	else if (s && !strcmp(s,"LZ4")) {
   3.766 ++		compress3 = lz4_compress;
   3.767 ++	}
   3.768 ++	else
   3.769 ++#ifdef FIND_BEST_COMPRESSION
   3.770 ++	if (s && !strcmp(s,"GZIP")) {
   3.771 ++		compress3 = compress2;
   3.772 ++	}
   3.773 ++	compress3 = best_compress;
   3.774 ++#else
   3.775 ++	compress3 = compress2;
   3.776 ++#endif
   3.777 ++	return compress3(compressed,compressed_len,uncompressed,uncompressed_len,level);
   3.778 ++}
   3.779 ++
   3.780 + #include <signal.h>
   3.781 + 
   3.782 + /* Creates a compressed file */
   3.783 +@@ -82,9 +170,7 @@
   3.784 + 	return i;
   3.785 + }
   3.786 + 
   3.787 +-#ifdef FIND_BEST_COMPRESSION
   3.788 + #include "md5sum.c"
   3.789 +-#endif
   3.790 + 
   3.791 + static unsigned n;
   3.792 + static unsigned long lastlen, pos;
   3.793 +@@ -96,15 +182,23 @@
   3.794 + 	static char padding[512];
   3.795 + 	struct cloop_tail tail;
   3.796 + 	unsigned long len;
   3.797 ++	int flags = 0;
   3.798 + 
   3.799 +-	fprintf(stderr, "Write index for %lu blocks\n", n);
   3.800 ++	fprintf(stderr, "Write index for %u blocks\n", n);
   3.801 + 	if (block_size >= 0x1000000) lastlen = 0;
   3.802 +-	tail.index_size = ntohl(sizeof(*block_index) + 256*(lastlen % 0xFFffFF));
   3.803 ++	if (sig) flags = 0x80;
   3.804 ++	if (compress3 == xz_compress) {
   3.805 ++		flags |= (CLOOP_COMPRESSOR_XZ << 4);
   3.806 ++	}
   3.807 ++	if (compress3 == lz4_compress) {
   3.808 ++		flags |= (CLOOP_COMPRESSOR_LZ4 << 4);
   3.809 ++	}
   3.810 ++	tail.index_size = ntohl(sizeof(*block_index) + flags + 256*(lastlen % 0xFFffFF));
   3.811 + 	tail.num_blocks = ntohl(n);
   3.812 + 	n *= sizeof(*block_index);
   3.813 +-	len = n + n/1000 + 12;
   3.814 ++	len = GZIP_MAX_BUFFER(n);
   3.815 + 	compressed = (unsigned char *) realloc(compressed, len);
   3.816 +-	if (!compressed || compress2(compressed, &len, (unsigned char *) block_index,
   3.817 ++	if (!compressed || compress3(compressed, &len, (unsigned char *) block_index,
   3.818 + 				     n, Z_BEST_SPEED) != Z_OK)
   3.819 + 		quit("Index compression failed");
   3.820 + 	tail.table_size = ntohl(len);
   3.821 +@@ -122,11 +216,10 @@
   3.822 + 	unsigned char *uncompressed;
   3.823 + 	unsigned long len;
   3.824 + 	unsigned indexmax, zlenmax;
   3.825 +-#ifdef FIND_BEST_COMPRESSION
   3.826 +-	unsigned i, j, hashmax;
   3.827 ++	unsigned i, j, hashmax, domd5;
   3.828 + 	md5hash *hash;
   3.829 +-#endif
   3.830 + 	
   3.831 ++	domd5 = getenv("CLOOP_NOMD5") == NULL;
   3.832 + #ifdef FIND_BEST_COMPRESSION
   3.833 + 	while (argc > 1) {
   3.834 + 		if (argv[1][0] == '-') {
   3.835 +@@ -141,11 +234,11 @@
   3.836 + 		}
   3.837 + 		argc--;
   3.838 + 		if (argv[1][0] < '0' || argv[1][0] > '9')
   3.839 +-			quit("Usage : create_compressed_fs [-n <pass>][ -i <iter>] [block size] < input > output");
   3.840 ++			quit("Usage : [CLOOP_COMP=XZ|GZIP|LZ4] [CLOOP_NOMD5] create_compressed_fs [-n <pass>][ -i <iter>] [block size] < input > output");
   3.841 + #else
   3.842 + 	if (argc > 1) {
   3.843 + 		if (argv[1][0] < '0' || argv[1][0] > '9')
   3.844 +-			quit("Usage : create_compressed_fs [block size] < input > output");
   3.845 ++			quit("Usage : [CLOOP_COMP=XZ|LZ4] [CLOOP_NOMD5=1] create_compressed_fs [block size] < input > output");
   3.846 + #endif
   3.847 + 		block_size = atoi(argv[1]);
   3.848 + 	}
   3.849 +@@ -164,12 +257,8 @@
   3.850 + 	compressed = (unsigned char *) malloc(zlenmax);
   3.851 + 	uncompressed = (unsigned char *) malloc(block_size);
   3.852 + 	block_index = (u_int32_t *) malloc(indexmax = CHUNK);
   3.853 +-#ifdef FIND_BEST_COMPRESSION
   3.854 + 	hash = (md5hash *) malloc(hashmax = CHUNK);
   3.855 + 	if (!compressed || !uncompressed || !block_index || !hash)
   3.856 +-#else
   3.857 +-	if (!compressed || !uncompressed || !block_index)
   3.858 +-#endif
   3.859 + 		quit("Malloc failed");
   3.860 + 	
   3.861 + 	signal(SIGINT,flush_index);
   3.862 +@@ -184,39 +273,42 @@
   3.863 + 			if (!block_index)
   3.864 + 				quit("Realloc");
   3.865 + 		}
   3.866 +-#ifdef FIND_BEST_COMPRESSION
   3.867 +-		if (n * sizeof(*hash) >= hashmax) {
   3.868 +-			hash = (md5hash *) realloc(hash, hashmax += CHUNK);
   3.869 +-			if (!hash)
   3.870 +-				quit("Realloc hash");
   3.871 +-		}
   3.872 +-		hash[n] = md5sum(uncompressed, len);
   3.873 +-		j = 0x7FFFFFFF;
   3.874 +-		if (n < j)
   3.875 +-			j = n;
   3.876 +-		for (i = 0; i < j; i++) {
   3.877 +-			if (* (uint32_t *) &hash[i] == * (uint32_t *) &hash[n]
   3.878 +-			    && !memcmp(&hash[i],&hash[n],sizeof(*hash)))
   3.879 +-				break;
   3.880 +-		}
   3.881 +-		if (i != j) {
   3.882 +-			block_index[n] = ntohl(0x80000000 | i);
   3.883 +-			fprintf(stderr, "Block %u length %lu => duplicate %lu\n",
   3.884 +-				n, block_size, i);
   3.885 ++		if (domd5) {
   3.886 ++			if (n * sizeof(*hash) >= hashmax) {
   3.887 ++				hash = (md5hash *) realloc(hash, hashmax += CHUNK);
   3.888 ++				if (!hash)
   3.889 ++					quit("Realloc hash");
   3.890 ++			}
   3.891 ++			hash[n] = md5sum(uncompressed, len);
   3.892 ++			j = 0x7FFFFFFF;
   3.893 ++			if (n < j)
   3.894 ++				j = n;
   3.895 ++			for (i = 0; i < j; i++) {
   3.896 ++				if (* (uint32_t *) &hash[i] == * (uint32_t *) &hash[n]
   3.897 ++				    && !memcmp(&hash[i],&hash[n],sizeof(*hash)))
   3.898 ++					break;
   3.899 ++			}
   3.900 ++			if (i != j) {
   3.901 ++				block_index[n] = ntohl(0x80000000 | i);
   3.902 ++				fprintf(stderr, "Block %u length %lu => duplicate %u\n",
   3.903 ++					n, block_size, i);
   3.904 ++				continue;
   3.905 ++			}
   3.906 + 		}
   3.907 +-		else
   3.908 +-#endif
   3.909 +-		{
   3.910 +-			len = zlenmax;
   3.911 +-			if (compress2(compressed, &len, uncompressed, lastlen, 
   3.912 +-					Z_BEST_SPEED) != Z_OK)
   3.913 +-				quit("Compression failed");
   3.914 +-			fprintf(stderr, "Block %u length %lu => %lu\n",
   3.915 +-				n, block_size, len);
   3.916 +-			write(STDOUT_FILENO, compressed, len);
   3.917 +-			pos += len;
   3.918 ++		len = zlenmax;
   3.919 ++		if (compress3(compressed, &len, uncompressed, lastlen, 
   3.920 ++				Z_BEST_SPEED) != Z_OK || len >= lastlen) {
   3.921 ++			len = lastlen;
   3.922 ++			block_index[n] = ntohl(0xFFFFFFFF);
   3.923 ++			write(STDOUT_FILENO, uncompressed, len);
   3.924 ++		}
   3.925 ++		else {
   3.926 + 			block_index[n] = ntohl(len);
   3.927 ++			write(STDOUT_FILENO, compressed, len);
   3.928 + 		}
   3.929 ++		fprintf(stderr, "Block %u length %lu => %lu\n",
   3.930 ++			n, block_size, len);
   3.931 ++		pos += len;
   3.932 + 	}
   3.933 + 	flush_index(0);
   3.934 + 	return 0;
     4.1 --- a/fusecloop/stuff/v4.u	Mon Apr 27 07:35:16 2020 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,921 +0,0 @@
     4.4 ---- compressed_loop.h
     4.5 -+++ compressed_loop.h
     4.6 -@@ -30,6 +30,54 @@
     4.7 - /* ...padding up to CLOOP_HEADROOM...                 */
     4.8 - /* block_size (32bit number, network order)           */
     4.9 - /* num_blocks (32bit number, network order)           */
    4.10 -+/*
    4.11 -+* Starting with Format V4.0 (cloop version 4.x), cloop can now have two   *
    4.12 -+* alternative structures:                                                 *
    4.13 -+* 1. Header first:                                                        *
    4.14 -+*   +---------------------------- FIXED SIZE ---------------------------+ *
    4.15 -+*   |Signature (128 bytes)                                              | *
    4.16 -+*   |block_size (32bit number, network order)                           | *
    4.17 -+*   |num_blocks (32bit number, network order)                           | *
    4.18 -+*   +--------------------------- VARIABLE SIZE -------------------------+ *
    4.19 -+*   |num_blocks * FlagsOffset (upper 4 bits flags, lower 60 bits offset)| *
    4.20 -+*   |compressed data blocks of variable size ...                        | *
    4.21 -+*   +-------------------------------------------------------------------+ *
    4.22 -+*                                                                         *
    4.23 -+* 2. Footer (header last):                                                *
    4.24 -+*   +--------------------------- VARIABLE SIZE -------------------------+ *
    4.25 -+*   |compressed data blocks of variable size ...                        | *
    4.26 -+*   |num_blocks * FlagsOffset (upper 4 bits flags, lower 60 bits offset)| *
    4.27 -+*   +---------------------------- FIXED SIZE ---------------------------+ *
    4.28 -+*   |Signature (128 bytes)                                              | *
    4.29 -+*   |block_size (32bit number, network order)                           | *
    4.30 -+*   |num_blocks (32bit number, network order)                           | *
    4.31 -+*   +-------------------------------------------------------------------+ *
    4.32 -+*                                                                         *
    4.33 -+* Offsets are always relative to beginning of file, in all formats.       *
    4.34 -+* The block index contains num_blocks+1 offsets, followed (1) or          *
    4.35 -+* preceded (2) by the compressed blocks.                                  *
    4.36 -+*                                                                         *
    4.37 -+*  CLOOP4 flags for each compressed block                                 *
    4.38 -+*  Value   Meaning                                                        *
    4.39 -+*    0     GZIP/7ZIP compression (compatible with V2.0 Format)            *
    4.40 -+*    1     no compression (incompressible data)                           *
    4.41 -+*    2     xz compression (currently best space saver)                    *
    4.42 -+*    3     lz4 compression                                                *
    4.43 -+*    4     lzo compression (fastest)                                      *
    4.44 -+*   15     block link                                                     *
    4.45 -+*/
    4.46 -+/* Get value of first 4 bits */
    4.47 -+#define CLOOP_BLOCK_FLAGS(x)  ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60))
    4.48 -+/* Get value of last 60 bits */
    4.49 -+#define CLOOP_BLOCK_OFFSET(x)  ((x) & 0x0fffffffffffffffLLU)
    4.50 -+
    4.51 -+#define CLOOP_COMPRESSOR_ZLIB  0x0
    4.52 -+#define CLOOP_COMPRESSOR_NONE  0x1
    4.53 -+#define CLOOP_COMPRESSOR_XZ    0x2
    4.54 -+#define CLOOP_COMPRESSOR_LZ4   0x3
    4.55 -+#define CLOOP_COMPRESSOR_LZO   0x4
    4.56 -+#define CLOOP_COMPRESSOR_LINK  0xF
    4.57 -+
    4.58 - 
    4.59 - struct cloop_head
    4.60 - {
    4.61 -@@ -43,47 +91,86 @@
    4.62 - 
    4.63 - struct cloop_tail
    4.64 - {
    4.65 --	u_int32_t table_size;
    4.66 --	u_int32_t index_size;
    4.67 -+	u_int32_t table_size; 
    4.68 -+	u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */
    4.69 -+#define CLOOP3_INDEX_SIZE(x)    ((unsigned int)((x) & 0xF))
    4.70 -+#define CLOOP3_BLOCKS_FLAGS(x)  ((unsigned int)((x) & 0x70) >> 4)
    4.71 -+#define CLOOP3_TRUNCATED(x)     ((unsigned int)((x) & 0x80) >> 7)
    4.72 -+#define CLOOP3_LASTLEN(x)       (unsigned int)((x) >> 8)
    4.73 - 	u_int32_t num_blocks;
    4.74 - };
    4.75 - 
    4.76 -+#define GZIP_MAX_BUFFER(n)	((n) + (n)/1000 + 12)
    4.77 -+
    4.78 - struct block_info
    4.79 - {
    4.80 - 	loff_t offset;		/* 64-bit offsets of compressed block */
    4.81 - 	u_int32_t size;		/* 32-bit compressed block size */
    4.82 --	u_int32_t optidx;	/* 32-bit index number */
    4.83 -+	u_int32_t flags;	/* 32-bit compression flags */
    4.84 -+
    4.85 - };
    4.86 - 
    4.87 --static inline char *build_index(struct block_info *offsets, unsigned long n)
    4.88 -+static inline char *build_index(struct block_info *offsets, unsigned long n, 
    4.89 -+			unsigned long block_size, unsigned global_flags)
    4.90 - {
    4.91 - 	u_int32_t *ofs32 = (u_int32_t *) offsets;
    4.92 - 	loff_t    *ofs64 = (loff_t *) offsets;
    4.93 --	
    4.94 -+
    4.95 -+	/* v3 64bits bug: v1 assumed */
    4.96 -+	unsigned long	v3_64;
    4.97 -+	loff_t	prev;
    4.98 -+
    4.99 -+	if (ofs32[0] != 0 && ofs32[1] == 0) {
   4.100 -+		for (v3_64=(n+1)/2, prev=__le64_to_cpu(ofs64[v3_64]);
   4.101 -+		     v3_64 > 0 && __le64_to_cpu(ofs64[--v3_64]) < prev;
   4.102 -+		     prev=__le64_to_cpu(ofs64[v3_64]));
   4.103 -+	}
   4.104 -+
   4.105 - 	if (ofs32[0] == 0) {
   4.106 - 		if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
   4.107 - 			while (n--) {
   4.108 - 				offsets[n].offset = __be64_to_cpu(offsets[n].offset);
   4.109 - 				offsets[n].size = ntohl(offsets[n].size);
   4.110 -+				offsets[n].flags = 0;
   4.111 - 			}
   4.112 - 			return (char *) "128BE accelerated knoppix 1.0";
   4.113 - 		}
   4.114 --		else { /* V2.0 */
   4.115 --			loff_t last = __be64_to_cpu(ofs64[n]);
   4.116 --			while (n--) {
   4.117 -+		else { /* V2.0/V4.0 */
   4.118 -+			loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n]));
   4.119 -+			u_int32_t flags;
   4.120 -+			static char v4[11];
   4.121 -+			unsigned long i = n;
   4.122 -+
   4.123 -+			for (flags = 0; n-- ;) {
   4.124 -+				loff_t data = __be64_to_cpu(ofs64[n]); 
   4.125 -+
   4.126 - 				offsets[n].size = last - 
   4.127 --					(offsets[n].offset = __be64_to_cpu(ofs64[n])); 
   4.128 -+					(offsets[n].offset = CLOOP_BLOCK_OFFSET(data)); 
   4.129 - 				last = offsets[n].offset;
   4.130 -+				offsets[n].flags = CLOOP_BLOCK_FLAGS(data); 
   4.131 -+				flags |= 1 << offsets[n].flags;
   4.132 -+			}
   4.133 -+			if (flags < 2) return (char *) "64BE v2.0";
   4.134 -+			while (i--) {
   4.135 -+				if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) {
   4.136 -+					offsets[i] = offsets[offsets[i].offset];
   4.137 -+				}
   4.138 -+			}
   4.139 -+			strcpy(v4, (char *) "64BE v4.0a");
   4.140 -+			v4[10] = 'a' + ((flags-1) & 0xF);	// compressors used
   4.141 -+			if (flags > 0x10) {			// with links ?
   4.142 -+				v4[10] += 'A' - 'a';
   4.143 - 			}
   4.144 --			return (char *) "64BE v2.0";
   4.145 -+			return v4;
   4.146 - 		}
   4.147 - 	}
   4.148 --	else if (ofs32[1] == 0) { /* V1.0 */
   4.149 -+	else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */
   4.150 - 		loff_t last = __le64_to_cpu(ofs64[n]);
   4.151 - 		while (n--) {
   4.152 - 			offsets[n].size = last - 
   4.153 - 				(offsets[n].offset = __le64_to_cpu(ofs64[n])); 
   4.154 - 			last = offsets[n].offset;
   4.155 -+			offsets[n].flags = 0;
   4.156 - 		}
   4.157 - 		return (char *) "64LE v1.0";
   4.158 - 	}
   4.159 -@@ -93,25 +180,37 @@
   4.160 - 			offsets[n].size = last - 
   4.161 - 				(offsets[n].offset = ntohl(ofs32[n])); 
   4.162 - 			last = offsets[n].offset;
   4.163 -+			offsets[n].flags = 0;
   4.164 - 		}
   4.165 - 		return (char *) "32BE v0.68";
   4.166 - 	}
   4.167 - 	else { /* V3.0 */
   4.168 - 		unsigned long i;
   4.169 - 		loff_t j;
   4.170 -+		static char v3[11];
   4.171 - 		
   4.172 -+		v3_64 = (ofs32[1] == 0) ? 2 : 1;
   4.173 - 		for (i = n; i-- != 0; )
   4.174 --			offsets[i].size = ntohl(ofs32[i]); 
   4.175 -+			offsets[i].size = ntohl(ofs32[i*v3_64]); 
   4.176 - 		for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
   4.177 - 			offsets[i].offset = j;
   4.178 -+			offsets[i].flags = global_flags;
   4.179 -+			if ((offsets[i].size & 0x80000000) == 0) {
   4.180 -+				j += offsets[i].size;
   4.181 -+			}
   4.182 -+			else if (offsets[i].size == 0xFFFFFFFF) {
   4.183 -+				offsets[i].flags = CLOOP_COMPRESSOR_NONE;
   4.184 -+				j += offsets[i].size = block_size;
   4.185 -+			}
   4.186 -+		}
   4.187 -+		for (i = 0; i < n; i++) {
   4.188 - 			if (offsets[i].size & 0x80000000) {
   4.189 --				unsigned long k = offsets[i].size & 0x7FFFFFFF;
   4.190 --				offsets[i].offset = offsets[k].offset;
   4.191 --				offsets[i].size = offsets[k].size;
   4.192 -+				offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF];
   4.193 - 			}
   4.194 --			else j += offsets[i].size;
   4.195 - 		}
   4.196 --		return (char *) "32BE v3.0";
   4.197 -+		strcpy(v3, (char *) (--v3_64) ? "64BE v3.0a" : "32BE v3.0a");
   4.198 -+		v3[10] += global_flags;
   4.199 -+		return v3;
   4.200 - 	}
   4.201 - }
   4.202 - 
   4.203 ---- cloopreader.c
   4.204 -+++ cloopreader.c
   4.205 -@@ -25,6 +25,8 @@
   4.206 - #include "debug.h"
   4.207 - #include "cloopreader.h"
   4.208 - 
   4.209 -+#include "cloopunpack.c"
   4.210 -+
   4.211 - int read_all(int fh, void* block, size_t size){
   4.212 -     bfuncinfo("fh=%d block=0x%lx size=0x%lx",
   4.213 - 	    fh,(ulong)block,(ulong)size);
   4.214 -@@ -50,18 +52,29 @@
   4.215 -     bfuncinfo("fh=%d",fh);
   4.216 -     c->fh=fh;
   4.217 -     struct cloop_head head;
   4.218 --    OP(read_all(c->fh,&head,sizeof head));   /* read Header */
   4.219 -+    int v4_header_last, flags;
   4.220 -+    loff_t end;
   4.221 -+
   4.222 -+    for (v4_header_last=0;;v4_header_last++) {
   4.223 -+	OP(read_all(c->fh,&head,sizeof head));   /* read Header */
   4.224 -+	if (!memcmp(&head,"#!/bin/sh",9)) break;
   4.225 -+        if (v4_header_last) exit(1);
   4.226 -+	end = lseek(c->fh, 0, SEEK_END); 
   4.227 -+	OP(lseek(c->fh, end - sizeof(head), SEEK_SET)); 
   4.228 -+    }
   4.229 - 
   4.230 -     c->numblocks=ntohl(head.num_blocks);
   4.231 -     c->blocksize=ntohl(head.block_size);
   4.232 - 
   4.233 -     bprintf("block_size=%lx  num_blocks=%x\n", c->blocksize, c->numblocks);
   4.234 -+    if (v4_header_last)
   4.235 -+	OP(lseek(c->fh, end - sizeof(head) - (sizeof(*c->toc) * c->numblocks), SEEK_SET)); 
   4.236 - 
   4.237 -     ALLOC(c->pblock,c->blocksize);
   4.238 - 
   4.239 -     if (c->numblocks + 1 == 0) {
   4.240 - 	struct cloop_tail tail;
   4.241 --	loff_t end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
   4.242 -+	end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
   4.243 - 	void *p;
   4.244 - 	ulong toclen, len; 
   4.245 - 
   4.246 -@@ -70,21 +83,23 @@
   4.247 - 	c->numblocks = ntohl(tail.num_blocks);
   4.248 - 	c->tocsize = sizeof(*c->toc) * c->numblocks;
   4.249 - 	len = ntohl(tail.table_size);
   4.250 --	toclen = (ntohl(tail.index_size) & 255) * c->numblocks;
   4.251 -+	flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size));
   4.252 -+	toclen = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * c->numblocks;
   4.253 - 	OP(lseek(c->fh, end - sizeof(tail) - len, SEEK_SET));
   4.254 -         ALLOC(c->toc, sizeof(*c->toc) * c->numblocks);
   4.255 -         ALLOC(p,len);
   4.256 -         OP(read_all(c->fh,p,len));  /* read Data Index */
   4.257 --	if (uncompress((void *)c->toc,&toclen,p,len) != Z_OK)
   4.258 -+	if (unpack[flags]((void *)c->toc,&toclen,p,len) != Z_OK)
   4.259 - 		exit(1);
   4.260 - 	free(p);
   4.261 -     }
   4.262 -     else {
   4.263 -+	flags = 0;
   4.264 - 	c->tocsize = sizeof(*c->toc) * c->numblocks;
   4.265 -         ALLOC(c->toc,c->tocsize);
   4.266 -         OP(read_all(c->fh,c->toc,c->tocsize));  /* read Data Index */
   4.267 -     }
   4.268 --    build_index(c->toc, c->numblocks);
   4.269 -+    build_index(c->toc, c->numblocks, c->blocksize, flags);
   4.270 -     c->cblocksizecur=0;
   4.271 -     c->curblock=-1;
   4.272 -     return 0;
   4.273 -@@ -121,7 +136,8 @@
   4.274 - 	    "pblock=0x%lx &destlen=0x%lx cblock=0x%lx cblocksize=%lu\n",
   4.275 - 	    (ulong)c->pblock,(ulong)&destlen,(ulong)c->cblock,c->cblocksize
   4.276 - 	    );
   4.277 --    switch(uncompress(c->pblock,&destlen,c->cblock,c->cblocksize)){
   4.278 -+    if(c->toc[page].flags <= CLOOP_COMPRESSOR_MAX){
   4.279 -+      switch(unpack[c->toc[page].flags](c->pblock,&destlen,c->cblock,c->cblocksize)){
   4.280 - 	case Z_OK: break;
   4.281 - 	#define entry(x)\
   4.282 - 	case x: bprintf( #x"\n"); break; 
   4.283 -@@ -130,7 +146,9 @@
   4.284 - 	entry(Z_DATA_ERROR)
   4.285 - 	#undef entry
   4.286 - 	default: bprintf("Z_UNKNOWN_ERROR\n");
   4.287 -+      }
   4.288 -     }
   4.289 -+    else bprintf("Unsuppoted compression type\n");
   4.290 -     if(destlen!=c->blocksize)bprintf("Size mismatch\n");
   4.291 -     return 0;
   4.292 - }
   4.293 ---- /dev/null
   4.294 -+++ cloopunpack.c
   4.295 -@@ -0,0 +1,74 @@
   4.296 -+
   4.297 -+static int none_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   4.298 -+{
   4.299 -+	memcpy(dest,source,*destLen = sourceLen);
   4.300 -+	return Z_OK;
   4.301 -+}
   4.302 -+
   4.303 -+#include <lzma.h>
   4.304 -+static int xz_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   4.305 -+{
   4.306 -+        size_t src_pos = 0;
   4.307 -+        size_t dest_pos = 0;
   4.308 -+        uint64_t memlimit = 32*1024*1024;
   4.309 -+
   4.310 -+        lzma_ret res = lzma_stream_buffer_decode(&memlimit, 0, NULL,
   4.311 -+                        source, &src_pos, sourceLen, dest, &dest_pos, *destLen);
   4.312 -+
   4.313 -+        if(res == LZMA_OK && sourceLen == (int) src_pos) {
   4.314 -+                *destLen = dest_pos;
   4.315 -+		return Z_OK;
   4.316 -+	}
   4.317 -+        else return Z_ERRNO;
   4.318 -+}
   4.319 -+
   4.320 -+#include <lz4.h>
   4.321 -+static int lz4_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   4.322 -+{
   4.323 -+	long size = LZ4_decompress_safe((const char *) source, (char *) dest, sourceLen, *destLen);
   4.324 -+
   4.325 -+	if (size < 0) return Z_ERRNO;
   4.326 -+        *destLen = size;
   4.327 -+	return Z_OK;
   4.328 -+}
   4.329 -+
   4.330 -+#include <lzo/lzo1x.h>
   4.331 -+static int lzo_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   4.332 -+{
   4.333 -+	lzo_uint outlen = *destLen;
   4.334 -+
   4.335 -+	if (lzo1x_decompress_safe(source, sourceLen, dest, &outlen, NULL) == LZO_E_OK) {
   4.336 -+                *destLen = outlen;
   4.337 -+		return Z_OK;
   4.338 -+	}
   4.339 -+        else return Z_ERRNO;
   4.340 -+}
   4.341 -+
   4.342 -+#include <zstd.h>
   4.343 -+static int zstd_uncompress(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen)
   4.344 -+{
   4.345 -+        const size_t res = ZSTD_decompress(dest, *destLen, source, sourceLen);
   4.346 -+
   4.347 -+        if (ZSTD_isError(res)) {
   4.348 -+                return Z_ERRNO;
   4.349 -+        }
   4.350 -+
   4.351 -+	*destLen = res;
   4.352 -+        return Z_OK;
   4.353 -+}
   4.354 -+
   4.355 -+#define CLOOP_COMPRESSOR_ZSTD  0x5
   4.356 -+
   4.357 -+#define CLOOP_COMPRESSOR_MAX CLOOP_COMPRESSOR_ZSTD
   4.358 -+
   4.359 -+#define CLOOP_COMPRESSOR_NAMES	"gzip","copy","xz","lz4","lzo","zstd"
   4.360 -+
   4.361 -+static int (*unpack[CLOOP_COMPRESSOR_MAX+1])(Bytef *dest,  uLongf *destLen, const Bytef *source, uLongf sourceLen) = {
   4.362 -+	uncompress,
   4.363 -+	none_uncompress,
   4.364 -+	xz_uncompress,
   4.365 -+	lz4_uncompress,
   4.366 -+	lzo_uncompress,
   4.367 -+	zstd_uncompress
   4.368 -+};
   4.369 -+
   4.370 ---- extract_compressed_fs.c
   4.371 -+++ extract_compressed_fs.c
   4.372 -@@ -3,14 +3,19 @@
   4.373 - #include "common_header.h"
   4.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"
   4.375 - 
   4.376 -+#include "cloopunpack.c"
   4.377 -+static char *packnames[CLOOP_COMPRESSOR_MAX+1] = { CLOOP_COMPRESSOR_NAMES };
   4.378 -+
   4.379 - int main(int argc, char *argv[])
   4.380 - {
   4.381 --	int handle;
   4.382 -+	int handle, err;
   4.383 - 	struct cloop_head head;
   4.384 --	unsigned int i;
   4.385 --	unsigned long num_blocks, block_size, zblock_maxsize, lastlen = 0;
   4.386 -+	unsigned int i, v4_header_last, global_flags;
   4.387 -+	unsigned long n, num_blocks, block_size, zblock_maxsize, len;
   4.388 -+	uLongf ulen;
   4.389 - 	unsigned char *buffer, *clear_buffer;
   4.390 - 	struct block_info *offsets;
   4.391 -+	loff_t end;
   4.392 - 
   4.393 - 	if (argc < 2 || argv[1][0] == '-') {
   4.394 - 		fprintf(stderr, "Usage: extract_compressed_fs file [--convert-to-v2] > output\n");
   4.395 -@@ -23,23 +28,35 @@
   4.396 - 		exit(1);
   4.397 - 	}
   4.398 - 
   4.399 --	if (read(handle, &head, sizeof(head)) != sizeof(head)) {
   4.400 --		perror("Reading compressed file header\n");
   4.401 -+	for (v4_header_last=0;; v4_header_last++) {
   4.402 -+		if (read(handle, &head, sizeof(head)) != sizeof(head)) {
   4.403 -+			perror("Reading compressed file header\n");
   4.404 -+			exit(1);
   4.405 -+		}
   4.406 -+		if (!memcmp(&head,"#!/bin/sh",9)) break;
   4.407 -+		end = lseek64(handle, 0, SEEK_END);
   4.408 -+		lseek64(handle, end - sizeof(head), SEEK_SET);
   4.409 -+		if (v4_header_last == 0) continue;
   4.410 -+		perror("Not a cloop file\n");
   4.411 - 		exit(1);
   4.412 - 	}
   4.413 - 
   4.414 - 	num_blocks = ntohl(head.num_blocks);
   4.415 - 	block_size = ntohl(head.block_size);
   4.416 --	zblock_maxsize =  block_size + block_size/1000 + 12 + 4;
   4.417 -+	zblock_maxsize = GZIP_MAX_BUFFER(block_size);
   4.418 - 	buffer = malloc(zblock_maxsize);
   4.419 - 	clear_buffer = malloc(block_size);
   4.420 - 
   4.421 -+	if (v4_header_last) {
   4.422 -+		lseek64(handle, end - ((num_blocks+1) * sizeof(loff_t)) - sizeof(head), SEEK_SET);
   4.423 -+	}
   4.424 -+
   4.425 - 	if (num_blocks == 0xFFFFFFFF) {
   4.426 - 		void *table;
   4.427 - 		struct cloop_tail tail;
   4.428 --		unsigned long len, table_size;
   4.429 --		loff_t end = lseek64(handle, 0, SEEK_END);
   4.430 -+		unsigned long table_size;
   4.431 - 		
   4.432 -+		end = lseek64(handle, 0, SEEK_END);
   4.433 - 		if (lseek64(handle, end - sizeof(tail), SEEK_SET) < 0 ||
   4.434 - 		    read(handle, &tail, sizeof(tail)) != sizeof(tail) ||
   4.435 - 		    lseek64(handle, end - sizeof(tail) - 
   4.436 -@@ -51,60 +68,91 @@
   4.437 - 		num_blocks = ntohl(head.num_blocks);
   4.438 - 		table_size = ntohl(tail.table_size);
   4.439 - 		table = malloc(table_size);
   4.440 --		len = i = num_blocks * (ntohl(tail.index_size) & 255);
   4.441 --		lastlen = ntohl(tail.index_size) / 256;
   4.442 --		offsets = malloc(num_blocks * sizeof(*offsets));
   4.443 --		if (!table || !offsets || 
   4.444 --		    read(handle, table, table_size) != table_size ||
   4.445 --		    uncompress((void *)offsets, &len, table, table_size) != Z_OK ||
   4.446 --		    len != i) {
   4.447 -+		len = num_blocks * CLOOP3_INDEX_SIZE(ntohl(tail.index_size));
   4.448 -+		global_flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size));
   4.449 -+		if (global_flags > CLOOP_COMPRESSOR_MAX) {
   4.450 -+			fprintf(stderr, "Unsupported compression %d\n",
   4.451 -+				global_flags);
   4.452 -+			exit(1);
   4.453 -+		}
   4.454 -+		ulen = num_blocks * sizeof(*offsets);
   4.455 -+		offsets = malloc(ulen);
   4.456 -+		if (!table || !offsets || !buffer || !clear_buffer) {
   4.457 -+			fprintf(stderr,"Out of memory\n");
   4.458 -+			exit(1);
   4.459 -+		}
   4.460 -+		if (read(handle, table, table_size) != table_size) {
   4.461 - 			perror("Reading index\n");
   4.462 - 			exit(1);
   4.463 - 		}
   4.464 -+		err = unpack[global_flags]((void *) offsets, &ulen, table, table_size);
   4.465 -+		if (err != Z_OK) {
   4.466 -+			fprintf(stderr, "Unpack %s index error %d\n",
   4.467 -+				packnames[global_flags],err);
   4.468 -+			exit(1);
   4.469 -+		}
   4.470 - 		free(table);
   4.471 - 	}
   4.472 - 	else {
   4.473 --		offsets = malloc(i = num_blocks * sizeof(*offsets));
   4.474 --		if (!offsets || read(handle, offsets, i) != i) {
   4.475 -+		global_flags = 0;
   4.476 -+		len = num_blocks * sizeof(*offsets);
   4.477 -+		offsets = malloc(len);
   4.478 -+		if (v4_header_last) {
   4.479 -+			len = (num_blocks+1) * sizeof(loff_t);
   4.480 -+		}
   4.481 -+		if (!offsets || !buffer || !clear_buffer) {
   4.482 -+			fprintf(stderr,"Out of memory\n");
   4.483 -+			exit(1);
   4.484 -+		}
   4.485 -+		if (read(handle, offsets, len) != len) {
   4.486 - 			perror("Reading index\n");
   4.487 - 			exit(1);
   4.488 - 		}
   4.489 - 	}
   4.490 - 	
   4.491 -+	if (v4_header_last) {
   4.492 -+		lseek64(handle, 0, SEEK_SET);
   4.493 -+	}
   4.494 -+
   4.495 - 	fprintf(stderr, "%lu blocks of size %lu. Preamble:\n%s\n", 
   4.496 - 		num_blocks, block_size, head.preamble);
   4.497 --	fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks));
   4.498 -+#if 1
   4.499 -+	if (getenv("CLOOP_INDEX") != NULL) {
   4.500 -+		fprintf(stderr, "CLOOP_INDEX: binary\n");
   4.501 -+		write(STDOUT_FILENO, offsets, len);
   4.502 -+		exit(0);
   4.503 -+	}
   4.504 -+#endif
   4.505 -+	fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks, block_size, global_flags));
   4.506 - 	
   4.507 -+#if 1
   4.508 -+	if (getenv("CLOOP_TABLE") != NULL) {
   4.509 -+		fprintf(stderr, "CLOOP_TABLE ascii: offset, size, flags\n");
   4.510 -+		for (i = 0; i < num_blocks; i++) {
   4.511 -+			printf("%llu  %u  %u\n",
   4.512 -+				offsets[i].offset,
   4.513 -+				offsets[i].size,
   4.514 -+				offsets[i].flags);
   4.515 -+		}
   4.516 -+		exit(0);
   4.517 -+	}
   4.518 -+#endif
   4.519 -+
   4.520 - 	if (argc > 2) {
   4.521 --		unsigned n;
   4.522 --		loff_t data, offset = ((num_blocks + 1) * sizeof(offset)) + sizeof(head);
   4.523 -+		loff_t data, ofs = ((num_blocks + 1) * sizeof(ofs)) + sizeof(head);
   4.524 - 		
   4.525 - 		strcpy(head.preamble, CLOOP_PREAMBLE);
   4.526 - 		write(STDOUT_FILENO, &head, n = sizeof(head));
   4.527 --		for (i = 0; i < num_blocks; i++) {
   4.528 --			data = __be64_to_cpu(offset);
   4.529 -+		for (i = 0; i <= num_blocks; i++) {
   4.530 -+			data = __be64_to_cpu(ofs);
   4.531 - 			write(STDOUT_FILENO, &data, sizeof(data));
   4.532 - 			n += sizeof(data);
   4.533 --			offset += offsets[i].size;
   4.534 -+			ofs += offsets[i].size;
   4.535 - 		}
   4.536 --		data = __be64_to_cpu(offset);
   4.537 --		write(STDOUT_FILENO, &data, sizeof(data));
   4.538 --		for (i = 0; i < num_blocks && lseek64(handle, offsets[i].offset, SEEK_SET) >= 0; i++) {
   4.539 --			read(handle, buffer, offsets[i].size);
   4.540 --			write(STDOUT_FILENO, buffer, offsets[i].size);
   4.541 --			n += offsets[i].size;
   4.542 --		}
   4.543 --		n &= 0x1FF;
   4.544 --		if (n) {
   4.545 --			memset(buffer, 0, 512);
   4.546 --			write(STDOUT_FILENO, buffer, 512 - n);
   4.547 --		}
   4.548 --		return 0;
   4.549 - 	}
   4.550 --	
   4.551 - 	for (i = 0; i < num_blocks; i++) {
   4.552 --		unsigned long destlen = block_size;
   4.553 --		unsigned int size = offsets[i].size;
   4.554 -+		unsigned char *out;
   4.555 -+		int flags = offsets[i].flags;
   4.556 - 
   4.557 - 		if (lseek64(handle, offsets[i].offset, SEEK_SET) < 0) {
   4.558 - 			fprintf(stderr, "lseek to %Lu: %s\n",
   4.559 -@@ -112,44 +160,61 @@
   4.560 - 			exit(1);
   4.561 - 		}
   4.562 -                 
   4.563 --		if (size > zblock_maxsize) {
   4.564 -+		len = offsets[i].size;
   4.565 -+		if (len > zblock_maxsize) {
   4.566 - 			fprintf(stderr, 
   4.567 - 				"Size %u for block %u (offset %Lu) too big\n",
   4.568 --				size, i, offsets[i].offset);
   4.569 -+				len, i, offsets[i].offset);
   4.570 - 			exit(1);
   4.571 - 		}
   4.572 --		read(handle, buffer, size);
   4.573 --
   4.574 --		fprintf(stderr, "Block %u at %llu length %u",
   4.575 --			i, offsets[i].offset, size);
   4.576 --		switch (uncompress(clear_buffer, &destlen,
   4.577 --				   buffer, size)) {
   4.578 --		case Z_OK:
   4.579 --			break;
   4.580 - 
   4.581 --		case Z_MEM_ERROR:
   4.582 --			fprintf(stderr, "Uncomp: oom block %u\n", i);
   4.583 --			exit(1);
   4.584 --
   4.585 --		case Z_BUF_ERROR:
   4.586 --			fprintf(stderr, "Uncomp: not enough out room %u\n", i);
   4.587 --			exit(1);
   4.588 --
   4.589 --		case Z_DATA_ERROR:
   4.590 --			fprintf(stderr, "Uncomp: input corrupt %u\n", i);
   4.591 -+		if (argc <= 2) {
   4.592 -+			fprintf(stderr, "Block %u at %llu length %lu ",
   4.593 -+				i, offsets[i].offset, len);
   4.594 -+		}
   4.595 -+
   4.596 -+		read(handle, out = buffer, ulen = len);
   4.597 -+
   4.598 -+		if (flags > CLOOP_COMPRESSOR_MAX) {
   4.599 -+			fprintf(stderr, "Block %u: unsupported compression %d \n",
   4.600 -+				i, flags);
   4.601 - 			exit(1);
   4.602 -+		}
   4.603 - 
   4.604 --		default:
   4.605 --			fprintf(stderr, "Uncomp: unknown error %u\n", i);
   4.606 --			exit(1);
   4.607 -+		if (flags != CLOOP_COMPRESSOR_ZLIB || argc <= 2) {
   4.608 -+			ulen = block_size;
   4.609 -+			err = unpack[flags](out = clear_buffer, &ulen, buffer, len);
   4.610 -+			if (err != Z_OK) {
   4.611 -+				fprintf(stderr, "Unpack %s block %u error %d \n",
   4.612 -+					packnames[flags], i, err);
   4.613 -+				exit(1);
   4.614 -+			}
   4.615 -+			if (argc > 2) {
   4.616 -+				err = compress2(out = buffer, &ulen, clear_buffer, ulen, Z_BEST_SPEED);
   4.617 -+				if (err != Z_OK) {
   4.618 -+					fprintf(stderr, "Compress %s block %u error %d \n",
   4.619 -+						packnames[flags], i, err);
   4.620 -+					exit(1);
   4.621 -+				}
   4.622 -+			}
   4.623 -+			else {
   4.624 -+				fprintf(stderr, "=> %lu\n", ulen);
   4.625 -+				if (ulen != block_size && i != num_blocks - 1) {
   4.626 -+					fprintf(stderr, "Uncomp %s: bad len %u (%lu not %lu)\n",
   4.627 -+						packnames[flags], i, ulen, block_size);
   4.628 -+					exit(1);
   4.629 -+				}
   4.630 -+			}
   4.631 - 		}
   4.632 --		fprintf(stderr, " => %lu\n", destlen);
   4.633 --		if (destlen != block_size && i != num_blocks - 1) {
   4.634 --			fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i,
   4.635 --				destlen, block_size);
   4.636 --			exit(1);
   4.637 -+		write(STDOUT_FILENO, out, ulen);
   4.638 -+		n += ulen;
   4.639 -+	}
   4.640 -+	if (argc > 2) {
   4.641 -+		n &= 0x1FF;
   4.642 -+		if (n) {
   4.643 -+			memset(buffer, 0, 512);
   4.644 -+			write(STDOUT_FILENO, buffer, 512 - n);
   4.645 - 		}
   4.646 --		write(STDOUT_FILENO, clear_buffer, (lastlen != 0 && (i+1) == num_blocks) ? lastlen : block_size);
   4.647 - 	}
   4.648 - 	return 0;
   4.649 - }
   4.650 ---- create_compressed_fs.c
   4.651 -+++ create_compressed_fs.c
   4.652 -@@ -7,10 +7,11 @@
   4.653 - #define ZMAX 9
   4.654 - static shrink_t level;
   4.655 - static int pass, iter;
   4.656 --static int best_compress(unsigned char *compressed,
   4.657 --			 unsigned long *compressed_len,
   4.658 --			 unsigned char *uncompressed,
   4.659 --			 unsigned long uncompressed_len)
   4.660 -+static int best_compress(Bytef *compressed,
   4.661 -+			uLongf *compressed_len,
   4.662 -+			const Bytef *uncompressed,
   4.663 -+			uLong uncompressed_len,
   4.664 -+			int dummy)
   4.665 - {
   4.666 - 	int i, j, err;
   4.667 - 	unsigned char *buf[2];
   4.668 -@@ -19,6 +20,7 @@
   4.669 - 	static unsigned char *buffer;
   4.670 - 	static unsigned long buffersz;
   4.671 - 
   4.672 -+	(void) dummy;
   4.673 - 	if (buffersz < *compressed_len) {
   4.674 - 		if (buffer) free(buffer);
   4.675 - 		buffer = (unsigned char *)  malloc(buffersz = *compressed_len);
   4.676 -@@ -50,9 +52,95 @@
   4.677 - 		memcpy(compressed, buffer, best);
   4.678 - 	return err;
   4.679 - }
   4.680 --#define compress2(a,b,c,d,e) best_compress(a,b,c,d)
   4.681 -+#else
   4.682 -+#include <stdlib.h>
   4.683 -+#include <string.h>
   4.684 -+#include <zlib.h>
   4.685 - #endif
   4.686 -+
   4.687 -+#include <lzma.h>
   4.688 -+static int xz_compress(Bytef *compressed,
   4.689 -+			uLongf *compressed_len,
   4.690 -+			const Bytef *uncompressed,
   4.691 -+			uLong uncompressed_len,
   4.692 -+			int level)
   4.693 -+{
   4.694 -+	int res = Z_ERRNO;
   4.695 -+	lzma_stream strm = LZMA_STREAM_INIT;
   4.696 -+
   4.697 -+	if (lzma_easy_encoder(&strm, LZMA_PRESET_DEFAULT, LZMA_CHECK_CRC32) == LZMA_OK) {
   4.698 -+
   4.699 -+		strm.next_in = uncompressed;
   4.700 -+		strm.avail_in = uncompressed_len;
   4.701 -+		strm.next_out = compressed;
   4.702 -+		strm.avail_out = *compressed_len;
   4.703 -+
   4.704 -+		if (lzma_code(&strm, LZMA_FINISH) == LZMA_STREAM_END) {
   4.705 -+
   4.706 -+			*compressed_len -= strm.avail_out;
   4.707 -+			res = Z_OK;
   4.708 -+		}
   4.709 -+	}
   4.710 -+	lzma_end(&strm);
   4.711 -+	return res;
   4.712 -+}
   4.713 -+
   4.714 -+#include <lz4.h>
   4.715 -+#include <lz4hc.h>
   4.716 -+#ifndef LZ4HC_CLEVEL_MAX
   4.717 -+#define LZ4HC_CLEVEL_MAX 12
   4.718 -+#endif
   4.719 -+static int lz4_compress(Bytef *compressed,
   4.720 -+			uLongf *compressed_len,
   4.721 -+			const Bytef *uncompressed,
   4.722 -+			uLong uncompressed_len,
   4.723 -+			int level)
   4.724 -+{
   4.725 -+	int res = LZ4_compress_HC((const char *) uncompressed, (char *) compressed,
   4.726 -+			 uncompressed_len, *compressed_len, LZ4HC_CLEVEL_MAX);
   4.727 -+	(void) level;
   4.728 -+	if (res <= 0) return Z_ERRNO;
   4.729 -+	*compressed_len = res;
   4.730 -+	return Z_OK;
   4.731 -+}
   4.732 -+
   4.733 -+static int setup_compress(Bytef *compressed,
   4.734 -+			uLongf *compressed_len,
   4.735 -+			const Bytef *uncompressed,
   4.736 -+			uLong uncompressed_len,
   4.737 -+			int level);
   4.738 -+
   4.739 -+static int (*compress3)(Bytef *compressed,
   4.740 -+			uLongf *compressed_len,
   4.741 -+			const Bytef *uncompressed,
   4.742 -+			uLong uncompressed_len,
   4.743 -+			int level) = setup_compress;
   4.744 -                         
   4.745 -+static int setup_compress(Bytef *compressed,
   4.746 -+			uLongf *compressed_len,
   4.747 -+			const Bytef *uncompressed,
   4.748 -+			uLong uncompressed_len,
   4.749 -+			int level)
   4.750 -+{
   4.751 -+	char *s = getenv("CLOOP_COMP");
   4.752 -+	if (s && !strcmp(s,"XZ")) {
   4.753 -+		compress3 = xz_compress;
   4.754 -+	}
   4.755 -+	else if (s && !strcmp(s,"LZ4")) {
   4.756 -+		compress3 = lz4_compress;
   4.757 -+	}
   4.758 -+	else
   4.759 -+#ifdef FIND_BEST_COMPRESSION
   4.760 -+	if (s && !strcmp(s,"GZIP")) {
   4.761 -+		compress3 = compress2;
   4.762 -+	}
   4.763 -+	compress3 = best_compress;
   4.764 -+#else
   4.765 -+	compress3 = compress2;
   4.766 -+#endif
   4.767 -+	return compress3(compressed,compressed_len,uncompressed,uncompressed_len,level);
   4.768 -+}
   4.769 -+
   4.770 - #include <signal.h>
   4.771 - 
   4.772 - /* Creates a compressed file */
   4.773 -@@ -82,9 +170,7 @@
   4.774 - 	return i;
   4.775 - }
   4.776 - 
   4.777 --#ifdef FIND_BEST_COMPRESSION
   4.778 - #include "md5sum.c"
   4.779 --#endif
   4.780 - 
   4.781 - static unsigned n;
   4.782 - static unsigned long lastlen, pos;
   4.783 -@@ -96,15 +182,23 @@
   4.784 - 	static char padding[512];
   4.785 - 	struct cloop_tail tail;
   4.786 - 	unsigned long len;
   4.787 -+	int flags = 0;
   4.788 - 
   4.789 --	fprintf(stderr, "Write index for %lu blocks\n", n);
   4.790 -+	fprintf(stderr, "Write index for %u blocks\n", n);
   4.791 - 	if (block_size >= 0x1000000) lastlen = 0;
   4.792 --	tail.index_size = ntohl(sizeof(*block_index) + 256*(lastlen % 0xFFffFF));
   4.793 -+	if (sig) flags = 0x80;
   4.794 -+	if (compress3 == xz_compress) {
   4.795 -+		flags |= (CLOOP_COMPRESSOR_XZ << 4);
   4.796 -+	}
   4.797 -+	if (compress3 == lz4_compress) {
   4.798 -+		flags |= (CLOOP_COMPRESSOR_LZ4 << 4);
   4.799 -+	}
   4.800 -+	tail.index_size = ntohl(sizeof(*block_index) + flags + 256*(lastlen % 0xFFffFF));
   4.801 - 	tail.num_blocks = ntohl(n);
   4.802 - 	n *= sizeof(*block_index);
   4.803 --	len = n + n/1000 + 12;
   4.804 -+	len = GZIP_MAX_BUFFER(n);
   4.805 - 	compressed = (unsigned char *) realloc(compressed, len);
   4.806 --	if (!compressed || compress2(compressed, &len, (unsigned char *) block_index,
   4.807 -+	if (!compressed || compress3(compressed, &len, (unsigned char *) block_index,
   4.808 - 				     n, Z_BEST_SPEED) != Z_OK)
   4.809 - 		quit("Index compression failed");
   4.810 - 	tail.table_size = ntohl(len);
   4.811 -@@ -122,11 +216,10 @@
   4.812 - 	unsigned char *uncompressed;
   4.813 - 	unsigned long len;
   4.814 - 	unsigned indexmax, zlenmax;
   4.815 --#ifdef FIND_BEST_COMPRESSION
   4.816 --	unsigned i, j, hashmax;
   4.817 -+	unsigned i, j, hashmax, domd5;
   4.818 - 	md5hash *hash;
   4.819 --#endif
   4.820 - 	
   4.821 -+	domd5 = getenv("CLOOP_NOMD5") == NULL;
   4.822 - #ifdef FIND_BEST_COMPRESSION
   4.823 - 	while (argc > 1) {
   4.824 - 		if (argv[1][0] == '-') {
   4.825 -@@ -141,11 +234,11 @@
   4.826 - 		}
   4.827 - 		argc--;
   4.828 - 		if (argv[1][0] < '0' || argv[1][0] > '9')
   4.829 --			quit("Usage : create_compressed_fs [-n <pass>][ -i <iter>] [block size] < input > output");
   4.830 -+			quit("Usage : [CLOOP_COMP=XZ|GZIP|LZ4] [CLOOP_NOMD5] create_compressed_fs [-n <pass>][ -i <iter>] [block size] < input > output");
   4.831 - #else
   4.832 - 	if (argc > 1) {
   4.833 - 		if (argv[1][0] < '0' || argv[1][0] > '9')
   4.834 --			quit("Usage : create_compressed_fs [block size] < input > output");
   4.835 -+			quit("Usage : [CLOOP_COMP=XZ|LZ4] [CLOOP_NOMD5=1] create_compressed_fs [block size] < input > output");
   4.836 - #endif
   4.837 - 		block_size = atoi(argv[1]);
   4.838 - 	}
   4.839 -@@ -164,12 +257,8 @@
   4.840 - 	compressed = (unsigned char *) malloc(zlenmax);
   4.841 - 	uncompressed = (unsigned char *) malloc(block_size);
   4.842 - 	block_index = (u_int32_t *) malloc(indexmax = CHUNK);
   4.843 --#ifdef FIND_BEST_COMPRESSION
   4.844 - 	hash = (md5hash *) malloc(hashmax = CHUNK);
   4.845 - 	if (!compressed || !uncompressed || !block_index || !hash)
   4.846 --#else
   4.847 --	if (!compressed || !uncompressed || !block_index)
   4.848 --#endif
   4.849 - 		quit("Malloc failed");
   4.850 - 	
   4.851 - 	signal(SIGINT,flush_index);
   4.852 -@@ -184,39 +273,42 @@
   4.853 - 			if (!block_index)
   4.854 - 				quit("Realloc");
   4.855 - 		}
   4.856 --#ifdef FIND_BEST_COMPRESSION
   4.857 --		if (n * sizeof(*hash) >= hashmax) {
   4.858 --			hash = (md5hash *) realloc(hash, hashmax += CHUNK);
   4.859 --			if (!hash)
   4.860 --				quit("Realloc hash");
   4.861 --		}
   4.862 --		hash[n] = md5sum(uncompressed, len);
   4.863 --		j = 0x7FFFFFFF;
   4.864 --		if (n < j)
   4.865 --			j = n;
   4.866 --		for (i = 0; i < j; i++) {
   4.867 --			if (* (uint32_t *) &hash[i] == * (uint32_t *) &hash[n]
   4.868 --			    && !memcmp(&hash[i],&hash[n],sizeof(*hash)))
   4.869 --				break;
   4.870 --		}
   4.871 --		if (i != j) {
   4.872 --			block_index[n] = ntohl(0x80000000 | i);
   4.873 --			fprintf(stderr, "Block %u length %lu => duplicate %lu\n",
   4.874 --				n, block_size, i);
   4.875 -+		if (domd5) {
   4.876 -+			if (n * sizeof(*hash) >= hashmax) {
   4.877 -+				hash = (md5hash *) realloc(hash, hashmax += CHUNK);
   4.878 -+				if (!hash)
   4.879 -+					quit("Realloc hash");
   4.880 -+			}
   4.881 -+			hash[n] = md5sum(uncompressed, len);
   4.882 -+			j = 0x7FFFFFFF;
   4.883 -+			if (n < j)
   4.884 -+				j = n;
   4.885 -+			for (i = 0; i < j; i++) {
   4.886 -+				if (* (uint32_t *) &hash[i] == * (uint32_t *) &hash[n]
   4.887 -+				    && !memcmp(&hash[i],&hash[n],sizeof(*hash)))
   4.888 -+					break;
   4.889 -+			}
   4.890 -+			if (i != j) {
   4.891 -+				block_index[n] = ntohl(0x80000000 | i);
   4.892 -+				fprintf(stderr, "Block %u length %lu => duplicate %u\n",
   4.893 -+					n, block_size, i);
   4.894 -+				continue;
   4.895 -+			}
   4.896 - 		}
   4.897 --		else
   4.898 --#endif
   4.899 --		{
   4.900 --			len = zlenmax;
   4.901 --			if (compress2(compressed, &len, uncompressed, lastlen, 
   4.902 --					Z_BEST_SPEED) != Z_OK)
   4.903 --				quit("Compression failed");
   4.904 --			fprintf(stderr, "Block %u length %lu => %lu\n",
   4.905 --				n, block_size, len);
   4.906 --			write(STDOUT_FILENO, compressed, len);
   4.907 --			pos += len;
   4.908 -+		len = zlenmax;
   4.909 -+		if (compress3(compressed, &len, uncompressed, lastlen, 
   4.910 -+				Z_BEST_SPEED) != Z_OK || len >= lastlen) {
   4.911 -+			len = lastlen;
   4.912 -+			block_index[n] = ntohl(0xFFFFFFFF);
   4.913 -+			write(STDOUT_FILENO, uncompressed, len);
   4.914 -+		}
   4.915 -+		else {
   4.916 - 			block_index[n] = ntohl(len);
   4.917 -+			write(STDOUT_FILENO, compressed, len);
   4.918 - 		}
   4.919 -+		fprintf(stderr, "Block %u length %lu => %lu\n",
   4.920 -+			n, block_size, len);
   4.921 -+		pos += len;
   4.922 - 	}
   4.923 - 	flush_index(0);
   4.924 - 	return 0;
     5.1 --- a/libtcplay-dev/receipt	Mon Apr 27 07:35:16 2020 +0100
     5.2 +++ b/libtcplay-dev/receipt	Mon Apr 27 09:29:39 2020 +0000
     5.3 @@ -1,7 +1,7 @@
     5.4  # SliTaz package receipt.
     5.5  
     5.6  PACKAGE="libtcplay-dev"
     5.7 -VERSION="2.0"
     5.8 +VERSION="3.3"
     5.9  CATEGORY="development"
    5.10  SHORT_DESC="Free TrueCrypt implementation, development files."
    5.11  MAINTAINER="pascal.bellard@slitaz.org"
     6.1 --- a/libtcplay/receipt	Mon Apr 27 07:35:16 2020 +0100
     6.2 +++ b/libtcplay/receipt	Mon Apr 27 09:29:39 2020 +0000
     6.3 @@ -1,7 +1,7 @@
     6.4  # SliTaz package receipt.
     6.5  
     6.6  PACKAGE="libtcplay"
     6.7 -VERSION="2.0"
     6.8 +VERSION="3.3"
     6.9  CATEGORY="system-tools"
    6.10  SHORT_DESC="Free TrueCrypt implementation."
    6.11  MAINTAINER="pascal.bellard@slitaz.org"
     7.1 --- a/lz4-dev/receipt	Mon Apr 27 07:35:16 2020 +0100
     7.2 +++ b/lz4-dev/receipt	Mon Apr 27 09:29:39 2020 +0000
     7.3 @@ -7,7 +7,7 @@
     7.4  MAINTAINER="pascal.bellard@slitaz.org"
     7.5  LICENSE="BSD"
     7.6  WANTED="lz4"
     7.7 -WEB_SITE="https://www.lz4.org/"
     7.8 +WEB_SITE="https://github.com/lz4/lz4"
     7.9  
    7.10  DEPENDS="pkg-config lz4-lib"
    7.11  
     8.1 --- a/lz4-lib/receipt	Mon Apr 27 07:35:16 2020 +0100
     8.2 +++ b/lz4-lib/receipt	Mon Apr 27 09:29:39 2020 +0000
     8.3 @@ -7,7 +7,7 @@
     8.4  MAINTAINER="pascal.bellard@slitaz.org"
     8.5  LICENSE="BSD"
     8.6  WANTED="lz4"
     8.7 -WEB_SITE="https://www.lz4.org/"
     8.8 +WEB_SITE="https://github.com/lz4/lz4"
     8.9  
    8.10  # Rules to gen a SliTaz package suitable for Tazpkg.
    8.11  genpkg_rules()
     9.1 --- a/lz4/receipt	Mon Apr 27 07:35:16 2020 +0100
     9.2 +++ b/lz4/receipt	Mon Apr 27 09:29:39 2020 +0000
     9.3 @@ -6,7 +6,7 @@
     9.4  SHORT_DESC="High speed lossless compressor."
     9.5  MAINTAINER="pascal.bellard@slitaz.org"
     9.6  LICENSE="BSD"
     9.7 -WEB_SITE="https://www.lz4.org/"
     9.8 +WEB_SITE="https://github.com/lz4/lz4"
     9.9  TARBALL="$PACKAGE-r$VERSION.tar.gz"
    9.10  WGET_URL="https://github.com/lz4/lz4/archive/v$VERSION.tar.gz"
    9.11  TAGS="compression"
    10.1 --- a/qemu/stuff/cloop.u	Mon Apr 27 07:35:16 2020 +0100
    10.2 +++ b/qemu/stuff/cloop.u	Mon Apr 27 09:29:39 2020 +0000
    10.3 @@ -215,6 +215,15 @@
    10.4       }
    10.5       return 0;
    10.6   }
    10.7 +@@ -60,7 +233,7 @@
    10.8 +                       Error **errp)
    10.9 + {
   10.10 +     BDRVCloopState *s = bs->opaque;
   10.11 +-    uint32_t offsets_size, max_compressed_block_size = 1, i;
   10.12 ++    uint32_t offsets_size, max_compressed_block_size = 1;
   10.13 +     int ret;
   10.14 + 
   10.15 +     bs->read_only = 1;
   10.16  @@ -91,79 +264,92 @@
   10.17                      MAX_BLOCK_SIZE / (1024 * 1024));
   10.18           return -EINVAL;