wok-4.x view fusecloop/stuff/fusecloop.u @ rev 10937

fusecloop: large file support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Aug 28 10:58:22 2011 +0200 (2011-08-28)
parents e5f7f1b3d407
children 1e7452b326f8
line source
1 --- compressed_loop.h
2 +++ compressed_loop.h
3 @@ -41,6 +41,73 @@
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 index_size;
10 + u_int32_t num_blocks;
11 +};
12 +
13 +struct block_info
14 +{
15 + loff_t offset; /* 64-bit offsets of compressed block */
16 + u_int32_t size; /* 32-bit compressed block size */
17 + u_int32_t optidx; /* 32-bit index number */
18 +};
19 +
20 +static inline char *build_index(struct block_info *offsets, unsigned long n)
21 +{
22 + u_int32_t *ofs32 = (u_int32_t *) offsets;
23 + loff_t *ofs64 = (loff_t *) offsets;
24 +
25 + if (ofs32[0] == 0) {
26 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
27 + while (n--) {
28 + offsets[n].offset = __be64_to_cpu(offsets[n].offset);
29 + offsets[n].size = ntohl(offsets[n].size);
30 + }
31 + return "128BE accelerated knoppix 1.0";
32 + }
33 + else { /* V2.0 */
34 + loff_t last = __be64_to_cpu(ofs64[n]);
35 + while (n--) {
36 + offsets[n].size = last -
37 + (offsets[n].offset = __be64_to_cpu(ofs64[n]));
38 + last = offsets[n].offset;
39 + }
40 + return "64BE v2.0";
41 + }
42 + }
43 + else if (ofs32[1] == 0) { /* V1.0 */
44 + loff_t last = __be64_to_cpu(ofs64[n]);
45 + while (n--) {
46 + offsets[n].size = last -
47 + (offsets[n].offset = __le64_to_cpu(ofs64[n]));
48 + last = offsets[n].offset;
49 + }
50 + return "64LE v1.0";
51 + }
52 + else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
53 + loff_t last = ntohl(ofs32[n]);
54 + while (n--) {
55 + offsets[n].size = last -
56 + (offsets[n].offset = ntohl(ofs32[n]));
57 + last = offsets[n].offset;
58 + }
59 + return "32BE v0.68";
60 + }
61 + else { /* V3.0 */
62 + int i, j;
63 +
64 + for (i = n; i-- > 0; )
65 + offsets[i].size = ntohl(ofs32[i]);
66 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
67 + offsets[i].offset = j;
68 + j += offsets[i].size;
69 + }
70 + return "32BE v3.0";
71 + }
72 +}
73 +
74 /* Cloop suspend IOCTL */
75 #define CLOOP_SUSPEND 0x4C07
78 --- cloopreader.h
79 +++ cloopreader.h
80 @@ -33,7 +33,7 @@
81 int numblocks;
82 ulong blocksize;
84 - loff_t* toc; /* Data index */
85 + struct block_info *toc; /* Data index */
86 size_t tocsize;
88 unsigned char* cblock; /* Compressed block */
90 --- cloopreader.c
91 +++ cloopreader.c
92 @@ -59,10 +59,21 @@
94 ALLOC(c->pblock,c->blocksize);
96 - c->tocsize=sizeof *c->toc * (c->numblocks+1); /* One extra address is position of EOF */
97 + c->tocsize=sizeof(*c->toc) * c->numblocks;
98 + if (c->numblocks == -1) {
99 + struct cloop_tail tail;
100 + loff_t end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
101 +
102 + OP(lseek(c->fh, end - sizeof(tail), SEEK_SET));
103 + OP(read_all(c->fh, &tail, sizeof(tail)));
104 + c->numblocks = ntohl(tail.num_blocks);
105 + c->tocsize = ntohl(tail.index_size) * c->numblocks;
106 + OP(lseek(c->fh, end - sizeof(tail) - c->tocsize, SEEK_SET));
107 + }
108 ALLOC(c->toc,c->tocsize);
110 OP(read_all(c->fh,c->toc,c->tocsize)); /* read Data Index */
111 + build_index(c->toc, c->numblocks);
112 c->cblocksizecur=0;
113 c->curblock=-1;
114 return 0;
115 @@ -79,10 +90,10 @@
116 if(page>=c->numblocks){errno=EFAULT;return -1;}
117 c->curblock=page;
119 - bprintf("Seeking to 0x%Lx\n",btc(c->toc[page]));
120 - OP(lseek(c->fh,btc(c->toc[page]), SEEK_SET));
121 + bprintf("Seeking to 0x%Lx\n",c->toc[page].offset);
122 + OP(lseek(c->fh,c->toc[page].offset, SEEK_SET));
124 - c->cblocksize=btc(c->toc[page+1]) - btc(c->toc[page]);
125 + c->cblocksize=c->toc[page].size;
126 bprintf("Compressed size=%lu\n",c->cblocksize);
127 if(c->cblocksize > c->cblocksizecur){
128 if(c->cblocksizecur)free(c->cblock);
130 --- extract_compressed_fs.c
131 +++ extract_compressed_fs.c
132 @@ -1,15 +1,19 @@
133 /* Extracts a filesystem back from a compressed fs file */
134 +#define _LARGEFILE64_SOURCE
135 #include "common_header.h"
136 +#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"
138 int main(int argc, char *argv[])
139 {
140 int handle;
141 struct cloop_head head;
142 unsigned int i;
143 + unsigned long num_blocks, block_size, zblock_maxsize;
144 unsigned char *buffer, *clear_buffer;
145 + struct block_info *offsets;
147 - if (argc != 2) {
148 - fprintf(stderr, "Need filename\n");
149 + if (argc < 2 || argv[1][0] == '-') {
150 + fprintf(stderr, "Usage: extract_compressed_fs file [--convert-to-v2] > output\n");
151 exit(1);
152 }
154 @@ -24,44 +28,77 @@
155 exit(1);
156 }
158 - buffer = malloc(ntohl(head.block_size) + ntohl(head.block_size)/1000
159 - + 12 + 4);
160 - clear_buffer = malloc(ntohl(head.block_size));
161 - fprintf(stderr, "%u blocks of size %u. Preamble:\n%s\n",
162 - ntohl(head.num_blocks), ntohl(head.block_size), head.preamble);
163 -
164 - for (i = 0; i < ntohl(head.num_blocks); i++) {
165 - int currpos;
166 - unsigned long destlen = ntohl(head.block_size);
167 - loff_t offset[2];
168 - unsigned int size;
169 + num_blocks = ntohl(head.num_blocks);
170 + block_size = ntohl(head.block_size);
171 + zblock_maxsize = block_size + block_size/1000 + 12 + 4;
172 + buffer = malloc(zblock_maxsize);
173 + clear_buffer = malloc(block_size);
174 + fprintf(stderr, "%lu blocks of size %lu. Preamble:\n%s\n",
175 + num_blocks, block_size, head.preamble);
176 +
177 + if (num_blocks == -1) {
178 + struct cloop_tail tail;
179 + loff_t end = lseek64(handle, 0, SEEK_END);
180 + if (lseek64(handle, end - sizeof(tail), SEEK_SET) < 0 ||
181 + read(handle, &tail, sizeof(tail)) != sizeof(tail) ||
182 + lseek64(handle, end - sizeof(tail) -
183 + (ntohl(tail.num_blocks) * ntohl(tail.index_size)),
184 + SEEK_SET) < 0) {
185 + perror("Reading tail\n");
186 + exit(1);
187 + }
188 + head.num_blocks = tail.num_blocks;
189 + num_blocks = ntohl(head.num_blocks);
190 + i = num_blocks * ntohl(tail.index_size);
191 + }
192 + else i = num_blocks * sizeof(*offsets);
193 + offsets = malloc(i);
194 + if (!offsets || read(handle, offsets, i) != i) {
195 + perror("Reading index\n");
196 + exit(1);
197 + }
198 +
199 + fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks));
200 +
201 + if (argc > 2) {
202 + loff_t data, offset = ((num_blocks + 1) * sizeof(offset)) + sizeof(head);
203 +
204 + strcpy(head.preamble, CLOOP_PREAMBLE);
205 + write(STDOUT_FILENO, &head, sizeof(head));
206 + for (i = 0; i < num_blocks; i++) {
207 + data = __be64_to_cpu(offset);
208 + write(STDOUT_FILENO, &data, sizeof(data));
209 + offset += offsets[i].size;
210 + }
211 + data = __be64_to_cpu(offset);
212 + write(STDOUT_FILENO, &data, sizeof(data));
213 + for (i = 0; i < num_blocks && lseek64(handle, offsets[i].offset, SEEK_SET) >= 0; i++) {
214 + read(handle, buffer, offsets[i].size);
215 + write(STDOUT_FILENO, buffer, offsets[i].size);
216 + }
217 + return 0;
218 + }
219 +
220 + for (i = 0; i < num_blocks; i++) {
221 + unsigned long destlen = block_size;
222 + unsigned int size = offsets[i].size;
224 - read(handle, &offset, 2*sizeof(loff_t));
225 - lseek(handle, -sizeof(loff_t), SEEK_CUR);
226 -
227 - currpos = lseek(handle, 0, SEEK_CUR);
228 - if (lseek(handle, __be64_to_cpu(offset[0]), SEEK_SET) < 0) {
229 + if (lseek64(handle, offsets[i].offset, SEEK_SET) < 0) {
230 fprintf(stderr, "lseek to %Lu: %s\n",
231 - __be64_to_cpu(offset[0]), strerror(errno));
232 + offsets[i].offset, strerror(errno));
233 exit(1);
234 }
236 - size=__be64_to_cpu(offset[1])-__be64_to_cpu(offset[0]);
237 - if (size > ntohl(head.block_size) + ntohl(head.block_size)/1000
238 - + 12 + 4) {
239 + if (size > zblock_maxsize) {
240 fprintf(stderr,
241 "Size %u for block %u (offset %Lu) too big\n",
242 - size, i, __be64_to_cpu(offset[0]));
243 + size, i, offsets[i].offset);
244 exit(1);
245 }
246 read(handle, buffer, size);
247 - if (lseek(handle, currpos, SEEK_SET) < 0) {
248 - perror("seeking");
249 - exit(1);
250 - }
252 - fprintf(stderr, "Block %u length %u => %lu\n",
253 - i, size, destlen);
254 + fprintf(stderr, "Block %u at %llu length %u => %lu\n",
255 + i, offsets[i].offset, size, destlen);
256 if (i == 3) {
257 fprintf(stderr,
258 "Block head:%02X%02X%02X%02X%02X%02X%02X%02X\n",
259 @@ -105,12 +142,12 @@
260 fprintf(stderr, "Uncomp: unknown error %u\n", i);
261 exit(1);
262 }
263 - if (destlen != ntohl(head.block_size)) {
264 - fprintf(stderr, "Uncomp: bad len %u (%lu not %u)\n", i,
265 - destlen, ntohl(head.block_size));
266 + if (destlen != block_size) {
267 + fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i,
268 + destlen, block_size);
269 exit(1);
270 }
271 - write(STDOUT_FILENO, clear_buffer, ntohl(head.block_size));
272 + write(STDOUT_FILENO, clear_buffer, block_size);
273 }
274 return 0;
275 }
276 @@ -105,12 +140,12 @@
277 fprintf(stderr, "Uncomp: unknown error %u\n", i);
278 exit(1);
279 }
280 - if (destlen != ntohl(head.block_size)) {
281 - fprintf(stderr, "Uncomp: bad len %u (%lu not %u)\n", i,
282 - destlen, ntohl(head.block_size));
283 + if (destlen != block_size) {
284 + fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i,
285 + destlen, block_size);
286 exit(1);
287 }
288 - write(STDOUT_FILENO, clear_buffer, ntohl(head.block_size));
289 + write(STDOUT_FILENO, clear_buffer, block_size);
290 }
291 return 0;
292 }
294 --- Makefile
295 +++ Makefile
296 @@ -1,16 +1,19 @@
297 PROGNAME=fusecloop
298 ARCFILES=*.c *.h *.pl Makefile configure README VERSION HELP INSTALL typescript *.cloop COPYING
299 -PROGS=fusecloop cloopreaderdemo extract_compressed_fs
300 +PROGS=fusecloop cloopreaderdemo extract_compressed_fs create_compressed_fs
301 FUSECFLAGS=`pkg-config fuse --cflags`
302 FUSELDFLAGS=`pkg-config fuse --libs`
304 CFLAGS= -Wall
306 -all: fusecloop extract_compressed_fs
307 +all: fusecloop extract_compressed_fs create_compressed_fs
309 extract_compressed_fs: extract_compressed_fs.c
310 ${CC} ${CFLAGS} ${LDFLAGS} -lz extract_compressed_fs.c -o extract_compressed_fs
312 +create_compressed_fs: create_compressed_fs.c
313 + ${CC} ${CFLAGS} ${LDFLAGS} -lz create_compressed_fs.c -o create_compressed_fs
314 +
315 fusecloop: fusecloop.c cloopreader.o strver debug.o
316 ${CC} ${CFLAGS} ${LDFLAGS} -lz cloopreader.o ${FUSECFLAGS} ${FUSELDFLAGS} fusecloop.c debug.o -o fusecloop
319 --- create_compressed_fs.c
320 +++ create_compressed_fs.c
321 @@ -0,0 +1,80 @@
322 +/* Creates a compressed file */
323 +#include "common_header.h"
324 +
325 +#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"
326 +#define CHUNK 65536
327 +#define DEFAULT_BLOCKSIZE 65536
328 +
329 +static void quit(char *s)
330 +{
331 + fprintf(stderr, "%s\n", s);
332 + exit(1);
333 +}
334 +
335 +static int readblock(unsigned char *buffer, int n)
336 +{
337 + int i;
338 +
339 + memset(buffer, 0, n);
340 + for (i = 0 ; i < n;) {
341 + int j = read(STDIN_FILENO, buffer + i, n - i);
342 + if (j < 0 && errno == EINTR) continue;
343 + if (j <= 0) break;
344 + i += j;
345 + }
346 + return i;
347 +}
348 +
349 +int main(int argc, char *argv[])
350 +{
351 + struct cloop_head head;
352 + struct cloop_tail tail;
353 + unsigned long block_size = 0;
354 + unsigned char *compressed, *uncompressed;
355 + unsigned long *index;
356 + int n, indexmax, zlenmax;
357 +
358 + if (argc > 1) {
359 + if (argv[1][0] < '0' || argv[1][0] > '9')
360 + quit("Usage : create_compressed_fs [block size] < input > output");
361 + block_size = atoi(argv[1]);
362 + }
363 + if (block_size < 4096)
364 + block_size = DEFAULT_BLOCKSIZE;
365 + fprintf(stderr, "Block size is %lu\n", block_size);
366 + zlenmax = block_size + block_size/1000 + 12;
367 +
368 + memset(&head, 0, sizeof(head));
369 + strcpy(head.preamble, CLOOP_PREAMBLE);
370 + head.num_blocks = -1;
371 + head.block_size = htonl(block_size);
372 + write(STDOUT_FILENO, &head, sizeof(head));
373 +
374 + compressed = malloc(zlenmax);
375 + uncompressed = malloc(block_size);
376 + index = malloc(indexmax = CHUNK);
377 + if (!compressed || !uncompressed || !index)
378 + quit("Malloc failed");
379 +
380 + for (n = 0; readblock(uncompressed, block_size); n++) {
381 + unsigned long len = zlenmax;
382 +
383 + if (compress2(compressed, &len, uncompressed, block_size,
384 + Z_BEST_COMPRESSION) != Z_OK)
385 + quit("Compression failed");
386 + fprintf(stderr, "Block %u length %lu => %lu\n",
387 + n, block_size, len);
388 + write(STDOUT_FILENO, compressed, len);
389 + if (n * sizeof(*index) >= indexmax) {
390 + index = realloc(index, indexmax += CHUNK);
391 + if (!index)
392 + quit("Realloc");
393 + }
394 + index[n] = ntohl(len);
395 + }
396 + write(STDOUT_FILENO, index, n * sizeof(*index));
397 + tail.index_size = ntohl(sizeof(*index));
398 + tail.num_blocks = ntohl(n);
399 + write(STDOUT_FILENO, &tail, sizeof(tail));
400 + return 0;
401 +}