wok view linux-cloop/stuff/cloop.u @ rev 17157

syslinux: fix rockridge (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Sep 15 23:31:45 2014 +0200 (2014-09-15)
parents
children ade6b9da6804
line source
1 --- cloop.h
2 +++ cloop.h
3 @@ -20,6 +20,74 @@
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 + int i, j;
64 +
65 + for (i = n; i-- > 0; )
66 + offsets[i].size = ntohl(ofs32[i]);
67 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
68 + offsets[i].offset = j;
69 + j += offsets[i].size;
70 + }
71 + return (char *) "32BE v3.0";
72 + }
73 +}
74 +
75 /* Cloop suspend IOCTL */
76 #define CLOOP_SUSPEND 0x4C07
78 --- cloop.c
79 +++ cloop.c
80 @@ -5,11 +5,18 @@
81 * A cloop file looks like this:
82 * [32-bit uncompressed block size: network order]
83 * [32-bit number of blocks (n_blocks): network order]
84 - * [64-bit file offsets of start of blocks: network order]
85 + * [for version < 3]
86 + * [32-bit, 64-bit or 128-bit file offsets of start of blocks]
87 * ...
88 * (n_blocks + 1).
89 * n_blocks consisting of:
90 * [compressed block]
91 + * ...
92 + * [for version >= 3]
93 + * [compressed list of 32-bit block sizes]
94 + * [32-bit compressed index size: network order]
95 + * [32-bit index size = 4: network order]
96 + * [32-bit number of blocks (n_blocks): network order]
97 *
98 * Every version greatly inspired by code seen in loop.c
99 * by Theodore Ts'o, 3/29/93.
100 @@ -115,7 +122,7 @@
101 struct cloop_head head;
103 /* An array of offsets of compressed blocks within the file */
104 - loff_t *offsets;
105 + struct block_info *offsets;
107 /* We buffer some uncompressed blocks for performance */
108 int buffered_blocknum[BUFFERED_BLOCKS];
109 @@ -256,11 +263,11 @@
110 return i;
111 }
113 - buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]);
114 + buf_length = clo->offsets[blocknum].size;
116 /* Load one compressed block from the file. */
117 cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
118 - be64_to_cpu(clo->offsets[blocknum]), buf_length);
119 + clo->offsets[blocknum].offset, buf_length);
121 buflen = ntohl(clo->head.block_size);
123 @@ -275,9 +282,9 @@
124 if (ret != 0)
125 {
126 printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u "
127 - "%Lu-%Lu\n", cloop_name, ret, blocknum,
128 + "%Lu:%u\n", cloop_name, ret, blocknum,
129 ntohl(clo->head.block_size), buflen, buf_length, buf_done,
130 - be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1]));
131 + clo->offsets[blocknum].offset, clo->offsets[blocknum].size);
132 clo->buffered_blocknum[clo->current_bufnum] = -1;
133 return -1;
134 }
135 @@ -489,30 +496,73 @@
136 cloop_name, ntohl(clo->head.block_size));
137 error=-EBADF; goto error_release;
138 }
139 - if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1')
140 - {
141 - printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, "
142 - "please use an older version of %s for this file.\n",
143 - cloop_name, cloop_name);
144 - error=-EBADF; goto error_release;
145 - }
146 - if (clo->head.preamble[0x0C]<'2')
147 - {
148 - printk(KERN_ERR "%s: Cannot read old architecture-dependent "
149 - "(format <= 1.0) images, please use an older "
150 - "version of %s for this file.\n",
151 - cloop_name, cloop_name);
152 - error=-EBADF; goto error_release;
153 - }
154 - total_offsets=ntohl(clo->head.num_blocks)+1;
155 - if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)*
156 + total_offsets=ntohl(clo->head.num_blocks);
157 + if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)*
158 total_offsets > inode->i_size))
159 {
160 printk(KERN_ERR "%s: file too small for %u blocks\n",
161 cloop_name, ntohl(clo->head.num_blocks));
162 error=-EBADF; goto error_release;
163 }
164 - clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets);
165 + if (total_offsets + 1 == 0) /* Version >= 3.0 */
166 + {
167 + struct cloop_tail tail;
168 + if(isblkdev)
169 + {
170 + /* No end of file: can't find index */
171 + printk(KERN_ERR "%s: no V3 support for block device\n",
172 + cloop_name);
173 + error=-EBADF; goto error_release;
174 + }
175 + bytes_read = cloop_read_from_file(clo, file, (void *) &tail,
176 + inode->i_size - sizeof(struct cloop_tail),
177 + sizeof(struct cloop_tail));
178 + if(bytes_read == sizeof(struct cloop_tail))
179 + {
180 + unsigned long len, zlen;
181 + void *zbuf;
182 + clo->head.num_blocks = tail.num_blocks;
183 + total_offsets = ntohl(clo->head.num_blocks);
184 + clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets);
185 + if (!clo->offsets)
186 + {
187 + printk(KERN_ERR "%s: can't alloc index\n",
188 + cloop_name);
189 + error=-EBADF; goto error_release;
190 + }
191 + zbuf = &clo->offsets[total_offsets/2];
192 + zlen = ntohl(tail.table_size);
193 + len = ntohl(tail.index_size) * total_offsets;
194 + bytes_read = cloop_read_from_file(clo, file, zbuf,
195 + inode->i_size - zlen - sizeof(struct cloop_tail),
196 + zlen);
197 + if (bytes_read != zlen)
198 + {
199 + printk(KERN_ERR "%s: can't read index\n",
200 + cloop_name);
201 + error=-EBADF; goto error_release;
202 + }
203 + clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize());
204 + if(!clo->zstream.workspace)
205 + {
206 + printk(KERN_ERR "%s: can't alloc index workspace\n",
207 + cloop_name);
208 + error=-EBADF; goto error_release;
209 + }
210 + zlib_inflateInit(&clo->zstream);
211 + uncompress(clo, (void *) clo->offsets, &len, zbuf, zlen);
212 + cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize());
213 + clo->zstream.workspace = NULL;
214 + break;
215 + }
216 + else
217 + {
218 + printk(KERN_ERR "%s: can't find index\n",
219 + cloop_name);
220 + error=-EBADF; goto error_release;
221 + }
222 + }
223 + clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets);
224 if (!clo->offsets)
225 {
226 printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
227 @@ -521,19 +571,19 @@
228 }
229 num_readable = MIN(total_offsets - offsets_read,
230 (clo->underlying_blksize - offset)
231 - / sizeof(loff_t));
232 - memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t));
233 + / sizeof(struct block_info));
234 + memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(struct block_info));
235 offsets_read += num_readable;
236 }
237 { /* Search for largest block rather than estimate. KK. */
238 int i;
239 - for(i=0;i<total_offsets-1;i++)
240 + char *version = build_index(clo->offsets, ntohl(clo->head.num_blocks));
241 + for(i=0;i<total_offsets;i++)
242 {
243 - loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]);
244 - clo->largest_block=MAX(clo->largest_block,d);
245 + clo->largest_block=MAX(clo->largest_block,clo->offsets[i].size);
246 }
247 - printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n",
248 - cloop_name, filename, ntohl(clo->head.num_blocks),
249 + printk(KERN_INFO "%s: %s: %s, %u blocks, %u bytes/block, largest block is %lu bytes.\n",
250 + cloop_name, filename, version, ntohl(clo->head.num_blocks),
251 ntohl(clo->head.block_size), clo->largest_block);
252 }
253 /* Combo kmalloc used too large chunks (>130000). */
254 @@ -565,16 +615,6 @@
255 error=-ENOMEM; goto error_release_free_all;
256 }
257 zlib_inflateInit(&clo->zstream);
258 - if(!isblkdev &&
259 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size)
260 - {
261 - printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n",
262 - cloop_name,
263 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]),
264 - inode->i_size);
265 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL;
266 - goto error_release_free_all;
267 - }
268 {
269 int i;
270 for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1;
271 @@ -653,7 +693,7 @@
272 }
273 }
274 error_release_free:
275 - cloop_free(clo->offsets, sizeof(loff_t) * total_offsets);
276 + cloop_free(clo->offsets, sizeof(struct block_info) * total_offsets);
277 clo->offsets=NULL;
278 error_release:
279 if(bbuf) cloop_free(bbuf, clo->underlying_blksize);