wok view fusecloop/stuff/fusecloop.u @ rev 17991

fusecloop: fix realloc index size
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Apr 23 15:42:00 2015 +0200 (2015-04-23)
parents bbffbcf032d1
children 002387f15e95
line source
1 --- compressed_loop.h
2 +++ compressed_loop.h
3 @@ -41,6 +41,75 @@
4 /* data_index (num_blocks 64bit pointers, network order)... */
5 /* compressed data (gzip block compressed format)... */
7 +struct cloop_tail
8 +{
9 + u_int32_t table_size;
10 + u_int32_t index_size;
11 + u_int32_t num_blocks;
12 +};
13 +
14 +struct block_info
15 +{
16 + loff_t offset; /* 64-bit offsets of compressed block */
17 + u_int32_t size; /* 32-bit compressed block size */
18 + u_int32_t optidx; /* 32-bit index number */
19 +};
20 +
21 +static inline char *build_index(struct block_info *offsets, unsigned long n)
22 +{
23 + u_int32_t *ofs32 = (u_int32_t *) offsets;
24 + loff_t *ofs64 = (loff_t *) offsets;
25 +
26 + if (ofs32[0] == 0) {
27 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
28 + while (n--) {
29 + offsets[n].offset = __be64_to_cpu(offsets[n].offset);
30 + offsets[n].size = ntohl(offsets[n].size);
31 + }
32 + return (char *) "128BE accelerated knoppix 1.0";
33 + }
34 + else { /* V2.0 */
35 + loff_t last = __be64_to_cpu(ofs64[n]);
36 + while (n--) {
37 + offsets[n].size = last -
38 + (offsets[n].offset = __be64_to_cpu(ofs64[n]));
39 + last = offsets[n].offset;
40 + }
41 + return (char *) "64BE v2.0";
42 + }
43 + }
44 + else if (ofs32[1] == 0) { /* V1.0 */
45 + loff_t last = __le64_to_cpu(ofs64[n]);
46 + while (n--) {
47 + offsets[n].size = last -
48 + (offsets[n].offset = __le64_to_cpu(ofs64[n]));
49 + last = offsets[n].offset;
50 + }
51 + return (char *) "64LE v1.0";
52 + }
53 + else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
54 + loff_t last = ntohl(ofs32[n]);
55 + while (n--) {
56 + offsets[n].size = last -
57 + (offsets[n].offset = ntohl(ofs32[n]));
58 + last = offsets[n].offset;
59 + }
60 + return (char *) "32BE v0.68";
61 + }
62 + else { /* V3.0 */
63 + unsigned long i;
64 + loff_t j;
65 +
66 + for (i = n; i-- != 0; )
67 + offsets[i].size = ntohl(ofs32[i]);
68 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
69 + offsets[i].offset = j;
70 + j += offsets[i].size;
71 + }
72 + return (char *) "32BE v3.0";
73 + }
74 +}
75 +
76 /* Cloop suspend IOCTL */
77 #define CLOOP_SUSPEND 0x4C07
80 --- cloopreader.h
81 +++ cloopreader.h
82 @@ -33,7 +33,7 @@
83 int numblocks;
84 ulong blocksize;
86 - loff_t* toc; /* Data index */
87 + struct block_info *toc; /* Data index */
88 size_t tocsize;
90 unsigned char* cblock; /* Compressed block */
92 --- cloopreader.c
93 +++ cloopreader.c
94 @@ -59,10 +59,32 @@
96 ALLOC(c->pblock,c->blocksize);
98 - c->tocsize=sizeof *c->toc * (c->numblocks+1); /* One extra address is position of EOF */
99 - ALLOC(c->toc,c->tocsize);
100 + if (c->numblocks + 1 == 0) {
101 + struct cloop_tail tail;
102 + loff_t end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
103 + void *p;
104 + ulong toclen, len;
106 - OP(read_all(c->fh,c->toc,c->tocsize)); /* read Data Index */
107 + OP(lseek(c->fh, end - sizeof(tail), SEEK_SET));
108 + OP(read_all(c->fh, &tail, sizeof(tail)));
109 + c->numblocks = ntohl(tail.num_blocks);
110 + c->tocsize = sizeof(*c->toc) * c->numblocks;
111 + len = ntohl(tail.table_size);
112 + toclen = (ntohl(tail.index_size) & 255) * c->numblocks;
113 + OP(lseek(c->fh, end - sizeof(tail) - len, SEEK_SET));
114 + ALLOC(c->toc, sizeof(*c->toc) * c->numblocks);
115 + ALLOC(p,len);
116 + OP(read_all(c->fh,p,len)); /* read Data Index */
117 + if (uncompress((void *)c->toc,&toclen,p,len) != Z_OK)
118 + exit(1);
119 + free(p);
120 + }
121 + else {
122 + c->tocsize = sizeof(*c->toc) * c->numblocks;
123 + ALLOC(c->toc,c->tocsize);
124 + OP(read_all(c->fh,c->toc,c->tocsize)); /* read Data Index */
125 + }
126 + build_index(c->toc, c->numblocks);
127 c->cblocksizecur=0;
128 c->curblock=-1;
129 return 0;
130 @@ -79,10 +101,10 @@
131 if(page>=c->numblocks){errno=EFAULT;return -1;}
132 c->curblock=page;
134 - bprintf("Seeking to 0x%Lx\n",btc(c->toc[page]));
135 - OP(lseek(c->fh,btc(c->toc[page]), SEEK_SET));
136 + bprintf("Seeking to 0x%Lx\n",c->toc[page].offset);
137 + OP(lseek(c->fh,c->toc[page].offset, SEEK_SET));
139 - c->cblocksize=btc(c->toc[page+1]) - btc(c->toc[page]);
140 + c->cblocksize=c->toc[page].size;
141 bprintf("Compressed size=%lu\n",c->cblocksize);
142 if(c->cblocksize > c->cblocksizecur){
143 if(c->cblocksizecur)free(c->cblock);
145 --- extract_compressed_fs.c
146 +++ extract_compressed_fs.c
147 @@ -1,19 +1,23 @@
148 /* Extracts a filesystem back from a compressed fs file */
149 +#define _LARGEFILE64_SOURCE
150 #include "common_header.h"
151 +#define CLOOP_PREAMBLE "#!/bin/sh\n" "#V2.0 Format\n" "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"
153 int main(int argc, char *argv[])
154 {
155 int handle;
156 struct cloop_head head;
157 unsigned int i;
158 + unsigned long num_blocks, block_size, zblock_maxsize;
159 unsigned char *buffer, *clear_buffer;
160 + struct block_info *offsets;
162 - if (argc != 2) {
163 - fprintf(stderr, "Need filename\n");
164 + if (argc < 2 || argv[1][0] == '-') {
165 + fprintf(stderr, "Usage: extract_compressed_fs file [--convert-to-v2] > output\n");
166 exit(1);
167 }
169 - handle = open(argv[1], O_RDONLY);
170 + handle = open(argv[1], O_RDONLY|O_LARGEFILE);
171 if (handle < 0) {
172 perror("Opening compressed file\n");
173 exit(1);
174 @@ -24,44 +28,99 @@
175 exit(1);
176 }
178 - buffer = malloc(ntohl(head.block_size) + ntohl(head.block_size)/1000
179 - + 12 + 4);
180 - clear_buffer = malloc(ntohl(head.block_size));
181 - fprintf(stderr, "%u blocks of size %u. Preamble:\n%s\n",
182 - ntohl(head.num_blocks), ntohl(head.block_size), head.preamble);
183 + num_blocks = ntohl(head.num_blocks);
184 + block_size = ntohl(head.block_size);
185 + zblock_maxsize = block_size + block_size/1000 + 12 + 4;
186 + buffer = malloc(zblock_maxsize);
187 + clear_buffer = malloc(block_size);
189 - for (i = 0; i < ntohl(head.num_blocks); i++) {
190 - int currpos;
191 - unsigned long destlen = ntohl(head.block_size);
192 - loff_t offset[2];
193 - unsigned int size;
194 + if (num_blocks == (unsigned long) -1) {
195 + void *table;
196 + struct cloop_tail tail;
197 + unsigned long len, table_size;
198 + loff_t end = lseek64(handle, 0, SEEK_END);
199 +
200 + if (lseek64(handle, end - sizeof(tail), SEEK_SET) < 0 ||
201 + read(handle, &tail, sizeof(tail)) != sizeof(tail) ||
202 + lseek64(handle, end - sizeof(tail) -
203 + ntohl(tail.table_size), SEEK_SET) < 0) {
204 + perror("Reading tail\n");
205 + exit(1);
206 + }
207 + head.num_blocks = tail.num_blocks;
208 + num_blocks = ntohl(head.num_blocks);
209 + table_size = ntohl(tail.table_size);
210 + table = malloc(table_size);
211 + len = i = num_blocks * (ntohl(tail.index_size) & 255);
212 + offsets = malloc(num_blocks * sizeof(*offsets));
213 + if (!table || !offsets ||
214 + read(handle, table, table_size) != table_size ||
215 + uncompress((void *)offsets, &len, table, table_size) != Z_OK ||
216 + len != i) {
217 + perror("Reading index\n");
218 + exit(1);
219 + }
220 + free(table);
221 + }
222 + else {
223 + offsets = malloc(i = num_blocks * sizeof(*offsets));
224 + if (!offsets || read(handle, offsets, i) != i) {
225 + perror("Reading index\n");
226 + exit(1);
227 + }
228 + }
229 +
230 + fprintf(stderr, "%lu blocks of size %lu. Preamble:\n%s\n",
231 + num_blocks, block_size, head.preamble);
232 + fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks));
233 +
234 + if (argc > 2) {
235 + unsigned n;
236 + loff_t data, offset = ((num_blocks + 1) * sizeof(offset)) + sizeof(head);
237 +
238 + strcpy(head.preamble, CLOOP_PREAMBLE);
239 + write(STDOUT_FILENO, &head, n = sizeof(head));
240 + for (i = 0; i < num_blocks; i++) {
241 + data = __be64_to_cpu(offset);
242 + write(STDOUT_FILENO, &data, sizeof(data));
243 + n += sizeof(data);
244 + offset += offsets[i].size;
245 + }
246 + data = __be64_to_cpu(offset);
247 + write(STDOUT_FILENO, &data, sizeof(data));
248 + for (i = 0; i < num_blocks && lseek64(handle, offsets[i].offset, SEEK_SET) >= 0; i++) {
249 + read(handle, buffer, offsets[i].size);
250 + write(STDOUT_FILENO, buffer, offsets[i].size);
251 + n += offsets[i].size;
252 + }
253 + n &= 0x1FF;
254 + if (n) {
255 + memset(buffer, 0, 512);
256 + write(STDOUT_FILENO, buffer, 512 - n);
257 + }
258 + return 0;
259 + }
260 +
261 + for (i = 0; i < num_blocks; i++) {
262 + unsigned long destlen = block_size;
263 + unsigned int size = offsets[i].size;
265 - read(handle, &offset, 2*sizeof(loff_t));
266 - lseek(handle, -sizeof(loff_t), SEEK_CUR);
267 -
268 - currpos = lseek(handle, 0, SEEK_CUR);
269 - if (lseek(handle, __be64_to_cpu(offset[0]), SEEK_SET) < 0) {
270 + if (lseek64(handle, offsets[i].offset, SEEK_SET) < 0) {
271 fprintf(stderr, "lseek to %Lu: %s\n",
272 - __be64_to_cpu(offset[0]), strerror(errno));
273 + offsets[i].offset, strerror(errno));
274 exit(1);
275 }
277 - size=__be64_to_cpu(offset[1])-__be64_to_cpu(offset[0]);
278 - if (size > ntohl(head.block_size) + ntohl(head.block_size)/1000
279 - + 12 + 4) {
280 + if (size > zblock_maxsize) {
281 fprintf(stderr,
282 "Size %u for block %u (offset %Lu) too big\n",
283 - size, i, __be64_to_cpu(offset[0]));
284 + size, i, offsets[i].offset);
285 exit(1);
286 }
287 read(handle, buffer, size);
288 - if (lseek(handle, currpos, SEEK_SET) < 0) {
289 - perror("seeking");
290 - exit(1);
291 - }
293 - fprintf(stderr, "Block %u length %u => %lu\n",
294 - i, size, destlen);
295 + fprintf(stderr, "Block %u at %llu length %u => %lu\n",
296 + i, offsets[i].offset, size, destlen);
297 if (i == 3) {
298 fprintf(stderr,
299 "Block head:%02X%02X%02X%02X%02X%02X%02X%02X\n",
300 @@ -105,12 +164,12 @@
301 fprintf(stderr, "Uncomp: unknown error %u\n", i);
302 exit(1);
303 }
304 - if (destlen != ntohl(head.block_size)) {
305 - fprintf(stderr, "Uncomp: bad len %u (%lu not %u)\n", i,
306 - destlen, ntohl(head.block_size));
307 + if (destlen != block_size) {
308 + fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i,
309 + destlen, block_size);
310 exit(1);
311 }
312 - write(STDOUT_FILENO, clear_buffer, ntohl(head.block_size));
313 + write(STDOUT_FILENO, clear_buffer, block_size);
314 }
315 return 0;
316 }
318 --- Makefile
319 +++ Makefile
320 @@ -1,16 +1,19 @@
321 PROGNAME=fusecloop
322 ARCFILES=*.c *.h *.pl Makefile configure README VERSION HELP INSTALL typescript *.cloop COPYING
323 -PROGS=fusecloop cloopreaderdemo extract_compressed_fs
324 +PROGS=fusecloop cloopreaderdemo extract_compressed_fs create_compressed_fs
325 FUSECFLAGS=`pkg-config fuse --cflags`
326 FUSELDFLAGS=`pkg-config fuse --libs`
328 CFLAGS= -Wall
330 -all: fusecloop extract_compressed_fs
331 +all: fusecloop extract_compressed_fs create_compressed_fs
333 extract_compressed_fs: extract_compressed_fs.c
334 ${CC} ${CFLAGS} ${LDFLAGS} -lz extract_compressed_fs.c -o extract_compressed_fs
336 +create_compressed_fs: create_compressed_fs.c
337 + ${CC} ${CFLAGS} ${LDFLAGS} -lz create_compressed_fs.c -o create_compressed_fs
338 +
339 fusecloop: fusecloop.c cloopreader.o strver debug.o
340 ${CC} ${CFLAGS} ${LDFLAGS} -lz cloopreader.o ${FUSECFLAGS} ${FUSELDFLAGS} fusecloop.c debug.o -o fusecloop
344 --- create_compressed_fs.c
345 +++ create_compressed_fs.c
346 @@ -0,0 +1,147 @@
347 +#ifdef FIND_BEST_COMPRESSION
348 +#include <compress.h>
349 +extern "C" {
350 +#include <stdlib.h>
351 +#include <string.h>
352 +
353 +static int best_compress(unsigned char *compressed,
354 + unsigned long *compressed_len,
355 + unsigned char *uncompressed,
356 + unsigned long uncompressed_len)
357 +{
358 + int i, j, err;
359 + unsigned char *buf[2];
360 + unsigned len;
361 + unsigned long llen, best = *compressed_len * 2;
362 + static unsigned char *buffer;
363 + static unsigned long buffersz;
364 +
365 + if (buffersz < *compressed_len) {
366 + if (buffer) free(buffer);
367 + buffer = (unsigned char *) malloc(buffersz = *compressed_len);
368 + if (!buffer) return Z_MEM_ERROR;
369 + }
370 + buf[0] = compressed;
371 + buf[1] = buffer;
372 + for (i = j = 0; i <= 10; i++) {
373 + llen = len = *compressed_len;
374 + if (i == 10)
375 + err = (compress_zlib(shrink_extreme, buf[j],
376 + len, uncompressed,
377 + uncompressed_len)) ? Z_OK : Z_DATA_ERROR;
378 + else {
379 + err = compress2(buf[j], &llen, uncompressed,
380 + uncompressed_len, i);
381 + len = llen;
382 + }
383 + if (err != Z_OK) return err;
384 + if (len < best) {
385 + best = len;
386 + j = 1 - j;
387 + }
388 + }
389 + *compressed_len = best;
390 + if (j == 0)
391 + memcpy(compressed, buffer, best);
392 + return err;
393 +}
394 +#define compress2(a,b,c,d,e) best_compress(a,b,c,d)
395 +#endif
396 +
397 +/* Creates a compressed file */
398 +#include "common_header.h"
399 +
400 +#define CLOOP_PREAMBLE "#!/bin/sh\n" "#V3.0 Format\n" "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"
401 +#define CHUNK 65536
402 +#define DEFAULT_BLOCKSIZE 65536
403 +
404 +static void quit(const char *s)
405 +{
406 + fprintf(stderr, "%s\n", s);
407 + exit(1);
408 +}
409 +
410 +static int readblock(unsigned char *buffer, int n)
411 +{
412 + int i;
413 +
414 + memset(buffer, 0, n);
415 + for (i = 0 ; i < n;) {
416 + int j = read(STDIN_FILENO, buffer + i, n - i);
417 + if (j < 0 && errno == EINTR) continue;
418 + if (j <= 0) break;
419 + i += j;
420 + }
421 + return i;
422 +}
423 +
424 +int main(int argc, char *argv[])
425 +{
426 + struct cloop_head head;
427 + struct cloop_tail tail;
428 + unsigned long block_size = 0;
429 + unsigned char *compressed, *uncompressed;
430 + unsigned long *index;
431 + int n, indexmax, zlenmax;
432 + unsigned long len, pos;
433 + static char padding[512];
434 +
435 + if (argc > 1) {
436 + if (argv[1][0] < '0' || argv[1][0] > '9')
437 + quit("Usage : create_compressed_fs [block size] < input > output");
438 + block_size = atoi(argv[1]);
439 + }
440 + if (block_size < 4096)
441 + block_size = DEFAULT_BLOCKSIZE;
442 + fprintf(stderr, "Block size is %lu\n", block_size);
443 + zlenmax = block_size + block_size/1000 + 12;
444 +
445 + memset(&head, 0, sizeof(head));
446 + strcpy(head.preamble, CLOOP_PREAMBLE);
447 + head.num_blocks = -1;
448 + head.block_size = htonl(block_size);
449 + write(STDOUT_FILENO, &head, sizeof(head));
450 + pos = sizeof(head);
451 +
452 + compressed = (unsigned char *) malloc(zlenmax);
453 + uncompressed = (unsigned char *) malloc(block_size);
454 + index = (unsigned long *) malloc(indexmax = CHUNK);
455 + if (!compressed || !uncompressed || !index)
456 + quit("Malloc failed");
457 +
458 + for (n = 0; readblock(uncompressed, block_size); n++) {
459 + len = zlenmax;
460 + if (compress2(compressed, &len, uncompressed, block_size,
461 + Z_BEST_COMPRESSION) != Z_OK)
462 + quit("Compression failed");
463 + fprintf(stderr, "Block %u length %lu => %lu\n",
464 + n, block_size, len);
465 + write(STDOUT_FILENO, compressed, len);
466 + pos += len;
467 + if (n * sizeof(*index) >= indexmax) {
468 + index = (unsigned long *) realloc(index,
469 + indexmax += CHUNK);
470 + if (!index)
471 + quit("Realloc");
472 + }
473 + index[n] = ntohl(len);
474 + }
475 + tail.index_size = ntohl(sizeof(*index));
476 + tail.num_blocks = ntohl(n);
477 + n *= sizeof(*index);
478 + len = n + n/1000 + 12;
479 + compressed = (unsigned char *) realloc(compressed, len);
480 + if (!compressed || compress2(compressed, &len, (unsigned char *) index,
481 + n, Z_BEST_COMPRESSION) != Z_OK)
482 + quit("Index compression failed");
483 + tail.table_size = ntohl(len);
484 + pos += len + sizeof(tail);
485 + n = pos & 511;
486 + if (n) write(STDOUT_FILENO, padding, 512 - n);
487 + write(STDOUT_FILENO, compressed, len);
488 + write(STDOUT_FILENO, &tail, sizeof(tail));
489 + return 0;
490 +}
491 +#ifdef FIND_BEST_COMPRESSION
492 +}
493 +#endif
495 --- fusecloop.c
496 +++ fusecloop.c
497 @@ -65,7 +65,7 @@
499 memcpy(stbuf,&stb,sizeof stb);
500 stbuf->st_mode&=~0222;
501 - stbuf->st_size = cd.blocksize * cd.numblocks;
502 + stbuf->st_size = (loff_t) cd.blocksize * cd.numblocks;
503 /*
504 stbuf->st_mode = S_IFREG | 0444;
505 stbuf->st_nlink = 1;