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;