rev |
line source |
pascal@17000
|
1 --- cloop.h
|
pascal@17000
|
2 +++ cloop.h
|
pascal@18828
|
3 @@ -20,6 +20,80 @@
|
pascal@17000
|
4 /* data_index (num_blocks 64bit pointers, network order)... */
|
pascal@17000
|
5 /* compressed data (gzip block compressed format)... */
|
pascal@17000
|
6
|
pascal@17000
|
7 +struct cloop_tail
|
pascal@17000
|
8 +{
|
pascal@17000
|
9 + u_int32_t table_size;
|
pascal@17000
|
10 + u_int32_t index_size;
|
pascal@17000
|
11 + u_int32_t num_blocks;
|
pascal@17000
|
12 +};
|
pascal@17000
|
13 +
|
pascal@17000
|
14 +struct block_info
|
pascal@17000
|
15 +{
|
pascal@17000
|
16 + loff_t offset; /* 64-bit offsets of compressed block */
|
pascal@17000
|
17 + u_int32_t size; /* 32-bit compressed block size */
|
pascal@17000
|
18 + u_int32_t optidx; /* 32-bit index number */
|
pascal@17000
|
19 +};
|
pascal@17000
|
20 +
|
pascal@17000
|
21 +static inline char *build_index(struct block_info *offsets, unsigned long n)
|
pascal@17000
|
22 +{
|
pascal@17000
|
23 + u_int32_t *ofs32 = (u_int32_t *) offsets;
|
pascal@17000
|
24 + loff_t *ofs64 = (loff_t *) offsets;
|
pascal@17000
|
25 +
|
pascal@17000
|
26 + if (ofs32[0] == 0) {
|
pascal@17000
|
27 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
|
pascal@17000
|
28 + while (n--) {
|
pascal@17000
|
29 + offsets[n].offset = __be64_to_cpu(offsets[n].offset);
|
pascal@17000
|
30 + offsets[n].size = ntohl(offsets[n].size);
|
pascal@17000
|
31 + }
|
pascal@17000
|
32 + return (char *) "128BE accelerated knoppix 1.0";
|
pascal@17000
|
33 + }
|
pascal@17000
|
34 + else { /* V2.0 */
|
pascal@17361
|
35 + loff_t last = __be64_to_cpu(ofs64[n - 1]);
|
pascal@17000
|
36 + while (n--) {
|
pascal@17000
|
37 + offsets[n].size = last -
|
pascal@17000
|
38 + (offsets[n].offset = __be64_to_cpu(ofs64[n]));
|
pascal@17000
|
39 + last = offsets[n].offset;
|
pascal@17000
|
40 + }
|
pascal@17000
|
41 + return (char *) "64BE v2.0";
|
pascal@17000
|
42 + }
|
pascal@17000
|
43 + }
|
pascal@17000
|
44 + else if (ofs32[1] == 0) { /* V1.0 */
|
pascal@17361
|
45 + loff_t last = __le64_to_cpu(ofs64[n - 1]);
|
pascal@17000
|
46 + while (n--) {
|
pascal@17000
|
47 + offsets[n].size = last -
|
pascal@17000
|
48 + (offsets[n].offset = __le64_to_cpu(ofs64[n]));
|
pascal@17000
|
49 + last = offsets[n].offset;
|
pascal@17000
|
50 + }
|
pascal@17000
|
51 + return (char *) "64LE v1.0";
|
pascal@17000
|
52 + }
|
pascal@17000
|
53 + else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
|
pascal@17361
|
54 + loff_t last = ntohl(ofs32[n - 1]);
|
pascal@17000
|
55 + while (n--) {
|
pascal@17000
|
56 + offsets[n].size = last -
|
pascal@17000
|
57 + (offsets[n].offset = ntohl(ofs32[n]));
|
pascal@17000
|
58 + last = offsets[n].offset;
|
pascal@17000
|
59 + }
|
pascal@17000
|
60 + return (char *) "32BE v0.68";
|
pascal@17000
|
61 + }
|
pascal@17000
|
62 + else { /* V3.0 */
|
pascal@17169
|
63 + unsigned long i;
|
pascal@17168
|
64 + loff_t j;
|
pascal@17000
|
65 +
|
pascal@17169
|
66 + for (i = n; i-- != 0; )
|
pascal@17000
|
67 + offsets[i].size = ntohl(ofs32[i]);
|
pascal@17000
|
68 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
|
pascal@17000
|
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@17000
|
76 + }
|
pascal@17000
|
77 + return (char *) "32BE v3.0";
|
pascal@17000
|
78 + }
|
pascal@17000
|
79 +}
|
pascal@17000
|
80 +
|
pascal@17000
|
81 /* Cloop suspend IOCTL */
|
pascal@17000
|
82 #define CLOOP_SUSPEND 0x4C07
|
pascal@17000
|
83
|
pascal@17000
|
84 --- cloop.c
|
pascal@17000
|
85 +++ cloop.c
|
pascal@17000
|
86 @@ -5,11 +5,18 @@
|
pascal@17000
|
87 * A cloop file looks like this:
|
pascal@17000
|
88 * [32-bit uncompressed block size: network order]
|
pascal@17000
|
89 * [32-bit number of blocks (n_blocks): network order]
|
pascal@17000
|
90 - * [64-bit file offsets of start of blocks: network order]
|
pascal@17000
|
91 + * [for version < 3]
|
pascal@17000
|
92 + * [32-bit, 64-bit or 128-bit file offsets of start of blocks]
|
pascal@17000
|
93 * ...
|
pascal@17000
|
94 * (n_blocks + 1).
|
pascal@17000
|
95 * n_blocks consisting of:
|
pascal@17000
|
96 * [compressed block]
|
pascal@17000
|
97 + * ...
|
pascal@17000
|
98 + * [for version >= 3]
|
pascal@17000
|
99 + * [compressed list of 32-bit block sizes]
|
pascal@17000
|
100 + * [32-bit compressed index size: network order]
|
pascal@17000
|
101 + * [32-bit index size = 4: network order]
|
pascal@17000
|
102 + * [32-bit number of blocks (n_blocks): network order]
|
pascal@17000
|
103 *
|
pascal@17000
|
104 * Every version greatly inspired by code seen in loop.c
|
pascal@17000
|
105 * by Theodore Ts'o, 3/29/93.
|
pascal@17000
|
106 @@ -115,7 +122,7 @@
|
pascal@17000
|
107 struct cloop_head head;
|
pascal@17000
|
108
|
pascal@17000
|
109 /* An array of offsets of compressed blocks within the file */
|
pascal@17000
|
110 - loff_t *offsets;
|
pascal@17000
|
111 + struct block_info *offsets;
|
pascal@17000
|
112
|
pascal@17000
|
113 /* We buffer some uncompressed blocks for performance */
|
pascal@17000
|
114 int buffered_blocknum[BUFFERED_BLOCKS];
|
pascal@17000
|
115 @@ -256,11 +263,11 @@
|
pascal@17000
|
116 return i;
|
pascal@17000
|
117 }
|
pascal@17000
|
118
|
pascal@17000
|
119 - buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]);
|
pascal@17000
|
120 + buf_length = clo->offsets[blocknum].size;
|
pascal@17000
|
121
|
pascal@17000
|
122 /* Load one compressed block from the file. */
|
pascal@17000
|
123 cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
|
pascal@17000
|
124 - be64_to_cpu(clo->offsets[blocknum]), buf_length);
|
pascal@17000
|
125 + clo->offsets[blocknum].offset, buf_length);
|
pascal@17000
|
126
|
pascal@17000
|
127 buflen = ntohl(clo->head.block_size);
|
pascal@17000
|
128
|
pascal@17000
|
129 @@ -275,9 +282,9 @@
|
pascal@17000
|
130 if (ret != 0)
|
pascal@17000
|
131 {
|
pascal@17000
|
132 printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u "
|
pascal@17000
|
133 - "%Lu-%Lu\n", cloop_name, ret, blocknum,
|
pascal@17000
|
134 + "%Lu:%u\n", cloop_name, ret, blocknum,
|
pascal@17000
|
135 ntohl(clo->head.block_size), buflen, buf_length, buf_done,
|
pascal@17000
|
136 - be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1]));
|
pascal@17000
|
137 + clo->offsets[blocknum].offset, clo->offsets[blocknum].size);
|
pascal@17000
|
138 clo->buffered_blocknum[clo->current_bufnum] = -1;
|
pascal@17000
|
139 return -1;
|
pascal@17000
|
140 }
|
pascal@17000
|
141 @@ -489,30 +496,73 @@
|
pascal@17000
|
142 cloop_name, ntohl(clo->head.block_size));
|
pascal@17000
|
143 error=-EBADF; goto error_release;
|
pascal@17000
|
144 }
|
pascal@17000
|
145 - if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1')
|
pascal@17000
|
146 - {
|
pascal@17000
|
147 - printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, "
|
pascal@17000
|
148 - "please use an older version of %s for this file.\n",
|
pascal@17000
|
149 - cloop_name, cloop_name);
|
pascal@17000
|
150 - error=-EBADF; goto error_release;
|
pascal@17000
|
151 - }
|
pascal@17000
|
152 - if (clo->head.preamble[0x0C]<'2')
|
pascal@17000
|
153 - {
|
pascal@17000
|
154 - printk(KERN_ERR "%s: Cannot read old architecture-dependent "
|
pascal@17000
|
155 - "(format <= 1.0) images, please use an older "
|
pascal@17000
|
156 - "version of %s for this file.\n",
|
pascal@17000
|
157 - cloop_name, cloop_name);
|
pascal@17000
|
158 - error=-EBADF; goto error_release;
|
pascal@17000
|
159 - }
|
pascal@17000
|
160 - total_offsets=ntohl(clo->head.num_blocks)+1;
|
pascal@17000
|
161 - if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)*
|
pascal@17000
|
162 + total_offsets=ntohl(clo->head.num_blocks);
|
pascal@17000
|
163 + if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)*
|
pascal@17000
|
164 total_offsets > inode->i_size))
|
pascal@17000
|
165 {
|
pascal@17000
|
166 printk(KERN_ERR "%s: file too small for %u blocks\n",
|
pascal@17000
|
167 cloop_name, ntohl(clo->head.num_blocks));
|
pascal@17000
|
168 error=-EBADF; goto error_release;
|
pascal@17000
|
169 }
|
pascal@17000
|
170 - clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets);
|
pascal@17000
|
171 + if (total_offsets + 1 == 0) /* Version >= 3.0 */
|
pascal@17000
|
172 + {
|
pascal@17000
|
173 + struct cloop_tail tail;
|
pascal@17000
|
174 + if(isblkdev)
|
pascal@17000
|
175 + {
|
pascal@17000
|
176 + /* No end of file: can't find index */
|
pascal@17000
|
177 + printk(KERN_ERR "%s: no V3 support for block device\n",
|
pascal@17000
|
178 + cloop_name);
|
pascal@17000
|
179 + error=-EBADF; goto error_release;
|
pascal@17000
|
180 + }
|
pascal@17000
|
181 + bytes_read = cloop_read_from_file(clo, file, (void *) &tail,
|
pascal@17000
|
182 + inode->i_size - sizeof(struct cloop_tail),
|
pascal@17000
|
183 + sizeof(struct cloop_tail));
|
pascal@17000
|
184 + if(bytes_read == sizeof(struct cloop_tail))
|
pascal@17000
|
185 + {
|
pascal@17000
|
186 + unsigned long len, zlen;
|
pascal@17000
|
187 + void *zbuf;
|
pascal@17000
|
188 + clo->head.num_blocks = tail.num_blocks;
|
pascal@17000
|
189 + total_offsets = ntohl(clo->head.num_blocks);
|
pascal@17000
|
190 + clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets);
|
pascal@17000
|
191 + if (!clo->offsets)
|
pascal@17000
|
192 + {
|
pascal@17000
|
193 + printk(KERN_ERR "%s: can't alloc index\n",
|
pascal@17000
|
194 + cloop_name);
|
pascal@17000
|
195 + error=-EBADF; goto error_release;
|
pascal@17000
|
196 + }
|
pascal@17000
|
197 + zbuf = &clo->offsets[total_offsets/2];
|
pascal@17000
|
198 + zlen = ntohl(tail.table_size);
|
pascal@17000
|
199 + len = ntohl(tail.index_size) * total_offsets;
|
pascal@17000
|
200 + bytes_read = cloop_read_from_file(clo, file, zbuf,
|
pascal@17000
|
201 + inode->i_size - zlen - sizeof(struct cloop_tail),
|
pascal@17000
|
202 + zlen);
|
pascal@17000
|
203 + if (bytes_read != zlen)
|
pascal@17000
|
204 + {
|
pascal@17000
|
205 + printk(KERN_ERR "%s: can't read index\n",
|
pascal@17000
|
206 + cloop_name);
|
pascal@17000
|
207 + error=-EBADF; goto error_release;
|
pascal@17000
|
208 + }
|
pascal@17000
|
209 + clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize());
|
pascal@17000
|
210 + if(!clo->zstream.workspace)
|
pascal@17000
|
211 + {
|
pascal@17000
|
212 + printk(KERN_ERR "%s: can't alloc index workspace\n",
|
pascal@17000
|
213 + cloop_name);
|
pascal@17000
|
214 + error=-EBADF; goto error_release;
|
pascal@17000
|
215 + }
|
pascal@17000
|
216 + zlib_inflateInit(&clo->zstream);
|
pascal@17000
|
217 + uncompress(clo, (void *) clo->offsets, &len, zbuf, zlen);
|
pascal@17000
|
218 + cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize());
|
pascal@17000
|
219 + clo->zstream.workspace = NULL;
|
pascal@17000
|
220 + break;
|
pascal@17000
|
221 + }
|
pascal@17000
|
222 + else
|
pascal@17000
|
223 + {
|
pascal@17000
|
224 + printk(KERN_ERR "%s: can't find index\n",
|
pascal@17000
|
225 + cloop_name);
|
pascal@17000
|
226 + error=-EBADF; goto error_release;
|
pascal@17000
|
227 + }
|
pascal@17000
|
228 + }
|
pascal@17000
|
229 + clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets);
|
pascal@17000
|
230 if (!clo->offsets)
|
pascal@17000
|
231 {
|
pascal@17000
|
232 printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
|
pascal@17365
|
233 @@ -521,19 +571,22 @@
|
pascal@17000
|
234 }
|
pascal@17000
|
235 num_readable = MIN(total_offsets - offsets_read,
|
pascal@17000
|
236 (clo->underlying_blksize - offset)
|
pascal@17000
|
237 - / sizeof(loff_t));
|
pascal@17000
|
238 - memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t));
|
pascal@17000
|
239 + / sizeof(struct block_info));
|
pascal@17000
|
240 + memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(struct block_info));
|
pascal@17000
|
241 offsets_read += num_readable;
|
pascal@17000
|
242 }
|
pascal@17000
|
243 { /* Search for largest block rather than estimate. KK. */
|
pascal@17000
|
244 int i;
|
pascal@17000
|
245 - for(i=0;i<total_offsets-1;i++)
|
pascal@17000
|
246 + char *version = build_index(clo->offsets, ntohl(clo->head.num_blocks));
|
pascal@17361
|
247 + for(i=0,clo->largest_block=0;i<total_offsets;i++)
|
pascal@17000
|
248 {
|
pascal@17000
|
249 - loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]);
|
pascal@17000
|
250 - clo->largest_block=MAX(clo->largest_block,d);
|
pascal@17000
|
251 + clo->largest_block=MAX(clo->largest_block,clo->offsets[i].size);
|
pascal@17000
|
252 }
|
pascal@17000
|
253 - printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n",
|
pascal@17000
|
254 - cloop_name, filename, ntohl(clo->head.num_blocks),
|
pascal@17365
|
255 + i = ntohl(clo->head.block_size);
|
pascal@17365
|
256 + i += i/1000 + 12 + 4; /* max gzip block size */
|
pascal@17365
|
257 + if (clo->largest_block > i) clo->largest_block = i; /* broken index ? */
|
pascal@17000
|
258 + printk(KERN_INFO "%s: %s: %s, %u blocks, %u bytes/block, largest block is %lu bytes.\n",
|
pascal@17000
|
259 + cloop_name, filename, version, ntohl(clo->head.num_blocks),
|
pascal@17000
|
260 ntohl(clo->head.block_size), clo->largest_block);
|
pascal@17000
|
261 }
|
pascal@17000
|
262 /* Combo kmalloc used too large chunks (>130000). */
|
pascal@17365
|
263 @@ -565,16 +618,6 @@
|
pascal@17000
|
264 error=-ENOMEM; goto error_release_free_all;
|
pascal@17000
|
265 }
|
pascal@17000
|
266 zlib_inflateInit(&clo->zstream);
|
pascal@17000
|
267 - if(!isblkdev &&
|
pascal@17000
|
268 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size)
|
pascal@17000
|
269 - {
|
pascal@17000
|
270 - printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n",
|
pascal@17000
|
271 - cloop_name,
|
pascal@17000
|
272 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]),
|
pascal@17000
|
273 - inode->i_size);
|
pascal@17000
|
274 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL;
|
pascal@17000
|
275 - goto error_release_free_all;
|
pascal@17000
|
276 - }
|
pascal@17000
|
277 {
|
pascal@17000
|
278 int i;
|
pascal@17000
|
279 for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1;
|
pascal@17365
|
280 @@ -653,7 +696,7 @@
|
pascal@17000
|
281 }
|
pascal@17000
|
282 }
|
pascal@17000
|
283 error_release_free:
|
pascal@17000
|
284 - cloop_free(clo->offsets, sizeof(loff_t) * total_offsets);
|
pascal@17000
|
285 + cloop_free(clo->offsets, sizeof(struct block_info) * total_offsets);
|
pascal@17000
|
286 clo->offsets=NULL;
|
pascal@17000
|
287 error_release:
|
pascal@17000
|
288 if(bbuf) cloop_free(bbuf, clo->underlying_blksize);
|