wok rev 10935

fusecloop: add create_compressed_fs
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Aug 27 13:32:15 2011 +0200 (2011-08-27)
parents 27a1c1c0fdf3
children e5f7f1b3d407
files fusecloop/stuff/fusecloop.u
line diff
     1.1 --- a/fusecloop/stuff/fusecloop.u	Fri Aug 26 20:47:01 2011 +0200
     1.2 +++ b/fusecloop/stuff/fusecloop.u	Sat Aug 27 13:32:15 2011 +0200
     1.3 @@ -1,6 +1,6 @@
     1.4  --- compressed_loop.h
     1.5  +++ compressed_loop.h
     1.6 -@@ -41,6 +41,85 @@
     1.7 +@@ -41,6 +41,73 @@
     1.8   /* data_index (num_blocks 64bit pointers, network order)...      */
     1.9   /* compressed data (gzip block compressed format)...             */
    1.10   
    1.11 @@ -17,10 +17,8 @@
    1.12  +	u_int32_t optidx;	/* 32-bit index number */
    1.13  +};
    1.14  +
    1.15 -+static inline char *build_index(struct block_info *offsets, unsigned long n,
    1.16 -+				unsigned long block_size)
    1.17 ++static inline char *build_index(struct block_info *offsets, unsigned long n)
    1.18  +{
    1.19 -+	u_int16_t *ofs16 = (u_int16_t *) offsets;
    1.20  +	u_int32_t *ofs32 = (u_int32_t *) offsets;
    1.21  +	loff_t    *ofs64 = (loff_t *) offsets;
    1.22  +	
    1.23 @@ -61,25 +59,15 @@
    1.24  +		return "32BE v0.68";
    1.25  +	}
    1.26  +	else { /* V3.0 */
    1.27 -+		char *type;
    1.28 -+		int i, j, smallest;
    1.29 ++		int i, j;
    1.30  +		
    1.31 -+		smallest = (block_size < 32768) ? 0 : block_size>>10;
    1.32 -+		if (block_size > 0x10000) {
    1.33 -+			for (i = 0; i < n; i++)
    1.34 -+				offsets[n].size = smallest + ntohl(ofs32[n]); 
    1.35 -+			type = "32BE size v3.0";
    1.36 -+		}
    1.37 -+		else {
    1.38 -+			for (i = 0; i < n; i++)
    1.39 -+				offsets[n].size = smallest + ntohs(ofs16[n]); 
    1.40 -+			type = "16BE size v3.0"; 
    1.41 -+		}
    1.42 -+		for (i = j = 0; i < n; i++) {
    1.43 ++		for (i = n; i-- > 0; )
    1.44 ++			offsets[i].size = ntohl(ofs32[i]); 
    1.45 ++		for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
    1.46  +			offsets[i].offset = j;
    1.47  +			j += offsets[i].size;
    1.48  +		}
    1.49 -+		return type;
    1.50 ++		return "32BE v3.0";
    1.51  +	}
    1.52  +}
    1.53  +
    1.54 @@ -101,7 +89,7 @@
    1.55  
    1.56  --- cloopreader.c
    1.57  +++ cloopreader.c
    1.58 -@@ -59,10 +59,20 @@
    1.59 +@@ -59,10 +59,21 @@
    1.60   
    1.61       ALLOC(c->pblock,c->blocksize);
    1.62   
    1.63 @@ -109,21 +97,22 @@
    1.64  +    c->tocsize=sizeof(*c->toc) * c->numblocks;
    1.65  +    if (c->numblocks == -1) {
    1.66  +	struct cloop_tail tail;
    1.67 ++	loff_t end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
    1.68  +
    1.69 -+	OP(lseek(c->fh, - sizeof(tail), SEEK_END)); 
    1.70 ++	OP(lseek(c->fh, end - sizeof(tail), SEEK_SET)); 
    1.71  +	OP(read_all(c->fh, &tail, sizeof(tail)));
    1.72  +	c->numblocks = ntohl(tail.num_blocks);
    1.73  +	c->tocsize = ntohl(tail.index_size) * c->numblocks;
    1.74 -+	OP(lseek(c->fh, - sizeof(tail) - c->tocsize, SEEK_END));
    1.75 ++	OP(lseek(c->fh, end - sizeof(tail) - c->tocsize, SEEK_SET));
    1.76  +    }
    1.77       ALLOC(c->toc,c->tocsize);
    1.78   
    1.79       OP(read_all(c->fh,c->toc,c->tocsize));  /* read Data Index */
    1.80 -+    build_index(c->toc, c->numblocks, c->blocksize);
    1.81 ++    build_index(c->toc, c->numblocks);
    1.82       c->cblocksizecur=0;
    1.83       c->curblock=-1;
    1.84       return 0;
    1.85 -@@ -79,10 +89,10 @@
    1.86 +@@ -79,10 +90,10 @@
    1.87       if(page>=c->numblocks){errno=EFAULT;return -1;}
    1.88       c->curblock=page;
    1.89   
    1.90 @@ -140,20 +129,51 @@
    1.91  
    1.92  --- extract_compressed_fs.c
    1.93  +++ extract_compressed_fs.c
    1.94 -@@ -7,6 +7,7 @@
    1.95 +@@ -1,15 +1,18 @@
    1.96 + /* Extracts a filesystem back from a compressed fs file */
    1.97 + #include "common_header.h"
    1.98 ++#define CLOOP_PREAMBLE "#!/bin/sh\n" "#V2.0 Format\n" "insmod cloop.o file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"
    1.99 + 
   1.100 + int main(int argc, char *argv[])
   1.101 + {
   1.102 + 	int handle;
   1.103   	struct cloop_head head;
   1.104   	unsigned int i;
   1.105 ++	unsigned long num_blocks, block_size, zblock_maxsize;
   1.106   	unsigned char *buffer, *clear_buffer;
   1.107  +	struct block_info *offsets;
   1.108   
   1.109 - 	if (argc != 2) {
   1.110 - 		fprintf(stderr, "Need filename\n");
   1.111 -@@ -30,35 +31,48 @@
   1.112 - 	fprintf(stderr, "%u blocks of size %u. Preamble:\n%s\n", 
   1.113 - 		ntohl(head.num_blocks), ntohl(head.block_size), head.preamble);
   1.114 +-	if (argc != 2) {
   1.115 +-		fprintf(stderr, "Need filename\n");
   1.116 ++	if (argc < 2 || argv[1][0] == '-') {
   1.117 ++		fprintf(stderr, "Usage: extract_compressed_fs file [--convert-to-v2] > output\n");
   1.118 + 		exit(1);
   1.119 + 	}
   1.120   
   1.121 -+	i = ntohl(head.num_blocks);
   1.122 -+	if (i == -1) {
   1.123 +@@ -24,44 +27,77 @@
   1.124 + 		exit(1);
   1.125 + 	}
   1.126 + 
   1.127 +-	buffer = malloc(ntohl(head.block_size) + ntohl(head.block_size)/1000
   1.128 +-			+ 12 + 4);
   1.129 +-	clear_buffer = malloc(ntohl(head.block_size));
   1.130 +-	fprintf(stderr, "%u blocks of size %u. Preamble:\n%s\n", 
   1.131 +-		ntohl(head.num_blocks), ntohl(head.block_size), head.preamble);
   1.132 +-
   1.133 +-	for (i = 0; i < ntohl(head.num_blocks); i++) {
   1.134 +-		int currpos;
   1.135 +-		unsigned long destlen = ntohl(head.block_size);
   1.136 +-		loff_t offset[2];
   1.137 +-		unsigned int size;
   1.138 ++	num_blocks = ntohl(head.num_blocks);
   1.139 ++	block_size = ntohl(head.block_size);
   1.140 ++	zblock_maxsize =  block_size + block_size/1000 + 12 + 4;
   1.141 ++	buffer = malloc(zblock_maxsize);
   1.142 ++	clear_buffer = malloc(block_size);
   1.143 ++	fprintf(stderr, "%lu blocks of size %lu. Preamble:\n%s\n", 
   1.144 ++		num_blocks, block_size, head.preamble);
   1.145 ++
   1.146 ++	if (num_blocks == -1) {
   1.147  +		struct cloop_tail tail;
   1.148  +		if (lseek(handle, - sizeof(tail), SEEK_END) < 0 ||
   1.149  +		    read(handle, &tail, sizeof(tail)) != sizeof(tail) ||
   1.150 @@ -164,23 +184,40 @@
   1.151  +			exit(1);
   1.152  +		}
   1.153  +		head.num_blocks = tail.num_blocks;
   1.154 -+		i = ntohl(tail.num_blocks) * ntohl(tail.index_size);
   1.155 ++		num_blocks = ntohl(head.num_blocks);
   1.156 ++		i = num_blocks * ntohl(tail.index_size);
   1.157  +	}
   1.158 -+	else i *= sizeof(*offsets);
   1.159 ++	else i = num_blocks * sizeof(*offsets);
   1.160  +	offsets = malloc(i);
   1.161  +	if (!offsets || read(handle, offsets, i) != i) {
   1.162  +		perror("Reading index\n");
   1.163  +		exit(1);
   1.164  +	}
   1.165  +	
   1.166 -+	fprintf(stderr, "Index %s.\n", build_index(offsets, 
   1.167 -+			ntohl(head.num_blocks), ntohl(head.block_size)));
   1.168 ++	fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks));
   1.169  +	
   1.170 - 	for (i = 0; i < ntohl(head.num_blocks); i++) {
   1.171 --		int currpos;
   1.172 - 		unsigned long destlen = ntohl(head.block_size);
   1.173 --		loff_t offset[2];
   1.174 --		unsigned int size;
   1.175 ++	if (argc > 2) {
   1.176 ++		loff_t offset;
   1.177 ++		int delta = ((num_blocks + 1) * sizeof(offset)) +
   1.178 ++			sizeof(head) - offsets[0].offset;
   1.179 ++		
   1.180 ++		strcpy(head.preamble, CLOOP_PREAMBLE);
   1.181 ++		write(STDOUT_FILENO, &head, sizeof(head));
   1.182 ++		for (i = 0; i < num_blocks; i++) {
   1.183 ++			offset = __be64_to_cpu(delta + offsets[i].offset); 
   1.184 ++			write(STDOUT_FILENO, &offset, sizeof(offset));
   1.185 ++		}
   1.186 ++		offset = __be64_to_cpu(delta + offsets[num_blocks-1].offset + offsets[num_blocks-1].size); 
   1.187 ++		write(STDOUT_FILENO, &offset, sizeof(offset));
   1.188 ++		for (i = 0; i < num_blocks && lseek(handle, offsets[i].offset, SEEK_SET) >= 0; i++) {
   1.189 ++			read(handle, buffer, offsets[i].size);
   1.190 ++			write(STDOUT_FILENO, buffer, offsets[i].size);
   1.191 ++		}
   1.192 ++		return 0;
   1.193 ++	}
   1.194 ++	
   1.195 ++	for (i = 0; i < num_blocks; i++) {
   1.196 ++		unsigned long destlen = block_size;
   1.197  +		unsigned int size = offsets[i].size;
   1.198   
   1.199  -		read(handle, &offset, 2*sizeof(loff_t));
   1.200 @@ -196,8 +233,9 @@
   1.201   		}
   1.202                   
   1.203  -                size=__be64_to_cpu(offset[1])-__be64_to_cpu(offset[0]);
   1.204 - 		if (size > ntohl(head.block_size) + ntohl(head.block_size)/1000
   1.205 - 		    + 12 + 4) {
   1.206 +-		if (size > ntohl(head.block_size) + ntohl(head.block_size)/1000
   1.207 +-		    + 12 + 4) {
   1.208 ++		if (size > zblock_maxsize) {
   1.209   			fprintf(stderr, 
   1.210   				"Size %u for block %u (offset %Lu) too big\n",
   1.211  -				size, i, __be64_to_cpu(offset[0]));
   1.212 @@ -210,5 +248,136 @@
   1.213  -			exit(1);
   1.214  -		}
   1.215   
   1.216 - 		fprintf(stderr, "Block %u length %u => %lu\n",
   1.217 - 			i, size, destlen);
   1.218 +-		fprintf(stderr, "Block %u length %u => %lu\n",
   1.219 +-			i, size, destlen);
   1.220 ++		fprintf(stderr, "Block %u at %llu length %u => %lu\n",
   1.221 ++			i, offsets[i].offset, size, destlen);
   1.222 + 		if (i == 3) {
   1.223 + 			fprintf(stderr,
   1.224 + 				"Block head:%02X%02X%02X%02X%02X%02X%02X%02X\n",
   1.225 +@@ -105,12 +141,12 @@
   1.226 + 			fprintf(stderr, "Uncomp: unknown error %u\n", i);
   1.227 + 			exit(1);
   1.228 + 		}
   1.229 +-		if (destlen != ntohl(head.block_size)) {
   1.230 +-			fprintf(stderr, "Uncomp: bad len %u (%lu not %u)\n", i,
   1.231 +-				destlen, ntohl(head.block_size));
   1.232 ++		if (destlen != block_size) {
   1.233 ++			fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i,
   1.234 ++				destlen, block_size);
   1.235 + 			exit(1);
   1.236 + 		}
   1.237 +-		write(STDOUT_FILENO, clear_buffer, ntohl(head.block_size));
   1.238 ++		write(STDOUT_FILENO, clear_buffer, block_size);
   1.239 + 	}
   1.240 + 	return 0;
   1.241 + }
   1.242 +
   1.243 +--- Makefile
   1.244 ++++ Makefile
   1.245 +@@ -1,16 +1,19 @@
   1.246 + PROGNAME=fusecloop
   1.247 + ARCFILES=*.c *.h *.pl Makefile configure README VERSION HELP INSTALL typescript *.cloop COPYING
   1.248 +-PROGS=fusecloop cloopreaderdemo extract_compressed_fs
   1.249 ++PROGS=fusecloop cloopreaderdemo extract_compressed_fs create_compressed_fs
   1.250 + FUSECFLAGS=`pkg-config fuse --cflags`
   1.251 + FUSELDFLAGS=`pkg-config fuse --libs` 
   1.252 + 
   1.253 + CFLAGS= -Wall
   1.254 + 
   1.255 +-all: fusecloop extract_compressed_fs 
   1.256 ++all: fusecloop extract_compressed_fs create_compressed_fs
   1.257 + 
   1.258 + extract_compressed_fs: extract_compressed_fs.c
   1.259 + 	${CC} ${CFLAGS} ${LDFLAGS} -lz extract_compressed_fs.c -o extract_compressed_fs
   1.260 + 
   1.261 ++create_compressed_fs: create_compressed_fs.c
   1.262 ++	${CC} ${CFLAGS} ${LDFLAGS} -lz create_compressed_fs.c -o create_compressed_fs
   1.263 ++
   1.264 + fusecloop: fusecloop.c cloopreader.o strver debug.o
   1.265 + 	${CC} ${CFLAGS} ${LDFLAGS} -lz cloopreader.o ${FUSECFLAGS} ${FUSELDFLAGS} fusecloop.c debug.o -o fusecloop
   1.266 + 
   1.267 +
   1.268 +--- create_compressed_fs.c
   1.269 ++++ create_compressed_fs.c
   1.270 +@@ -0,0 +1,80 @@
   1.271 ++/* Creates a compressed file */
   1.272 ++#include "common_header.h"
   1.273 ++
   1.274 ++#define CLOOP_PREAMBLE "#!/bin/sh\n" "#V3.0 Format\n" "insmod cloop.o file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"
   1.275 ++#define CHUNK 65536
   1.276 ++#define DEFAULT_BLOCKSIZE 65536
   1.277 ++
   1.278 ++static void quit(char *s)
   1.279 ++{
   1.280 ++	fprintf(stderr, "%s\n", s);
   1.281 ++	exit(1);
   1.282 ++}
   1.283 ++
   1.284 ++static int readblock(unsigned char *buffer, int n)
   1.285 ++{
   1.286 ++	int i;
   1.287 ++	
   1.288 ++	memset(buffer, 0, n);
   1.289 ++	for (i = 0 ; i < n;) {
   1.290 ++		int j = read(STDIN_FILENO, buffer + i, n - i);
   1.291 ++		if (j < 0 && errno == EINTR) continue;
   1.292 ++		if (j <= 0) break;
   1.293 ++		i += j;
   1.294 ++	}
   1.295 ++	return i;
   1.296 ++}
   1.297 ++
   1.298 ++int main(int argc, char *argv[])
   1.299 ++{
   1.300 ++	struct cloop_head head;
   1.301 ++	struct cloop_tail tail;
   1.302 ++	unsigned long  block_size = 0;
   1.303 ++	unsigned char *compressed, *uncompressed;
   1.304 ++	unsigned long *index;
   1.305 ++	int n, indexmax, zlenmax;
   1.306 ++	
   1.307 ++	if (argc > 1) {
   1.308 ++		if (argv[1][0] < '0' || argv[1][0] > '9')
   1.309 ++			quit("Usage : create_compressed_fs [block size] < input > output");
   1.310 ++		block_size = atoi(argv[1]);
   1.311 ++	}
   1.312 ++	if (block_size < 4096)
   1.313 ++		block_size = DEFAULT_BLOCKSIZE;
   1.314 ++	fprintf(stderr, "Block size is %lu\n", block_size);
   1.315 ++	zlenmax = block_size + block_size/1000 + 12;
   1.316 ++
   1.317 ++	memset(&head, 0, sizeof(head));
   1.318 ++	strcpy(head.preamble, CLOOP_PREAMBLE);
   1.319 ++	head.num_blocks = -1;
   1.320 ++	head.block_size = htonl(block_size);
   1.321 ++	write(STDOUT_FILENO, &head, sizeof(head));
   1.322 ++	
   1.323 ++	compressed = malloc(zlenmax);
   1.324 ++	uncompressed = malloc(block_size);
   1.325 ++	index = malloc(indexmax = CHUNK);
   1.326 ++	if (!compressed || !uncompressed || !index)
   1.327 ++		quit("Malloc failed");
   1.328 ++	
   1.329 ++	for (n = 0; readblock(uncompressed, block_size); n++) {
   1.330 ++		unsigned long len = zlenmax;
   1.331 ++		
   1.332 ++		if (compress2(compressed, &len, uncompressed, block_size, 
   1.333 ++				Z_BEST_COMPRESSION) != Z_OK)
   1.334 ++			quit("Compression failed");
   1.335 ++		fprintf(stderr, "Block %u length %lu => %lu\n",
   1.336 ++			n, block_size, len);
   1.337 ++		write(STDOUT_FILENO, compressed, len);
   1.338 ++		if (n * sizeof(*index) >= indexmax) {
   1.339 ++			index = realloc(index, indexmax += CHUNK);
   1.340 ++			if (!index)
   1.341 ++				quit("Realloc");
   1.342 ++		}
   1.343 ++		index[n] = ntohl(len);
   1.344 ++	}
   1.345 ++	write(STDOUT_FILENO, index, n * sizeof(*index));
   1.346 ++	tail.index_size = ntohl(sizeof(*index));
   1.347 ++	tail.num_blocks = ntohl(n);
   1.348 ++	write(STDOUT_FILENO, &tail, sizeof(tail));
   1.349 ++	return 0;
   1.350 ++}