rev |
line source |
pascal@10932
|
1 --- compressed_loop.h
|
pascal@10932
|
2 +++ compressed_loop.h
|
pascal@18828
|
3 @@ -41,6 +41,80 @@
|
pascal@10932
|
4 /* data_index (num_blocks 64bit pointers, network order)... */
|
pascal@10932
|
5 /* compressed data (gzip block compressed format)... */
|
pascal@10932
|
6
|
pascal@10933
|
7 +struct cloop_tail
|
pascal@10933
|
8 +{
|
pascal@12214
|
9 + u_int32_t table_size;
|
pascal@10933
|
10 + u_int32_t index_size;
|
pascal@10933
|
11 + u_int32_t num_blocks;
|
pascal@10933
|
12 +};
|
pascal@10933
|
13 +
|
pascal@10932
|
14 +struct block_info
|
pascal@10932
|
15 +{
|
pascal@10932
|
16 + loff_t offset; /* 64-bit offsets of compressed block */
|
pascal@10932
|
17 + u_int32_t size; /* 32-bit compressed block size */
|
pascal@10932
|
18 + u_int32_t optidx; /* 32-bit index number */
|
pascal@10932
|
19 +};
|
pascal@10932
|
20 +
|
pascal@10935
|
21 +static inline char *build_index(struct block_info *offsets, unsigned long n)
|
pascal@10932
|
22 +{
|
pascal@10932
|
23 + u_int32_t *ofs32 = (u_int32_t *) offsets;
|
pascal@10932
|
24 + loff_t *ofs64 = (loff_t *) offsets;
|
pascal@10933
|
25 +
|
pascal@10932
|
26 + if (ofs32[0] == 0) {
|
pascal@10932
|
27 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
|
pascal@10933
|
28 + while (n--) {
|
pascal@10932
|
29 + offsets[n].offset = __be64_to_cpu(offsets[n].offset);
|
pascal@10932
|
30 + offsets[n].size = ntohl(offsets[n].size);
|
pascal@10933
|
31 + }
|
pascal@12214
|
32 + return (char *) "128BE accelerated knoppix 1.0";
|
pascal@10932
|
33 + }
|
pascal@10932
|
34 + else { /* V2.0 */
|
pascal@10933
|
35 + loff_t last = __be64_to_cpu(ofs64[n]);
|
pascal@10933
|
36 + while (n--) {
|
pascal@10932
|
37 + offsets[n].size = last -
|
pascal@10932
|
38 + (offsets[n].offset = __be64_to_cpu(ofs64[n]));
|
pascal@10932
|
39 + last = offsets[n].offset;
|
pascal@10933
|
40 + }
|
pascal@12214
|
41 + return (char *) "64BE v2.0";
|
pascal@10932
|
42 + }
|
pascal@10932
|
43 + }
|
pascal@10932
|
44 + else if (ofs32[1] == 0) { /* V1.0 */
|
pascal@11113
|
45 + loff_t last = __le64_to_cpu(ofs64[n]);
|
pascal@10933
|
46 + while (n--) {
|
pascal@10932
|
47 + offsets[n].size = last -
|
pascal@10932
|
48 + (offsets[n].offset = __le64_to_cpu(ofs64[n]));
|
pascal@10932
|
49 + last = offsets[n].offset;
|
pascal@10933
|
50 + }
|
pascal@12214
|
51 + return (char *) "64LE v1.0";
|
pascal@10932
|
52 + }
|
pascal@10933
|
53 + else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
|
pascal@10933
|
54 + loff_t last = ntohl(ofs32[n]);
|
pascal@10933
|
55 + while (n--) {
|
pascal@10932
|
56 + offsets[n].size = last -
|
pascal@10932
|
57 + (offsets[n].offset = ntohl(ofs32[n]));
|
pascal@10932
|
58 + last = offsets[n].offset;
|
pascal@10933
|
59 + }
|
pascal@12214
|
60 + return (char *) "32BE v0.68";
|
pascal@10932
|
61 + }
|
pascal@10933
|
62 + else { /* V3.0 */
|
pascal@17169
|
63 + unsigned long i;
|
pascal@17168
|
64 + loff_t j;
|
pascal@10933
|
65 +
|
pascal@17169
|
66 + for (i = n; i-- != 0; )
|
pascal@10935
|
67 + offsets[i].size = ntohl(ofs32[i]);
|
pascal@10935
|
68 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
|
pascal@10933
|
69 + offsets[i].offset = j;
|
pascal@18828
|
70 + if (offsets[i].size & 0x80000000) {
|
pascal@18829
|
71 + unsigned long k = offsets[i].size & 0x7FFFFFFF;
|
pascal@18828
|
72 + offsets[i].offset = offsets[k].offset;
|
pascal@18828
|
73 + offsets[i].size = offsets[k].size;
|
pascal@18828
|
74 + }
|
pascal@18828
|
75 + else j += offsets[i].size;
|
pascal@10933
|
76 + }
|
pascal@12214
|
77 + return (char *) "32BE v3.0";
|
pascal@10933
|
78 + }
|
pascal@10932
|
79 +}
|
pascal@10932
|
80 +
|
pascal@10932
|
81 /* Cloop suspend IOCTL */
|
pascal@10932
|
82 #define CLOOP_SUSPEND 0x4C07
|
pascal@10932
|
83
|
pascal@10932
|
84
|
pascal@10932
|
85 --- cloopreader.h
|
pascal@10932
|
86 +++ cloopreader.h
|
pascal@10932
|
87 @@ -33,7 +33,7 @@
|
pascal@10932
|
88 int numblocks;
|
pascal@10932
|
89 ulong blocksize;
|
pascal@10932
|
90
|
pascal@10932
|
91 - loff_t* toc; /* Data index */
|
pascal@10932
|
92 + struct block_info *toc; /* Data index */
|
pascal@10932
|
93 size_t tocsize;
|
pascal@10932
|
94
|
pascal@10932
|
95 unsigned char* cblock; /* Compressed block */
|
pascal@10932
|
96
|
pascal@10932
|
97 --- cloopreader.c
|
pascal@10932
|
98 +++ cloopreader.c
|
pascal@12214
|
99 @@ -59,10 +59,32 @@
|
pascal@10932
|
100
|
pascal@10932
|
101 ALLOC(c->pblock,c->blocksize);
|
pascal@10932
|
102
|
pascal@10932
|
103 - c->tocsize=sizeof *c->toc * (c->numblocks+1); /* One extra address is position of EOF */
|
pascal@12214
|
104 - ALLOC(c->toc,c->tocsize);
|
pascal@12214
|
105 + if (c->numblocks + 1 == 0) {
|
pascal@10933
|
106 + struct cloop_tail tail;
|
pascal@10935
|
107 + loff_t end = lseek(c->fh,0,SEEK_END); /* lseek(,-n,SEEK_END) buggy ? */
|
pascal@12214
|
108 + void *p;
|
pascal@12214
|
109 + ulong toclen, len;
|
pascal@12214
|
110
|
pascal@12214
|
111 - OP(read_all(c->fh,c->toc,c->tocsize)); /* read Data Index */
|
pascal@10935
|
112 + OP(lseek(c->fh, end - sizeof(tail), SEEK_SET));
|
pascal@10933
|
113 + OP(read_all(c->fh, &tail, sizeof(tail)));
|
pascal@10933
|
114 + c->numblocks = ntohl(tail.num_blocks);
|
pascal@12214
|
115 + c->tocsize = sizeof(*c->toc) * c->numblocks;
|
pascal@12214
|
116 + len = ntohl(tail.table_size);
|
pascal@12214
|
117 + toclen = (ntohl(tail.index_size) & 255) * c->numblocks;
|
pascal@12214
|
118 + OP(lseek(c->fh, end - sizeof(tail) - len, SEEK_SET));
|
pascal@17168
|
119 + ALLOC(c->toc, sizeof(*c->toc) * c->numblocks);
|
pascal@12214
|
120 + ALLOC(p,len);
|
pascal@12214
|
121 + OP(read_all(c->fh,p,len)); /* read Data Index */
|
pascal@12214
|
122 + if (uncompress((void *)c->toc,&toclen,p,len) != Z_OK)
|
pascal@12214
|
123 + exit(1);
|
pascal@12214
|
124 + free(p);
|
pascal@10933
|
125 + }
|
pascal@12214
|
126 + else {
|
pascal@12214
|
127 + c->tocsize = sizeof(*c->toc) * c->numblocks;
|
pascal@12214
|
128 + ALLOC(c->toc,c->tocsize);
|
pascal@12214
|
129 + OP(read_all(c->fh,c->toc,c->tocsize)); /* read Data Index */
|
pascal@12214
|
130 + }
|
pascal@10935
|
131 + build_index(c->toc, c->numblocks);
|
pascal@10932
|
132 c->cblocksizecur=0;
|
pascal@10932
|
133 c->curblock=-1;
|
pascal@10932
|
134 return 0;
|
pascal@12214
|
135 @@ -79,10 +101,10 @@
|
pascal@10932
|
136 if(page>=c->numblocks){errno=EFAULT;return -1;}
|
pascal@10932
|
137 c->curblock=page;
|
pascal@10932
|
138
|
pascal@10932
|
139 - bprintf("Seeking to 0x%Lx\n",btc(c->toc[page]));
|
pascal@10932
|
140 - OP(lseek(c->fh,btc(c->toc[page]), SEEK_SET));
|
pascal@10932
|
141 + bprintf("Seeking to 0x%Lx\n",c->toc[page].offset);
|
pascal@10932
|
142 + OP(lseek(c->fh,c->toc[page].offset, SEEK_SET));
|
pascal@10932
|
143
|
pascal@10932
|
144 - c->cblocksize=btc(c->toc[page+1]) - btc(c->toc[page]);
|
pascal@10932
|
145 + c->cblocksize=c->toc[page].size;
|
pascal@10932
|
146 bprintf("Compressed size=%lu\n",c->cblocksize);
|
pascal@10932
|
147 if(c->cblocksize > c->cblocksizecur){
|
pascal@10932
|
148 if(c->cblocksizecur)free(c->cblock);
|
pascal@10933
|
149
|
pascal@10932
|
150 --- extract_compressed_fs.c
|
pascal@10932
|
151 +++ extract_compressed_fs.c
|
pascal@17885
|
152 @@ -1,19 +1,23 @@
|
pascal@10935
|
153 /* Extracts a filesystem back from a compressed fs file */
|
pascal@10937
|
154 +#define _LARGEFILE64_SOURCE
|
pascal@10935
|
155 #include "common_header.h"
|
pascal@12214
|
156 +#define CLOOP_PREAMBLE "#!/bin/sh\n" "#V2.0 Format\n" "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"
|
pascal@10935
|
157
|
pascal@10935
|
158 int main(int argc, char *argv[])
|
pascal@10935
|
159 {
|
pascal@10935
|
160 int handle;
|
pascal@10932
|
161 struct cloop_head head;
|
pascal@10932
|
162 unsigned int i;
|
pascal@17996
|
163 + unsigned long num_blocks, block_size, zblock_maxsize, lastlen = 0;
|
pascal@10932
|
164 unsigned char *buffer, *clear_buffer;
|
pascal@10932
|
165 + struct block_info *offsets;
|
pascal@10932
|
166
|
pascal@10935
|
167 - if (argc != 2) {
|
pascal@10935
|
168 - fprintf(stderr, "Need filename\n");
|
pascal@10935
|
169 + if (argc < 2 || argv[1][0] == '-') {
|
pascal@10935
|
170 + fprintf(stderr, "Usage: extract_compressed_fs file [--convert-to-v2] > output\n");
|
pascal@10935
|
171 exit(1);
|
pascal@10935
|
172 }
|
pascal@10932
|
173
|
pascal@17885
|
174 - handle = open(argv[1], O_RDONLY);
|
pascal@17885
|
175 + handle = open(argv[1], O_RDONLY|O_LARGEFILE);
|
pascal@17885
|
176 if (handle < 0) {
|
pascal@17885
|
177 perror("Opening compressed file\n");
|
pascal@17885
|
178 exit(1);
|
pascal@18894
|
179 @@ -24,66 +28,100 @@
|
pascal@10935
|
180 exit(1);
|
pascal@10935
|
181 }
|
pascal@10935
|
182
|
pascal@10935
|
183 - buffer = malloc(ntohl(head.block_size) + ntohl(head.block_size)/1000
|
pascal@10935
|
184 - + 12 + 4);
|
pascal@10935
|
185 - clear_buffer = malloc(ntohl(head.block_size));
|
pascal@10935
|
186 - fprintf(stderr, "%u blocks of size %u. Preamble:\n%s\n",
|
pascal@10935
|
187 - ntohl(head.num_blocks), ntohl(head.block_size), head.preamble);
|
pascal@12214
|
188 + num_blocks = ntohl(head.num_blocks);
|
pascal@12214
|
189 + block_size = ntohl(head.block_size);
|
pascal@12214
|
190 + zblock_maxsize = block_size + block_size/1000 + 12 + 4;
|
pascal@12214
|
191 + buffer = malloc(zblock_maxsize);
|
pascal@12214
|
192 + clear_buffer = malloc(block_size);
|
pascal@12214
|
193
|
pascal@10935
|
194 - for (i = 0; i < ntohl(head.num_blocks); i++) {
|
pascal@10935
|
195 - int currpos;
|
pascal@10935
|
196 - unsigned long destlen = ntohl(head.block_size);
|
pascal@10935
|
197 - loff_t offset[2];
|
pascal@10935
|
198 - unsigned int size;
|
pascal@12214
|
199 + if (num_blocks == (unsigned long) -1) {
|
pascal@12214
|
200 + void *table;
|
pascal@10933
|
201 + struct cloop_tail tail;
|
pascal@12214
|
202 + unsigned long len, table_size;
|
pascal@10937
|
203 + loff_t end = lseek64(handle, 0, SEEK_END);
|
pascal@12214
|
204 +
|
pascal@10937
|
205 + if (lseek64(handle, end - sizeof(tail), SEEK_SET) < 0 ||
|
pascal@10933
|
206 + read(handle, &tail, sizeof(tail)) != sizeof(tail) ||
|
pascal@10937
|
207 + lseek64(handle, end - sizeof(tail) -
|
pascal@12214
|
208 + ntohl(tail.table_size), SEEK_SET) < 0) {
|
pascal@10933
|
209 + perror("Reading tail\n");
|
pascal@10933
|
210 + exit(1);
|
pascal@10933
|
211 + }
|
pascal@10933
|
212 + head.num_blocks = tail.num_blocks;
|
pascal@10935
|
213 + num_blocks = ntohl(head.num_blocks);
|
pascal@12214
|
214 + table_size = ntohl(tail.table_size);
|
pascal@12214
|
215 + table = malloc(table_size);
|
pascal@12214
|
216 + len = i = num_blocks * (ntohl(tail.index_size) & 255);
|
pascal@18894
|
217 + lastlen = ntohl(tail.index_size) / 256;
|
pascal@12214
|
218 + offsets = malloc(num_blocks * sizeof(*offsets));
|
pascal@12214
|
219 + if (!table || !offsets ||
|
pascal@12214
|
220 + read(handle, table, table_size) != table_size ||
|
pascal@12214
|
221 + uncompress((void *)offsets, &len, table, table_size) != Z_OK ||
|
pascal@12214
|
222 + len != i) {
|
pascal@12214
|
223 + perror("Reading index\n");
|
pascal@12214
|
224 + exit(1);
|
pascal@12214
|
225 + }
|
pascal@12214
|
226 + free(table);
|
pascal@10933
|
227 + }
|
pascal@12214
|
228 + else {
|
pascal@12214
|
229 + offsets = malloc(i = num_blocks * sizeof(*offsets));
|
pascal@12214
|
230 + if (!offsets || read(handle, offsets, i) != i) {
|
pascal@12214
|
231 + perror("Reading index\n");
|
pascal@12214
|
232 + exit(1);
|
pascal@12214
|
233 + }
|
pascal@10932
|
234 + }
|
pascal@10932
|
235 +
|
pascal@12214
|
236 + fprintf(stderr, "%lu blocks of size %lu. Preamble:\n%s\n",
|
pascal@12214
|
237 + num_blocks, block_size, head.preamble);
|
pascal@10935
|
238 + fprintf(stderr, "Index %s.\n", build_index(offsets, num_blocks));
|
pascal@10932
|
239 +
|
pascal@10935
|
240 + if (argc > 2) {
|
pascal@14712
|
241 + unsigned n;
|
pascal@10936
|
242 + loff_t data, offset = ((num_blocks + 1) * sizeof(offset)) + sizeof(head);
|
pascal@10935
|
243 +
|
pascal@10935
|
244 + strcpy(head.preamble, CLOOP_PREAMBLE);
|
pascal@14712
|
245 + write(STDOUT_FILENO, &head, n = sizeof(head));
|
pascal@10935
|
246 + for (i = 0; i < num_blocks; i++) {
|
pascal@10936
|
247 + data = __be64_to_cpu(offset);
|
pascal@10936
|
248 + write(STDOUT_FILENO, &data, sizeof(data));
|
pascal@14712
|
249 + n += sizeof(data);
|
pascal@10936
|
250 + offset += offsets[i].size;
|
pascal@10935
|
251 + }
|
pascal@10936
|
252 + data = __be64_to_cpu(offset);
|
pascal@10936
|
253 + write(STDOUT_FILENO, &data, sizeof(data));
|
pascal@10937
|
254 + for (i = 0; i < num_blocks && lseek64(handle, offsets[i].offset, SEEK_SET) >= 0; i++) {
|
pascal@10935
|
255 + read(handle, buffer, offsets[i].size);
|
pascal@10935
|
256 + write(STDOUT_FILENO, buffer, offsets[i].size);
|
pascal@14712
|
257 + n += offsets[i].size;
|
pascal@14712
|
258 + }
|
pascal@14712
|
259 + n &= 0x1FF;
|
pascal@14712
|
260 + if (n) {
|
pascal@14712
|
261 + memset(buffer, 0, 512);
|
pascal@14712
|
262 + write(STDOUT_FILENO, buffer, 512 - n);
|
pascal@10935
|
263 + }
|
pascal@10935
|
264 + return 0;
|
pascal@10935
|
265 + }
|
pascal@10935
|
266 +
|
pascal@10935
|
267 + for (i = 0; i < num_blocks; i++) {
|
pascal@10935
|
268 + unsigned long destlen = block_size;
|
pascal@10932
|
269 + unsigned int size = offsets[i].size;
|
pascal@10932
|
270
|
pascal@10932
|
271 - read(handle, &offset, 2*sizeof(loff_t));
|
pascal@10932
|
272 - lseek(handle, -sizeof(loff_t), SEEK_CUR);
|
pascal@10932
|
273 -
|
pascal@10932
|
274 - currpos = lseek(handle, 0, SEEK_CUR);
|
pascal@10932
|
275 - if (lseek(handle, __be64_to_cpu(offset[0]), SEEK_SET) < 0) {
|
pascal@10937
|
276 + if (lseek64(handle, offsets[i].offset, SEEK_SET) < 0) {
|
pascal@10932
|
277 fprintf(stderr, "lseek to %Lu: %s\n",
|
pascal@10932
|
278 - __be64_to_cpu(offset[0]), strerror(errno));
|
pascal@10932
|
279 + offsets[i].offset, strerror(errno));
|
pascal@10932
|
280 exit(1);
|
pascal@10932
|
281 }
|
pascal@10932
|
282
|
pascal@10932
|
283 - size=__be64_to_cpu(offset[1])-__be64_to_cpu(offset[0]);
|
pascal@10935
|
284 - if (size > ntohl(head.block_size) + ntohl(head.block_size)/1000
|
pascal@10935
|
285 - + 12 + 4) {
|
pascal@10935
|
286 + if (size > zblock_maxsize) {
|
pascal@10932
|
287 fprintf(stderr,
|
pascal@10932
|
288 "Size %u for block %u (offset %Lu) too big\n",
|
pascal@10932
|
289 - size, i, __be64_to_cpu(offset[0]));
|
pascal@10932
|
290 + size, i, offsets[i].offset);
|
pascal@10932
|
291 exit(1);
|
pascal@10932
|
292 }
|
pascal@10932
|
293 read(handle, buffer, size);
|
pascal@10932
|
294 - if (lseek(handle, currpos, SEEK_SET) < 0) {
|
pascal@10932
|
295 - perror("seeking");
|
pascal@10932
|
296 - exit(1);
|
pascal@10932
|
297 - }
|
pascal@10932
|
298
|
pascal@10935
|
299 - fprintf(stderr, "Block %u length %u => %lu\n",
|
pascal@10935
|
300 - i, size, destlen);
|
pascal@18894
|
301 - if (i == 3) {
|
pascal@18894
|
302 - fprintf(stderr,
|
pascal@18894
|
303 - "Block head:%02X%02X%02X%02X%02X%02X%02X%02X\n",
|
pascal@18894
|
304 - buffer[0],
|
pascal@18894
|
305 - buffer[1],
|
pascal@18894
|
306 - buffer[2],
|
pascal@18894
|
307 - buffer[3],
|
pascal@18894
|
308 - buffer[4],
|
pascal@18894
|
309 - buffer[5],
|
pascal@18894
|
310 - buffer[6],
|
pascal@18894
|
311 - buffer[7]);
|
pascal@18894
|
312 - fprintf(stderr,
|
pascal@18894
|
313 - "Block tail:%02X%02X%02X%02X%02X%02X%02X%02X\n",
|
pascal@18894
|
314 - buffer[3063],
|
pascal@18894
|
315 - buffer[3064],
|
pascal@18894
|
316 - buffer[3065],
|
pascal@18894
|
317 - buffer[3066],
|
pascal@18894
|
318 - buffer[3067],
|
pascal@18894
|
319 - buffer[3068],
|
pascal@18894
|
320 - buffer[3069],
|
pascal@18894
|
321 - buffer[3070]);
|
pascal@18894
|
322 - }
|
pascal@18894
|
323 + fprintf(stderr, "Block %u at %llu length %u",
|
pascal@18894
|
324 + i, offsets[i].offset, size);
|
pascal@18894
|
325 switch (uncompress(clear_buffer, &destlen,
|
pascal@18894
|
326 buffer, size)) {
|
pascal@18894
|
327 case Z_OK:
|
pascal@18894
|
328 @@ -105,12 +143,13 @@
|
pascal@10937
|
329 fprintf(stderr, "Uncomp: unknown error %u\n", i);
|
pascal@10937
|
330 exit(1);
|
pascal@10937
|
331 }
|
pascal@10937
|
332 - if (destlen != ntohl(head.block_size)) {
|
pascal@10937
|
333 - fprintf(stderr, "Uncomp: bad len %u (%lu not %u)\n", i,
|
pascal@10937
|
334 - destlen, ntohl(head.block_size));
|
pascal@18894
|
335 + fprintf(stderr, " => %lu\n", destlen);
|
pascal@18894
|
336 + if (destlen != block_size && i != num_blocks - 1) {
|
pascal@10937
|
337 + fprintf(stderr, "Uncomp: bad len %u (%lu not %lu)\n", i,
|
pascal@10937
|
338 + destlen, block_size);
|
pascal@10937
|
339 exit(1);
|
pascal@10937
|
340 }
|
pascal@10937
|
341 - write(STDOUT_FILENO, clear_buffer, ntohl(head.block_size));
|
pascal@17996
|
342 + write(STDOUT_FILENO, clear_buffer, (lastlen != 0 && (i+1) == num_blocks) ? lastlen : block_size);
|
pascal@10937
|
343 }
|
pascal@10937
|
344 return 0;
|
pascal@10937
|
345 }
|
pascal@10935
|
346 --- Makefile
|
pascal@10935
|
347 +++ Makefile
|
pascal@10935
|
348 @@ -1,16 +1,19 @@
|
pascal@10935
|
349 PROGNAME=fusecloop
|
pascal@10935
|
350 ARCFILES=*.c *.h *.pl Makefile configure README VERSION HELP INSTALL typescript *.cloop COPYING
|
pascal@10935
|
351 -PROGS=fusecloop cloopreaderdemo extract_compressed_fs
|
pascal@10935
|
352 +PROGS=fusecloop cloopreaderdemo extract_compressed_fs create_compressed_fs
|
pascal@10935
|
353 FUSECFLAGS=`pkg-config fuse --cflags`
|
pascal@10935
|
354 FUSELDFLAGS=`pkg-config fuse --libs`
|
pascal@10935
|
355
|
pascal@10935
|
356 CFLAGS= -Wall
|
pascal@10935
|
357
|
pascal@10935
|
358 -all: fusecloop extract_compressed_fs
|
pascal@10935
|
359 +all: fusecloop extract_compressed_fs create_compressed_fs
|
pascal@10935
|
360
|
pascal@10935
|
361 extract_compressed_fs: extract_compressed_fs.c
|
pascal@10935
|
362 ${CC} ${CFLAGS} ${LDFLAGS} -lz extract_compressed_fs.c -o extract_compressed_fs
|
pascal@10935
|
363
|
pascal@18894
|
364 +create_compressed_fs: create_compressed_fs.c md5sum.c
|
pascal@10935
|
365 + ${CC} ${CFLAGS} ${LDFLAGS} -lz create_compressed_fs.c -o create_compressed_fs
|
pascal@10935
|
366 +
|
pascal@10935
|
367 fusecloop: fusecloop.c cloopreader.o strver debug.o
|
pascal@10935
|
368 ${CC} ${CFLAGS} ${LDFLAGS} -lz cloopreader.o ${FUSECFLAGS} ${FUSELDFLAGS} fusecloop.c debug.o -o fusecloop
|
pascal@10935
|
369
|
pascal@10935
|
370
|
pascal@12214
|
371
|
pascal@18894
|
372 --- md5sum.c
|
pascal@18894
|
373 +++ md5sum.c
|
pascal@18894
|
374 @@ -0,0 +1,246 @@
|
pascal@18894
|
375 +/*
|
pascal@18894
|
376 + * Based on busybox code.
|
pascal@18894
|
377 + *
|
pascal@18894
|
378 + * Compute MD5 checksum of strings according to the
|
pascal@18894
|
379 + * definition of MD5 in RFC 1321 from April 1992.
|
pascal@18894
|
380 + *
|
pascal@18894
|
381 + * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
|
pascal@18894
|
382 + *
|
pascal@18894
|
383 + * Copyright (C) 1995-1999 Free Software Foundation, Inc.
|
pascal@18894
|
384 + * Copyright (C) 2001 Manuel Novoa III
|
pascal@18894
|
385 + * Copyright (C) 2003 Glenn L. McGrath
|
pascal@18894
|
386 + * Copyright (C) 2003 Erik Andersen
|
pascal@18894
|
387 + * Copyright (C) 2010 Denys Vlasenko
|
pascal@18894
|
388 + * Copyright (C) 2012 Pascal Bellard
|
pascal@18894
|
389 + *
|
pascal@18894
|
390 + * Licensed under GPLv2 or later
|
pascal@18894
|
391 + */
|
pascal@18894
|
392 +
|
pascal@18894
|
393 +#define ALIGN1
|
pascal@18894
|
394 +
|
pascal@18894
|
395 +static uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */
|
pascal@18894
|
396 +static uint64_t total64; /* must be directly before hash[] */
|
pascal@18894
|
397 +static uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */
|
pascal@18894
|
398 +
|
pascal@18894
|
399 +/* Emit a string of hex representation of bytes */
|
pascal@18894
|
400 +static char* bin2hex(char *p)
|
pascal@18894
|
401 +{
|
pascal@18894
|
402 + static const char bb_hexdigits_upcase[] ALIGN1 = "0123456789abcdef";
|
pascal@18894
|
403 + int count = 16;
|
pascal@18894
|
404 + const char *cp = (const char *) hash;
|
pascal@18894
|
405 + while (count) {
|
pascal@18894
|
406 + unsigned char c = *cp++;
|
pascal@18894
|
407 + /* put lowercase hex digits */
|
pascal@18894
|
408 + *p++ = bb_hexdigits_upcase[c >> 4];
|
pascal@18894
|
409 + *p++ = bb_hexdigits_upcase[c & 0xf];
|
pascal@18894
|
410 + count--;
|
pascal@18894
|
411 + }
|
pascal@18894
|
412 + return p;
|
pascal@18894
|
413 +}
|
pascal@18894
|
414 +
|
pascal@18894
|
415 +//#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
|
pascal@18894
|
416 +static uint32_t rotl32(uint32_t x, unsigned n)
|
pascal@18894
|
417 +{
|
pascal@18894
|
418 + return (x << n) | (x >> (32 - n));
|
pascal@18894
|
419 +}
|
pascal@18894
|
420 +
|
pascal@18894
|
421 +static void md5_process_block64(void);
|
pascal@18894
|
422 +
|
pascal@18894
|
423 +/* Feed data through a temporary buffer.
|
pascal@18894
|
424 + * The internal buffer remembers previous data until it has 64
|
pascal@18894
|
425 + * bytes worth to pass on.
|
pascal@18894
|
426 + */
|
pascal@18894
|
427 +static void common64_hash(const void *buffer, size_t len)
|
pascal@18894
|
428 +{
|
pascal@18894
|
429 + unsigned bufpos = total64 & 63;
|
pascal@18894
|
430 +
|
pascal@18894
|
431 + total64 += len;
|
pascal@18894
|
432 +
|
pascal@18894
|
433 + while (1) {
|
pascal@18894
|
434 + unsigned remaining = 64 - bufpos;
|
pascal@18894
|
435 + if (remaining > len)
|
pascal@18894
|
436 + remaining = len;
|
pascal@18894
|
437 + /* Copy data into aligned buffer */
|
pascal@18894
|
438 + memcpy(wbuffer + bufpos, buffer, remaining);
|
pascal@18894
|
439 + len -= remaining;
|
pascal@18894
|
440 + buffer = (const char *)buffer + remaining;
|
pascal@18894
|
441 + bufpos += remaining;
|
pascal@18894
|
442 + /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */
|
pascal@18894
|
443 + bufpos -= 64;
|
pascal@18894
|
444 + if (bufpos != 0)
|
pascal@18894
|
445 + break;
|
pascal@18894
|
446 + /* Buffer is filled up, process it */
|
pascal@18894
|
447 + md5_process_block64();
|
pascal@18894
|
448 + /*bufpos = 0; - already is */
|
pascal@18894
|
449 + }
|
pascal@18894
|
450 +}
|
pascal@18894
|
451 +
|
pascal@18894
|
452 +/* Process the remaining bytes in the buffer */
|
pascal@18894
|
453 +static void common64_end(void)
|
pascal@18894
|
454 +{
|
pascal@18894
|
455 + unsigned bufpos = total64 & 63;
|
pascal@18894
|
456 + /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
|
pascal@18894
|
457 + wbuffer[bufpos++] = 0x80;
|
pascal@18894
|
458 +
|
pascal@18894
|
459 + /* This loop iterates either once or twice, no more, no less */
|
pascal@18894
|
460 + while (1) {
|
pascal@18894
|
461 + unsigned remaining = 64 - bufpos;
|
pascal@18894
|
462 + memset(wbuffer + bufpos, 0, remaining);
|
pascal@18894
|
463 + /* Do we have enough space for the length count? */
|
pascal@18894
|
464 + if (remaining >= 8) {
|
pascal@18894
|
465 + /* Store the 64-bit counter of bits in the buffer */
|
pascal@18894
|
466 + uint64_t t = total64 << 3;
|
pascal@18894
|
467 + /* wbuffer is suitably aligned for this */
|
pascal@18894
|
468 + *(uint64_t *) (&wbuffer[64 - 8]) = t;
|
pascal@18894
|
469 + }
|
pascal@18894
|
470 + md5_process_block64();
|
pascal@18894
|
471 + if (remaining >= 8)
|
pascal@18894
|
472 + break;
|
pascal@18894
|
473 + bufpos = 0;
|
pascal@18894
|
474 + }
|
pascal@18894
|
475 +}
|
pascal@18894
|
476 +
|
pascal@18894
|
477 +/* These are the four functions used in the four steps of the MD5 algorithm
|
pascal@18894
|
478 + * and defined in the RFC 1321. The first function is a little bit optimized
|
pascal@18894
|
479 + * (as found in Colin Plumbs public domain implementation).
|
pascal@18894
|
480 + * #define FF(b, c, d) ((b & c) | (~b & d))
|
pascal@18894
|
481 + */
|
pascal@18894
|
482 +#undef FF
|
pascal@18894
|
483 +#undef FG
|
pascal@18894
|
484 +#undef FH
|
pascal@18894
|
485 +#undef FI
|
pascal@18894
|
486 +#define FF(b, c, d) (d ^ (b & (c ^ d)))
|
pascal@18894
|
487 +#define FG(b, c, d) FF(d, b, c)
|
pascal@18894
|
488 +#define FH(b, c, d) (b ^ c ^ d)
|
pascal@18894
|
489 +#define FI(b, c, d) (c ^ (b | ~d))
|
pascal@18894
|
490 +
|
pascal@18894
|
491 +/* Hash a single block, 64 bytes long and 4-byte aligned */
|
pascal@18894
|
492 +static void md5_process_block64(void)
|
pascal@18894
|
493 +{
|
pascal@18894
|
494 + /* Before we start, one word to the strange constants.
|
pascal@18894
|
495 + They are defined in RFC 1321 as
|
pascal@18894
|
496 + T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
|
pascal@18894
|
497 + */
|
pascal@18894
|
498 + static const uint32_t C_array[] = {
|
pascal@18894
|
499 + /* round 1 */
|
pascal@18894
|
500 + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
pascal@18894
|
501 + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
pascal@18894
|
502 + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
pascal@18894
|
503 + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
pascal@18894
|
504 + /* round 2 */
|
pascal@18894
|
505 + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
pascal@18894
|
506 + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
pascal@18894
|
507 + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
pascal@18894
|
508 + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
pascal@18894
|
509 + /* round 3 */
|
pascal@18894
|
510 + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
pascal@18894
|
511 + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
pascal@18894
|
512 + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
|
pascal@18894
|
513 + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
pascal@18894
|
514 + /* round 4 */
|
pascal@18894
|
515 + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
pascal@18894
|
516 + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
pascal@18894
|
517 + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
pascal@18894
|
518 + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
pascal@18894
|
519 + };
|
pascal@18894
|
520 + static const char P_array[] ALIGN1 = {
|
pascal@18894
|
521 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
|
pascal@18894
|
522 + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
|
pascal@18894
|
523 + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
|
pascal@18894
|
524 + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
|
pascal@18894
|
525 + };
|
pascal@18895
|
526 + uint32_t *words = (uint32_t *) wbuffer;
|
pascal@18894
|
527 + uint32_t A = hash[0];
|
pascal@18894
|
528 + uint32_t B = hash[1];
|
pascal@18894
|
529 + uint32_t C = hash[2];
|
pascal@18894
|
530 + uint32_t D = hash[3];
|
pascal@18894
|
531 +
|
pascal@18894
|
532 + static const char S_array[] ALIGN1 = {
|
pascal@18894
|
533 + 7, 12, 17, 22,
|
pascal@18894
|
534 + 5, 9, 14, 20,
|
pascal@18894
|
535 + 4, 11, 16, 23,
|
pascal@18894
|
536 + 6, 10, 15, 21
|
pascal@18894
|
537 + };
|
pascal@18894
|
538 + const uint32_t *pc;
|
pascal@18894
|
539 + const char *pp;
|
pascal@18894
|
540 + const char *ps;
|
pascal@18894
|
541 + int i;
|
pascal@18894
|
542 + uint32_t temp;
|
pascal@18894
|
543 +
|
pascal@18894
|
544 +
|
pascal@18894
|
545 + pc = C_array;
|
pascal@18894
|
546 + pp = P_array;
|
pascal@18894
|
547 + ps = S_array - 4;
|
pascal@18894
|
548 +
|
pascal@18894
|
549 + for (i = 0; i < 64; i++) {
|
pascal@18894
|
550 + if ((i & 0x0f) == 0)
|
pascal@18894
|
551 + ps += 4;
|
pascal@18894
|
552 + temp = A;
|
pascal@18894
|
553 + switch (i >> 4) {
|
pascal@18894
|
554 + case 0:
|
pascal@18894
|
555 + temp += FF(B, C, D);
|
pascal@18894
|
556 + break;
|
pascal@18894
|
557 + case 1:
|
pascal@18894
|
558 + temp += FG(B, C, D);
|
pascal@18894
|
559 + break;
|
pascal@18894
|
560 + case 2:
|
pascal@18894
|
561 + temp += FH(B, C, D);
|
pascal@18894
|
562 + break;
|
pascal@18894
|
563 + case 3:
|
pascal@18894
|
564 + temp += FI(B, C, D);
|
pascal@18894
|
565 + }
|
pascal@18894
|
566 + temp += words[(int) (*pp++)] + *pc++;
|
pascal@18894
|
567 + temp = rotl32(temp, ps[i & 3]);
|
pascal@18894
|
568 + temp += B;
|
pascal@18894
|
569 + A = D;
|
pascal@18894
|
570 + D = C;
|
pascal@18894
|
571 + C = B;
|
pascal@18894
|
572 + B = temp;
|
pascal@18894
|
573 + }
|
pascal@18894
|
574 + /* Add checksum to the starting values */
|
pascal@18894
|
575 + hash[0] += A;
|
pascal@18894
|
576 + hash[1] += B;
|
pascal@18894
|
577 + hash[2] += C;
|
pascal@18894
|
578 + hash[3] += D;
|
pascal@18894
|
579 +
|
pascal@18894
|
580 +}
|
pascal@18894
|
581 +#undef FF
|
pascal@18894
|
582 +#undef FG
|
pascal@18894
|
583 +#undef FH
|
pascal@18894
|
584 +#undef FI
|
pascal@18894
|
585 +
|
pascal@18894
|
586 +/* Initialize structure containing state of computation.
|
pascal@18894
|
587 + * (RFC 1321, 3.3: Step 3)
|
pascal@18894
|
588 + */
|
pascal@18894
|
589 +static void md5_begin(void)
|
pascal@18894
|
590 +{
|
pascal@18894
|
591 + hash[0] = 0x67452301;
|
pascal@18894
|
592 + hash[1] = 0xefcdab89;
|
pascal@18894
|
593 + hash[2] = 0x98badcfe;
|
pascal@18894
|
594 + hash[3] = 0x10325476;
|
pascal@18894
|
595 + total64 = 0;
|
pascal@18894
|
596 +}
|
pascal@18894
|
597 +
|
pascal@18894
|
598 +/* Used also for sha1 and sha256 */
|
pascal@18894
|
599 +#define md5_hash common64_hash
|
pascal@18894
|
600 +
|
pascal@18894
|
601 +/* Process the remaining bytes in the buffer and put result from CTX
|
pascal@18894
|
602 + * in first 16 bytes following RESBUF. The result is always in little
|
pascal@18894
|
603 + * endian byte order, so that a byte-wise output yields to the wanted
|
pascal@18894
|
604 + * ASCII representation of the message digest.
|
pascal@18894
|
605 + */
|
pascal@18894
|
606 +#define md5_end common64_end
|
pascal@18894
|
607 +
|
pascal@18894
|
608 +typedef struct { char hash[16]; } md5hash;
|
pascal@18894
|
609 +
|
pascal@18894
|
610 +static md5hash md5sum(uint8_t *buffer, int len)
|
pascal@18894
|
611 +{
|
pascal@18894
|
612 + md5hash val;
|
pascal@18894
|
613 +
|
pascal@18894
|
614 + md5_begin();
|
pascal@18894
|
615 + md5_hash(buffer, len);
|
pascal@18894
|
616 + md5_end();
|
pascal@18894
|
617 + memcpy(&val, hash, 16);
|
pascal@18894
|
618 +
|
pascal@18894
|
619 + return val;
|
pascal@18894
|
620 +}
|
pascal@10935
|
621 --- create_compressed_fs.c
|
pascal@10935
|
622 +++ create_compressed_fs.c
|
pascal@19560
|
623 @@ -0,0 +1,224 @@
|
pascal@12214
|
624 +#ifdef FIND_BEST_COMPRESSION
|
pascal@12214
|
625 +#include <compress.h>
|
pascal@12214
|
626 +extern "C" {
|
pascal@12214
|
627 +#include <stdlib.h>
|
pascal@12214
|
628 +#include <string.h>
|
pascal@12214
|
629 +
|
pascal@19560
|
630 +#define ZMAX 12 /* 12 compression levels with libdeflate, not 9 */
|
pascal@19408
|
631 +static shrink_t level;
|
pascal@19408
|
632 +static int pass, iter;
|
pascal@12214
|
633 +static int best_compress(unsigned char *compressed,
|
pascal@12214
|
634 + unsigned long *compressed_len,
|
pascal@12214
|
635 + unsigned char *uncompressed,
|
pascal@12214
|
636 + unsigned long uncompressed_len)
|
pascal@12214
|
637 +{
|
pascal@12214
|
638 + int i, j, err;
|
pascal@12214
|
639 + unsigned char *buf[2];
|
pascal@12214
|
640 + unsigned len;
|
pascal@12214
|
641 + unsigned long llen, best = *compressed_len * 2;
|
pascal@12214
|
642 + static unsigned char *buffer;
|
pascal@12214
|
643 + static unsigned long buffersz;
|
pascal@12214
|
644 +
|
pascal@12214
|
645 + if (buffersz < *compressed_len) {
|
pascal@12214
|
646 + if (buffer) free(buffer);
|
pascal@12214
|
647 + buffer = (unsigned char *) malloc(buffersz = *compressed_len);
|
pascal@12214
|
648 + if (!buffer) return Z_MEM_ERROR;
|
pascal@12214
|
649 + }
|
pascal@12214
|
650 + buf[0] = compressed;
|
pascal@12214
|
651 + buf[1] = buffer;
|
pascal@19560
|
652 + for (i = j = 0; i <= ZMAX+2 && (pass == 0 || i < pass); i++) {
|
pascal@12214
|
653 + llen = len = *compressed_len;
|
pascal@19560
|
654 + if (i >= ZMAX+1) {
|
pascal@19560
|
655 + level.level = (i == ZMAX+1) ? shrink_extra : shrink_insane;
|
pascal@19408
|
656 + err = (compress_zlib(level, buf[j],
|
pascal@12214
|
657 + len, uncompressed,
|
pascal@12214
|
658 + uncompressed_len)) ? Z_OK : Z_DATA_ERROR;
|
pascal@19408
|
659 + } else {
|
pascal@12214
|
660 + err = compress2(buf[j], &llen, uncompressed,
|
pascal@12214
|
661 + uncompressed_len, i);
|
pascal@12214
|
662 + len = llen;
|
pascal@12214
|
663 + }
|
pascal@12214
|
664 + if (err != Z_OK) return err;
|
pascal@12214
|
665 + if (len < best) {
|
pascal@12214
|
666 + best = len;
|
pascal@12214
|
667 + j = 1 - j;
|
pascal@12214
|
668 + }
|
pascal@12214
|
669 + }
|
pascal@12214
|
670 + *compressed_len = best;
|
pascal@12214
|
671 + if (j == 0)
|
pascal@12214
|
672 + memcpy(compressed, buffer, best);
|
pascal@12214
|
673 + return err;
|
pascal@12214
|
674 +}
|
pascal@12214
|
675 +#define compress2(a,b,c,d,e) best_compress(a,b,c,d)
|
pascal@12214
|
676 +#endif
|
pascal@12214
|
677 +
|
pascal@18894
|
678 +#include <signal.h>
|
pascal@18894
|
679 +
|
pascal@10935
|
680 +/* Creates a compressed file */
|
pascal@10935
|
681 +#include "common_header.h"
|
pascal@10935
|
682 +
|
pascal@12214
|
683 +#define CLOOP_PREAMBLE "#!/bin/sh\n" "#V3.0 Format\n" "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"
|
pascal@10935
|
684 +#define CHUNK 65536
|
pascal@10935
|
685 +#define DEFAULT_BLOCKSIZE 65536
|
pascal@10935
|
686 +
|
pascal@12214
|
687 +static void quit(const char *s)
|
pascal@10935
|
688 +{
|
pascal@10935
|
689 + fprintf(stderr, "%s\n", s);
|
pascal@10935
|
690 + exit(1);
|
pascal@10935
|
691 +}
|
pascal@10935
|
692 +
|
pascal@10935
|
693 +static int readblock(unsigned char *buffer, int n)
|
pascal@10935
|
694 +{
|
pascal@10935
|
695 + int i;
|
pascal@10935
|
696 +
|
pascal@10935
|
697 + memset(buffer, 0, n);
|
pascal@10935
|
698 + for (i = 0 ; i < n;) {
|
pascal@10935
|
699 + int j = read(STDIN_FILENO, buffer + i, n - i);
|
pascal@10935
|
700 + if (j < 0 && errno == EINTR) continue;
|
pascal@10935
|
701 + if (j <= 0) break;
|
pascal@10935
|
702 + i += j;
|
pascal@10935
|
703 + }
|
pascal@10935
|
704 + return i;
|
pascal@10935
|
705 +}
|
pascal@10935
|
706 +
|
pascal@18894
|
707 +#ifdef FIND_BEST_COMPRESSION
|
pascal@18894
|
708 +#include "md5sum.c"
|
pascal@18894
|
709 +#endif
|
pascal@18894
|
710 +
|
pascal@18894
|
711 +static unsigned n;
|
pascal@18894
|
712 +static unsigned long lastlen, pos, *block_index;
|
pascal@18894
|
713 +static unsigned char *compressed;
|
pascal@18894
|
714 +static unsigned long block_size = 0;
|
pascal@18894
|
715 +static void flush_index(int sig)
|
pascal@18894
|
716 +{
|
pascal@18894
|
717 + static char padding[512];
|
pascal@18894
|
718 + struct cloop_tail tail;
|
pascal@18894
|
719 + unsigned long len;
|
pascal@18894
|
720 +
|
pascal@18894
|
721 + fprintf(stderr, "Write index for %lu blocks\n", n);
|
pascal@18894
|
722 + if (block_size >= 0x1000000) lastlen = 0;
|
pascal@18894
|
723 + tail.index_size = ntohl(sizeof(*block_index) + 256*(lastlen % 0xFFffFF));
|
pascal@18894
|
724 + tail.num_blocks = ntohl(n);
|
pascal@18894
|
725 + n *= sizeof(*block_index);
|
pascal@18894
|
726 + len = n + n/1000 + 12;
|
pascal@18894
|
727 + compressed = (unsigned char *) realloc(compressed, len);
|
pascal@18894
|
728 + if (!compressed || compress2(compressed, &len, (unsigned char *) block_index,
|
pascal@18894
|
729 + n, Z_BEST_SPEED) != Z_OK)
|
pascal@18894
|
730 + quit("Index compression failed");
|
pascal@18894
|
731 + tail.table_size = ntohl(len);
|
pascal@18894
|
732 + pos += len + sizeof(tail);
|
pascal@18894
|
733 + n = pos & 511;
|
pascal@18894
|
734 + if (n) write(STDOUT_FILENO, padding, 512 - n);
|
pascal@18894
|
735 + write(STDOUT_FILENO, compressed, len);
|
pascal@18894
|
736 + write(STDOUT_FILENO, &tail, sizeof(tail));
|
pascal@18894
|
737 + exit(sig != 0);
|
pascal@18894
|
738 +}
|
pascal@18894
|
739 +
|
pascal@10935
|
740 +int main(int argc, char *argv[])
|
pascal@10935
|
741 +{
|
pascal@10935
|
742 + struct cloop_head head;
|
pascal@18894
|
743 + unsigned char *uncompressed;
|
pascal@18894
|
744 + unsigned long len;
|
pascal@18894
|
745 + unsigned indexmax, zlenmax;
|
pascal@18894
|
746 +#ifdef FIND_BEST_COMPRESSION
|
pascal@18894
|
747 + unsigned i, j, hashmax;
|
pascal@18894
|
748 + md5hash *hash;
|
pascal@18894
|
749 +#endif
|
pascal@10935
|
750 +
|
pascal@19408
|
751 +#ifdef FIND_BEST_COMPRESSION
|
pascal@19408
|
752 + while (argc > 1) {
|
pascal@19408
|
753 + if (argv[1][0] == '-') {
|
pascal@19408
|
754 + int *p = &pass;
|
pascal@19408
|
755 + switch (argv[1][1]) {
|
pascal@19408
|
756 + case 'i' : p = &iter;
|
pascal@19408
|
757 + case 'n' : *p = atoi(argv[2]);
|
pascal@19408
|
758 + argc -= 2;
|
pascal@19408
|
759 + argv += 2;
|
pascal@19408
|
760 + continue;
|
pascal@19408
|
761 + }
|
pascal@19408
|
762 + }
|
pascal@19408
|
763 + argc--;
|
pascal@19408
|
764 + if (argv[1][0] < '0' || argv[1][0] > '9')
|
pascal@19408
|
765 + quit("Usage : create_compressed_fs [-n <pass>][ -i <iter>] [block size] < input > output");
|
pascal@19408
|
766 +#else
|
pascal@10935
|
767 + if (argc > 1) {
|
pascal@10935
|
768 + if (argv[1][0] < '0' || argv[1][0] > '9')
|
pascal@10935
|
769 + quit("Usage : create_compressed_fs [block size] < input > output");
|
pascal@19408
|
770 +#endif
|
pascal@10935
|
771 + block_size = atoi(argv[1]);
|
pascal@10935
|
772 + }
|
pascal@10935
|
773 + if (block_size < 4096)
|
pascal@10935
|
774 + block_size = DEFAULT_BLOCKSIZE;
|
pascal@10935
|
775 + fprintf(stderr, "Block size is %lu\n", block_size);
|
pascal@10935
|
776 + zlenmax = block_size + block_size/1000 + 12;
|
pascal@10935
|
777 +
|
pascal@10935
|
778 + memset(&head, 0, sizeof(head));
|
pascal@10935
|
779 + strcpy(head.preamble, CLOOP_PREAMBLE);
|
pascal@10935
|
780 + head.num_blocks = -1;
|
pascal@10935
|
781 + head.block_size = htonl(block_size);
|
pascal@10935
|
782 + write(STDOUT_FILENO, &head, sizeof(head));
|
pascal@12214
|
783 + pos = sizeof(head);
|
pascal@10935
|
784 +
|
pascal@12214
|
785 + compressed = (unsigned char *) malloc(zlenmax);
|
pascal@12214
|
786 + uncompressed = (unsigned char *) malloc(block_size);
|
pascal@18894
|
787 + block_index = (unsigned long *) malloc(indexmax = CHUNK);
|
pascal@18894
|
788 +#ifdef FIND_BEST_COMPRESSION
|
pascal@18894
|
789 + hash = (md5hash *) malloc(hashmax = CHUNK);
|
pascal@18894
|
790 + if (!compressed || !uncompressed || !block_index || !hash)
|
pascal@18894
|
791 +#else
|
pascal@18894
|
792 + if (!compressed || !uncompressed || !block_index)
|
pascal@18894
|
793 +#endif
|
pascal@10935
|
794 + quit("Malloc failed");
|
pascal@10935
|
795 +
|
pascal@18894
|
796 + signal(SIGINT,flush_index);
|
pascal@18894
|
797 + signal(SIGQUIT,flush_index);
|
pascal@18894
|
798 + signal(SIGTERM,flush_index);
|
pascal@18894
|
799 +
|
pascal@17996
|
800 + for (n = 0; (len = readblock(uncompressed, block_size)) != 0; n++) {
|
pascal@17997
|
801 + lastlen = len;
|
pascal@18894
|
802 + if (n * sizeof(*block_index) >= indexmax) {
|
pascal@18894
|
803 + block_index = (unsigned long *) realloc(block_index,
|
pascal@12214
|
804 + indexmax += CHUNK);
|
pascal@18894
|
805 + if (!block_index)
|
pascal@10935
|
806 + quit("Realloc");
|
pascal@10935
|
807 + }
|
pascal@18894
|
808 +#ifdef FIND_BEST_COMPRESSION
|
pascal@18894
|
809 + if (n * sizeof(*hash) >= hashmax) {
|
pascal@18894
|
810 + hash = (md5hash *) realloc(hash, hashmax += CHUNK);
|
pascal@18895
|
811 + if (!hash)
|
pascal@18894
|
812 + quit("Realloc hash");
|
pascal@18894
|
813 + }
|
pascal@18894
|
814 + hash[n] = md5sum(uncompressed, len);
|
pascal@18894
|
815 + j = 0x7FFFFFFF;
|
pascal@18894
|
816 + if (n < j)
|
pascal@18894
|
817 + j = n;
|
pascal@18894
|
818 + for (i = 0; i < j; i++) {
|
pascal@18894
|
819 + if (* (uint32_t *) &hash[i] == * (uint32_t *) &hash[n]
|
pascal@18894
|
820 + && !memcmp(&hash[i],&hash[n],sizeof(*hash)))
|
pascal@18894
|
821 + break;
|
pascal@18894
|
822 + }
|
pascal@18894
|
823 + if (i != j) {
|
pascal@18894
|
824 + block_index[n] = ntohl(0x80000000 | i);
|
pascal@18894
|
825 + fprintf(stderr, "Block %u length %lu => duplicate %lu\n",
|
pascal@18894
|
826 + n, block_size, i);
|
pascal@18894
|
827 + }
|
pascal@18894
|
828 + else
|
pascal@18894
|
829 +#endif
|
pascal@18894
|
830 + {
|
pascal@18894
|
831 + len = zlenmax;
|
pascal@18894
|
832 + if (compress2(compressed, &len, uncompressed, lastlen,
|
pascal@18894
|
833 + Z_BEST_SPEED) != Z_OK)
|
pascal@18894
|
834 + quit("Compression failed");
|
pascal@18894
|
835 + fprintf(stderr, "Block %u length %lu => %lu\n",
|
pascal@18894
|
836 + n, block_size, len);
|
pascal@18894
|
837 + write(STDOUT_FILENO, compressed, len);
|
pascal@18894
|
838 + pos += len;
|
pascal@18894
|
839 + block_index[n] = ntohl(len);
|
pascal@18894
|
840 + }
|
pascal@10935
|
841 + }
|
pascal@18894
|
842 + flush_index(0);
|
pascal@10935
|
843 + return 0;
|
pascal@10935
|
844 +}
|
pascal@12214
|
845 +#ifdef FIND_BEST_COMPRESSION
|
pascal@12214
|
846 +}
|
pascal@12214
|
847 +#endif
|
pascal@10938
|
848 --- fusecloop.c
|
pascal@10938
|
849 +++ fusecloop.c
|
pascal@10938
|
850 @@ -65,7 +65,7 @@
|
pascal@10938
|
851
|
pascal@10938
|
852 memcpy(stbuf,&stb,sizeof stb);
|
pascal@10938
|
853 stbuf->st_mode&=~0222;
|
pascal@10938
|
854 - stbuf->st_size = cd.blocksize * cd.numblocks;
|
pascal@10938
|
855 + stbuf->st_size = (loff_t) cd.blocksize * cd.numblocks;
|
pascal@10938
|
856 /*
|
pascal@10938
|
857 stbuf->st_mode = S_IFREG | 0444;
|
pascal@10938
|
858 stbuf->st_nlink = 1;
|