]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.20-squashfs.patch
- added description of djurban's branch
[packages/kernel.git] / linux-2.4.20-squashfs.patch
1 diff --new-file -ur linux-2.4.20/fs/Config.in linux/fs/Config.in
2 --- linux-2.4.20/fs/Config.in   Thu Nov 28 23:53:15 2002
3 +++ linux/fs/Config.in  Sun Dec  1 05:40:22 2002
4 @@ -47,6 +47,7 @@
5     int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
6  fi
7  tristate 'Compressed ROM file system support' CONFIG_CRAMFS
8 +tristate 'Squashed file system support' CONFIG_SQUASHFS
9  bool 'Virtual memory file system support (former shm fs)' CONFIG_TMPFS
10  define_bool CONFIG_RAMFS y
11  
12 diff --new-file -ur linux-2.4.20/fs/Makefile linux/fs/Makefile
13 --- linux-2.4.20/fs/Makefile    Thu Nov 28 23:53:15 2002
14 +++ linux/fs/Makefile   Sun Dec  1 05:57:31 2002
15 @@ -68,6 +68,7 @@
16  subdir-$(CONFIG_BEFS_FS)       += befs
17  subdir-$(CONFIG_JFS_FS)                += jfs
18  subdir-$(CONFIG_XFS_FS)                += xfs
19 +subdir-$(CONFIG_SQUASHFS)      += squashfs
20  
21  
22  obj-$(CONFIG_BINFMT_AOUT)      += binfmt_aout.o
23 diff --new-file -ur linux-2.4.20/fs/squashfs/Makefile linux/fs/squashfs/Makefile
24 --- linux-2.4.20/fs/squashfs/Makefile   Thu Jan  1 01:00:00 1970
25 +++ linux/fs/squashfs/Makefile  Wed Jan  8 10:39:54 2003
26 @@ -0,0 +1,11 @@
27 +#
28 +# Makefile for the linux squashfs routines.
29 +#
30 +
31 +O_TARGET := squashfs.o
32 +
33 +obj-y  := inode.o
34 +
35 +obj-m := $(O_TARGET)
36 +
37 +include $(TOPDIR)/Rules.make
38 diff --new-file -ur linux-2.4.20/fs/squashfs/inode.c linux/fs/squashfs/inode.c
39 --- linux-2.4.20/fs/squashfs/inode.c    Thu Jan  1 01:00:00 1970
40 +++ linux/fs/squashfs/inode.c   Tue Jan 14 04:44:35 2003
41 @@ -0,0 +1,923 @@
42 +/*
43 + * Squashfs - a compressed read only filesystem for Linux
44 + *
45 + * Copyright (c) 2002 Phillip Lougher <phillip@lougher.demon.co.uk>
46 + *
47 + * This program is free software; you can redistribute it and/or
48 + * modify it under the terms of the GNU General Public License
49 + * as published by the Free Software Foundation; either version
50 + * 2 of the License, or (at your option) any later version.
51 + *
52 + * inode.c
53 + */
54 +
55 +#include <linux/types.h>
56 +#include <linux/squashfs_fs.h>
57 +#include <linux/module.h>
58 +#include <linux/errno.h>
59 +#include <linux/slab.h>
60 +#include <linux/fs.h>
61 +#include <linux/locks.h>
62 +#include <linux/init.h>
63 +#include <linux/dcache.h>
64 +#include <asm/uaccess.h>
65 +#include <linux/wait.h>
66 +#include <asm/semaphore.h>
67 +#include <linux/zlib.h>
68 +#include <linux/blkdev.h>
69 +#include <linux/vmalloc.h>
70 +
71 +#ifdef SQUASHFS_TRACE
72 +#define TRACE(s, args...)                              printk(KERN_NOTICE "SQUASHFS: "s, ## args)
73 +#else
74 +#define TRACE(s, args...)                              {}
75 +#endif
76 +
77 +#define ERROR(s, args...)                              printk(KERN_ERR "SQUASHFS error: "s, ## args)
78 +
79 +#define SERROR(s, args...)                             if(!silent) printk(KERN_ERR "SQUASHFS error: "s, ## args)
80 +#define WARNING(s, args...)                            printk(KERN_WARNING "SQUASHFS: "s, ## args)
81 +
82 +static struct super_block *squashfs_read_super(struct super_block *, void *, int);
83 +static void squashfs_put_super(struct super_block *);
84 +static int squashfs_statfs(struct super_block *, struct statfs *);
85 +static int squashfs_symlink_readpage(struct file *file, struct page *page);
86 +static int squashfs_readpage(struct file *file, struct page *page);
87 +static int squashfs_readdir(struct file *, void *, filldir_t);
88 +static struct dentry *squashfs_lookup(struct inode *, struct dentry *);
89 +static unsigned int read_data(struct super_block *s, char *buffer,
90 +               unsigned int index, int length, unsigned int *next_index);
91 +static int squashfs_get_cached_block(struct super_block *s, char *buffer,
92 +               unsigned int block, unsigned int offset, int length,
93 +               unsigned int *next_block, unsigned int *next_offset);
94 +static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode);
95 +static void squashfs_put_super(struct super_block *s);
96 +
97 +DECLARE_MUTEX(read_data_mutex);
98 +
99 +static z_stream stream;
100 +
101 +static DECLARE_FSTYPE_DEV(squashfs_fs_type, "squashfs", squashfs_read_super);
102 +
103 +static unsigned char squashfs_filetype_table[] = {
104 +       DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR
105 +};
106 +
107 +static struct super_operations squashfs_ops = {
108 +       statfs: squashfs_statfs,
109 +       put_super: squashfs_put_super,
110 +};
111 +
112 +static struct address_space_operations squashfs_symlink_aops = {
113 +       readpage: squashfs_symlink_readpage
114 +};
115 +
116 +static struct address_space_operations squashfs_aops = {
117 +       readpage: squashfs_readpage
118 +};
119 +
120 +static struct file_operations squashfs_dir_ops = {
121 +       read: generic_read_dir,
122 +       readdir: squashfs_readdir
123 +};
124 +
125 +static struct inode_operations squashfs_dir_inode_ops = {
126 +       lookup: squashfs_lookup
127 +};
128 +
129 +
130 +static unsigned int read_data(struct super_block *s, char *buffer,
131 +               unsigned int index, int length, unsigned int *next_index)
132 +{
133 +       squashfs_sb_info *msBlk = &s->u.squashfs_sb;
134 +       struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> msBlk->devblksize_log2) + 2];
135 +       unsigned short c_byte;
136 +       unsigned int offset = index & ((1 << msBlk->devblksize_log2) - 1);
137 +       unsigned int cur_index = index >> msBlk->devblksize_log2;
138 +       int bytes, avail_bytes, b, k;
139 +       char *c_buffer;
140 +       unsigned int compressed;
141 +
142 +       if(!(bh[0] = sb_bread(s, cur_index)))
143 +               goto read_failure;
144 +
145 +       if(length)
146 +               c_byte = length;
147 +       else {
148 +               if(msBlk->devblksize - offset == 1) {
149 +                       if(msBlk->swap)
150 +                               ((unsigned char *) &c_byte)[1] = *((unsigned char *) (bh[0]->b_data + offset));
151 +                       else
152 +                               ((unsigned char *) &c_byte)[0] = *((unsigned char *) (bh[0]->b_data + offset));
153 +                       brelse(bh[0]);
154 +                       if(!(bh[0] = sb_bread(s, ++cur_index)))
155 +                               goto read_failure;
156 +                       if(msBlk->swap)
157 +                               ((unsigned char *) &c_byte)[0] = *((unsigned char *) bh[0]->b_data); 
158 +                       else
159 +                               ((unsigned char *) &c_byte)[1] = *((unsigned char *) bh[0]->b_data); 
160 +                       offset = 1;
161 +               }
162 +               else {
163 +                       if(msBlk->swap) {
164 +                               ((unsigned char *) &c_byte)[1] = *((unsigned char *) (bh[0]->b_data + offset));
165 +                               ((unsigned char *) &c_byte)[0] = *((unsigned char *) (bh[0]->b_data + offset + 1)); 
166 +                       } else
167 +                               c_byte = *((unsigned short *) (bh[0]->b_data + offset));
168 +                       offset += 2;
169 +               }
170 +               if(SQUASHFS_CHECK_DATA(msBlk->sBlk.flags)) {
171 +                       if(offset == msBlk->devblksize) {
172 +                               brelse(bh[0]);
173 +                               if(!(bh[0] = sb_bread(s, ++cur_index)))
174 +                                       goto read_failure;
175 +                               offset = 0;
176 +                       }
177 +                       if(*((unsigned char *) (bh[0]->b_data + offset)) != SQUASHFS_MARKER_BYTE) {
178 +                               ERROR("Metadata block marker corrupt @ %x\n", index);
179 +                               brelse(bh[0]);
180 +                               return 0;
181 +                       }
182 +                       offset ++;
183 +               }
184 +       }
185 +
186 +       bytes = msBlk->devblksize - offset;
187 +       c_buffer = (compressed = SQUASHFS_COMPRESSED(c_byte)) ? msBlk->read_data : buffer;
188 +       c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
189 +
190 +       TRACE("Block @ 0x%x, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte);
191 +
192 +       for(b = 1; bytes < c_byte; b++) {
193 +               if(!(bh[b] = sb_bread(s, ++cur_index)))
194 +                       goto block_release;
195 +               bytes += msBlk->devblksize;
196 +       }
197 +
198 +       if(compressed)
199 +               down(&read_data_mutex);
200 +
201 +       for(bytes = 0, k = 0; k < b; k++) {
202 +               avail_bytes = (c_byte - bytes) > (msBlk->devblksize - offset) ? msBlk->devblksize - offset : c_byte - bytes;
203 +               memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
204 +               bytes += avail_bytes;
205 +               offset = 0;
206 +               brelse(bh[k]);
207 +       }
208 +
209 +       /*
210 +        * uncompress block
211 +        */
212 +       if(compressed) {
213 +               int zlib_err;
214 +
215 +               stream.next_in = c_buffer;
216 +               stream.avail_in = c_byte;
217 +               stream.next_out = buffer;
218 +               stream.avail_out = msBlk->read_size;
219 +               if(((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
220 +                               ((zlib_err = zlib_inflate(&stream, Z_FINISH)) != Z_STREAM_END) ||
221 +                               ((zlib_err = zlib_inflateEnd(&stream)) != Z_OK)) {
222 +                       ERROR("zlib_fs returned unexpected result 0x%x\n", zlib_err);
223 +                       bytes = 0;
224 +               } else
225 +                       bytes = stream.total_out;
226 +               up(&read_data_mutex);
227 +       }
228 +
229 +       if(next_index)
230 +               *next_index = index + c_byte + (length ? 0 : (SQUASHFS_CHECK_DATA(msBlk->sBlk.flags) ? 3 : 2));
231 +
232 +       return bytes;
233 +
234 +block_release:
235 +       while(--b >= 0) brelse(bh[b]);
236 +
237 +read_failure:
238 +       ERROR("sb_bread failed reading block 0x%x\n", cur_index);
239 +       return 0;
240 +}
241 +
242 +
243 +static int squashfs_get_cached_block(struct super_block *s, char *buffer,
244 +               unsigned int block, unsigned int offset, int length,
245 +               unsigned int *next_block, unsigned int *next_offset)
246 +{
247 +       squashfs_sb_info *msBlk = &s->u.squashfs_sb;
248 +       int n, i, bytes, return_length = length;
249 +       unsigned int next_index;
250 +
251 +       TRACE("Entered squashfs_get_cached_block [%x:%x]\n", block, offset);
252 +
253 +       for(;;) {
254 +               for(i = 0; i < SQUASHFS_CACHED_BLKS; i++) 
255 +                       if(msBlk->block_cache[i].block == block)
256 +                               break; 
257 +               
258 +               down(&msBlk->block_cache_mutex);
259 +               if(i == SQUASHFS_CACHED_BLKS) {
260 +                       /* read inode header block */
261 +                       for(i = msBlk->next_cache, n = SQUASHFS_CACHED_BLKS; n ; n --, i = (i + 1) % SQUASHFS_CACHED_BLKS)
262 +                               if(msBlk->block_cache[i].block != SQUASHFS_USED_BLK)
263 +                                       break;
264 +                       if(n == 0) {
265 +                               up(&msBlk->block_cache_mutex);
266 +                               sleep_on(&msBlk->waitq);
267 +                               continue;
268 +                       }
269 +                       msBlk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
270 +
271 +                       if(msBlk->block_cache[i].block == SQUASHFS_INVALID_BLK) {
272 +                               if(!(msBlk->block_cache[i].data = (unsigned char *)
273 +                                                       kmalloc(SQUASHFS_METADATA_SIZE, GFP_KERNEL))) {
274 +                                       ERROR("Failed to allocate cache block\n");
275 +                                       up(&msBlk->block_cache_mutex);
276 +                                       return 0;
277 +                               }
278 +                       }
279 +       
280 +                       msBlk->block_cache[i].block = SQUASHFS_USED_BLK;
281 +                       up(&msBlk->block_cache_mutex);
282 +                       if(!(msBlk->block_cache[i].length = read_data(s, msBlk->block_cache[i].data, block, 0,
283 +                                                       &next_index))) {
284 +                               ERROR("Unable to read cache block [%x:%x]\n", block, offset);
285 +                               return 0;
286 +                       }
287 +                       down(&msBlk->block_cache_mutex);
288 +                       wake_up(&msBlk->waitq);
289 +                       msBlk->block_cache[i].block = block;
290 +                       msBlk->block_cache[i].next_index = next_index;
291 +                       TRACE("Read cache block [%x:%x]\n", block, offset);
292 +               }
293 +
294 +               if(msBlk->block_cache[i].block != block) {
295 +                       up(&msBlk->block_cache_mutex);
296 +                       continue;
297 +               }
298 +
299 +               if((bytes = msBlk->block_cache[i].length - offset) >= length) {
300 +                       memcpy(buffer, msBlk->block_cache[i].data + offset, length);
301 +                       if(msBlk->block_cache[i].length - offset == length) {
302 +                               *next_block = msBlk->block_cache[i].next_index;
303 +                               *next_offset = 0;
304 +                       } else {
305 +                               *next_block = block;
306 +                               *next_offset = offset + length;
307 +                       }
308 +       
309 +                       up(&msBlk->block_cache_mutex);
310 +                       return return_length;
311 +               } else {
312 +                       memcpy(buffer, msBlk->block_cache[i].data + offset, bytes);
313 +                       block = msBlk->block_cache[i].next_index;
314 +                       up(&msBlk->block_cache_mutex);
315 +                       length -= bytes;
316 +                       offset = 0;
317 +                       buffer += bytes;
318 +               }
319 +       }
320 +}
321 +
322 +
323 +static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode)
324 +{
325 +       struct inode *i = new_inode(s);
326 +       squashfs_sb_info *msBlk = &s->u.squashfs_sb;
327 +       squashfs_super_block *sBlk = &msBlk->sBlk;
328 +       unsigned int block = SQUASHFS_INODE_BLK(inode) + sBlk->inode_table_start;
329 +       unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
330 +       unsigned int next_block, next_offset;
331 +       squashfs_base_inode_header inodeb;
332 +
333 +       TRACE("Entered squashfs_iget\n");
334 +
335 +       if(msBlk->swap) {
336 +               squashfs_base_inode_header sinodeb;
337 +
338 +               if(!squashfs_get_cached_block(s, (char *) &sinodeb, block,  offset,
339 +                                       sizeof(sinodeb), &next_block, &next_offset))
340 +                       goto failed_read;
341 +               SQUASHFS_SWAP_BASE_INODE_HEADER(&inodeb, &sinodeb, sizeof(sinodeb));
342 +       } else
343 +               if(!squashfs_get_cached_block(s, (char *) &inodeb, block,  offset,
344 +                                       sizeof(inodeb), &next_block, &next_offset))
345 +                       goto failed_read;
346 +
347 +       i->i_nlink = 1;
348 +
349 +       i->i_mtime = sBlk->mkfs_time;
350 +       i->i_atime = sBlk->mkfs_time;
351 +       i->i_ctime = sBlk->mkfs_time;
352 +       i->i_uid = msBlk->uid[((inodeb.inode_type - 1) / SQUASHFS_TYPES) * 16 + inodeb.uid];
353 +       i->i_ino = SQUASHFS_MK_VFS_INODE(block - sBlk->inode_table_start, offset);
354 +
355 +       if(inodeb.guid == SQUASHFS_GUIDS)
356 +               i->i_gid = i->i_uid;
357 +       else
358 +               i->i_gid = msBlk->guid[inodeb.guid];
359 +
360 +       i->i_mode = inodeb.mode;
361 +
362 +       switch((inodeb.inode_type - 1) % SQUASHFS_TYPES + 1) {
363 +               case SQUASHFS_FILE_TYPE: {
364 +                       squashfs_reg_inode_header inodep;
365 +
366 +                       if(msBlk->swap) {
367 +                               squashfs_reg_inode_header sinodep;
368 +
369 +                               if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
370 +                                                       &next_block, &next_offset))
371 +                                       goto failed_read;
372 +                               SQUASHFS_SWAP_REG_INODE_HEADER(&inodep, &sinodep);
373 +                       } else
374 +                               if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
375 +                                                       &next_block, &next_offset))
376 +                                       goto failed_read;
377 +
378 +                       i->i_size = inodep.file_size;
379 +                       i->i_fop = &generic_ro_fops;
380 +                       i->i_data.a_ops = &squashfs_aops;
381 +                       i->i_mode |= S_IFREG;
382 +                       i->i_mtime = inodep.mtime;
383 +                       i->i_atime = inodep.mtime;
384 +                       i->i_ctime = inodep.mtime;
385 +                       i->u.squashfs_i.start_block = inodep.start_block;
386 +                       i->u.squashfs_i.block_list_start = next_block;
387 +                       i->u.squashfs_i.offset = next_offset;
388 +                       TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n",
389 +                                       SQUASHFS_INODE_BLK(inode), offset, inodep.start_block, next_block, next_offset);
390 +                       break;
391 +               }
392 +               case SQUASHFS_DIR_TYPE: {
393 +                       squashfs_dir_inode_header inodep;
394 +
395 +                       if(msBlk->swap) {
396 +                               squashfs_dir_inode_header sinodep;
397 +
398 +                               if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
399 +                                                       &next_block, &next_offset))
400 +                                       goto failed_read;
401 +                               SQUASHFS_SWAP_DIR_INODE_HEADER(&inodep, &sinodep);
402 +                       } else
403 +                               if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
404 +                                                       &next_block, &next_offset))
405 +                                       goto failed_read;
406 +
407 +                       i->i_size = inodep.file_size;
408 +                       i->i_op = &squashfs_dir_inode_ops;
409 +                       i->i_fop = &squashfs_dir_ops;
410 +                       i->i_mode |= S_IFDIR;
411 +                       i->i_mtime = inodep.mtime;
412 +                       i->i_atime = inodep.mtime;
413 +                       i->i_ctime = inodep.mtime;
414 +                       i->u.squashfs_i.start_block = inodep.start_block;
415 +                       i->u.squashfs_i.offset = inodep.offset;
416 +                       TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset,
417 +                                       inodep.start_block, inodep.offset);
418 +                       break;
419 +               }
420 +               case SQUASHFS_SYMLINK_TYPE: {
421 +                       squashfs_symlink_inode_header inodep;
422 +       
423 +                       if(msBlk->swap) {
424 +                               squashfs_symlink_inode_header sinodep;
425 +
426 +                               if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
427 +                                                       &next_block, &next_offset))
428 +                                       goto failed_read;
429 +                               SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep);
430 +                       } else
431 +                               if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
432 +                                                       &next_block, &next_offset))
433 +                                       goto failed_read;
434 +
435 +                       i->i_size = inodep.symlink_size;
436 +                       i->i_op = &page_symlink_inode_operations;
437 +                       i->i_data.a_ops = &squashfs_symlink_aops;
438 +                       i->i_mode |= S_IFLNK;
439 +                       i->u.squashfs_i.start_block = next_block;
440 +                       i->u.squashfs_i.offset = next_offset;
441 +                       TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n",
442 +                               SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset);
443 +                       break;
444 +                }
445 +                case SQUASHFS_BLKDEV_TYPE:
446 +                case SQUASHFS_CHRDEV_TYPE: {
447 +                       squashfs_dev_inode_header inodep;
448 +
449 +                       if(msBlk->swap) {
450 +                               squashfs_dev_inode_header sinodep;
451 +
452 +                               if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
453 +                                                       &next_block, &next_offset))
454 +                                       goto failed_read;
455 +                               SQUASHFS_SWAP_DEV_INODE_HEADER(&inodep, &sinodep);
456 +                       } else  
457 +                               if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
458 +                                                       &next_block, &next_offset))
459 +                                       goto failed_read;
460 +
461 +                       i->i_size = 0;
462 +                       i->i_mode |= (inodeb.inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK;
463 +                       init_special_inode(i, i->i_mode, inodep.rdev);
464 +                       TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep.rdev);
465 +                       break;
466 +                }
467 +                default:
468 +                       ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb.inode_type);
469 +                               goto failed_read1;
470 +       }
471 +       
472 +       return i;
473 +
474 +failed_read:
475 +       ERROR("Unable to read inode [%x:%x]\n", block, offset);
476 +
477 +failed_read1:
478 +       return NULL;
479 +}
480 +
481 +
482 +static struct super_block *squashfs_read_super(struct super_block *s,
483 +               void *data, int silent)
484 +{
485 +       kdev_t dev = s->s_dev;
486 +       squashfs_sb_info *msBlk = &s->u.squashfs_sb;
487 +       squashfs_super_block *sBlk = &msBlk->sBlk;
488 +       int i;
489 +
490 +       TRACE("Entered squashfs_read_superblock\n");
491 +
492 +       msBlk->devblksize = get_hardsect_size(dev);
493 +       if(msBlk->devblksize < BLOCK_SIZE)
494 +               msBlk->devblksize = BLOCK_SIZE;
495 +       msBlk->devblksize_log2 = ffz(~msBlk->devblksize);
496 +       set_blocksize(dev, msBlk->devblksize);
497 +       s->s_blocksize = msBlk->devblksize;
498 +       s->s_blocksize_bits = msBlk->devblksize_log2;
499 +
500 +       init_MUTEX(&msBlk->read_page_mutex);
501 +       init_MUTEX(&msBlk->block_cache_mutex);
502 +       
503 +       init_waitqueue_head(&msBlk->waitq);
504 +
505 +       if(!read_data(s, (char *) sBlk, SQUASHFS_START, sizeof(squashfs_super_block) | SQUASHFS_COMPRESSED_BIT, NULL)) {
506 +               SERROR("unable to read superblock\n");
507 +               goto failed_mount;
508 +       }
509 +
510 +       /* Check it is a SQUASHFS superblock */
511 +       msBlk->swap = 0;
512 +       if((s->s_magic = sBlk->s_magic) != SQUASHFS_MAGIC) {
513 +               if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) {
514 +                       squashfs_super_block sblk;
515 +                       WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", bdevname(dev));
516 +                       SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk);
517 +                       memcpy(sBlk, &sblk, sizeof(squashfs_super_block));
518 +                       msBlk->swap = 1;
519 +               } else  {
520 +                       SERROR("Can't find a SQUASHFS superblock on %s\n", bdevname(dev));
521 +                       goto failed_mount;
522 +               }
523 +       }
524 +
525 +       /* Check the MAJOR & MINOR versions */
526 +       if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
527 +               SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (%d: <= %d)\n",
528 +                               sBlk->s_major, sBlk->s_minor, SQUASHFS_MAJOR, SQUASHFS_MINOR);
529 +               goto failed_mount;
530 +       }
531 +
532 +       TRACE("Found valid superblock on %s\n", bdevname(dev));
533 +       TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
534 +       TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : "");
535 +       TRACE("Check data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not");
536 +       TRACE("Filesystem size %d bytes\n", sBlk->bytes_used);
537 +       TRACE("Block size %d\n", sBlk->block_size);
538 +       TRACE("Number of inodes %d\n", sBlk->inodes);
539 +       TRACE("Number of uids %d\n", sBlk->no_uids);
540 +       TRACE("Number of gids %d\n", sBlk->no_guids);
541 +       TRACE("sBlk->inode_table_start %x\n", sBlk->inode_table_start);
542 +       TRACE("sBlk->directory_table_start %x\n", sBlk->directory_table_start);
543 +       TRACE("sBlk->uid_start %x\n", sBlk->uid_start);
544 +
545 +       s->s_flags |= MS_RDONLY;
546 +       s->s_op = &squashfs_ops;
547 +
548 +       /* Init inode_table block pointer array */
549 +       if(!(msBlk->block_cache = (squashfs_cache *) kmalloc(sizeof(squashfs_cache) * SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
550 +               ERROR("Failed to allocate block cache\n");
551 +               goto failed_mount;
552 +       }
553 +
554 +       for(i = 0; i < SQUASHFS_CACHED_BLKS; i++)
555 +               msBlk->block_cache[i].block = SQUASHFS_INVALID_BLK;
556 +
557 +       msBlk->next_cache = 0;
558 +
559 +       /* Allocate read_data block */
560 +       msBlk->read_size = (sBlk->block_size < SQUASHFS_METADATA_SIZE) ? SQUASHFS_METADATA_SIZE : sBlk->block_size;
561 +       if(!(msBlk->read_data = (char *) kmalloc(msBlk->read_size, GFP_KERNEL))) {
562 +               ERROR("Failed to allocate read_data block\n");
563 +               goto failed_mount1;
564 +       }
565 +
566 +       /* Allocate read_page block */
567 +       if(sBlk->block_size > PAGE_CACHE_SIZE && 
568 +          !(msBlk->read_page = (char *) kmalloc(sBlk->block_size, GFP_KERNEL))) {
569 +               ERROR("Failed to allocate read_page block\n");
570 +               goto failed_mount2;
571 +       }
572 +
573 +       /* Allocate uid and gid tables */
574 +       if(!(msBlk->uid = (squashfs_uid *) kmalloc((sBlk->no_uids +
575 +               sBlk->no_guids) * sizeof(squashfs_uid), GFP_KERNEL))) {
576 +               ERROR("Failed to allocate uid/gid table\n");
577 +               goto failed_mount3;
578 +       }
579 +       msBlk->guid = msBlk->uid + sBlk->no_uids;
580 +   
581 +       if(msBlk->swap) {
582 +               squashfs_uid suid[sBlk->no_uids + sBlk->no_guids];
583 +
584 +               if(!read_data(s, (char *) &suid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) *
585 +                               sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, NULL)) {
586 +                       SERROR("unable to read uid/gid table\n");
587 +                       goto failed_mount4;
588 +               }
589 +               SQUASHFS_SWAP_DATA(msBlk->uid, suid, (sBlk->no_uids + sBlk->no_guids), (sizeof(squashfs_uid) * 8));
590 +       } else
591 +               if(!read_data(s, (char *) msBlk->uid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) *
592 +                               sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, NULL)) {
593 +                       SERROR("unable to read uid/gid table\n");
594 +                       goto failed_mount4;
595 +               }
596 +
597 +       if(!(s->s_root = d_alloc_root(squashfs_iget(s, sBlk->root_inode)))) {
598 +               ERROR("Root inode create failed\n");
599 +               goto failed_mount4;
600 +       }
601 +
602 +       TRACE("Leaving squashfs_read_super\n");
603 +       return s;
604 +
605 +failed_mount4:
606 +       kfree(msBlk->uid);
607 +failed_mount3:
608 +       kfree(msBlk->read_page);
609 +failed_mount2:
610 +       kfree(msBlk->read_data);
611 +failed_mount1:
612 +       kfree(msBlk->block_cache);
613 +failed_mount:
614 +       return NULL;
615 +}
616 +
617 +
618 +static int squashfs_statfs(struct super_block *s, struct statfs *buf)
619 +{
620 +       squashfs_super_block *sBlk = &s->u.squashfs_sb.sBlk;
621 +
622 +       TRACE("Entered squashfs_statfs\n");
623 +       buf->f_type = SQUASHFS_MAGIC;
624 +       buf->f_bsize = sBlk->block_size;
625 +       buf->f_blocks = ((sBlk->bytes_used - 1) >> sBlk->block_log) + 1;
626 +       buf->f_bfree = buf->f_bavail = 0;
627 +       buf->f_files = sBlk->inodes;
628 +       buf->f_ffree = 0;
629 +       buf->f_namelen = SQUASHFS_NAME_LEN;
630 +       return 0;
631 +}
632 +
633 +
634 +static int squashfs_symlink_readpage(struct file *file, struct page *page)
635 +{
636 +       struct inode *inode = page->mapping->host;
637 +       int index = page->index << PAGE_CACHE_SHIFT, length = 0, bytes;
638 +       int block = inode->u.squashfs_i.start_block;
639 +       int offset = inode->u.squashfs_i.offset;
640 +
641 +       TRACE("Entered squashfs_symlink_readpage, page index %d, start block %x, offset %x\n",
642 +               page->index, inode->u.squashfs_i.start_block, inode->u.squashfs_i.offset);
643 +
644 +       while(length < index) {
645 +               char buffer[PAGE_CACHE_SIZE];
646 +
647 +               if(length += bytes = squashfs_get_cached_block(inode->i_sb, buffer, block, offset,
648 +                                       PAGE_CACHE_SIZE, &block, &offset), !bytes) {
649 +                       ERROR("Unable to read symbolic link [%x:%x]\n", block, offset);
650 +                       goto skip_read;
651 +               }
652 +       }
653 +
654 +       if(length != index) {
655 +               ERROR("(squashfs_symlink_readpage) length != index\n");
656 +               return 0;
657 +       }
658 +
659 +       bytes = (inode->i_size - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : inode->i_size - length;
660 +       if(!squashfs_get_cached_block(inode->i_sb, page_address(page), block, offset, bytes, &block, &offset))
661 +               ERROR("Unable to read symbolic link [%x:%x]\n", block, offset);
662 +
663 +skip_read:
664 +       memset(page_address(page) + bytes, 0, PAGE_CACHE_SIZE - bytes);
665 +       flush_dcache_page(page);
666 +       SetPageUptodate(page);
667 +       UnlockPage(page);
668 +
669 +       return 0;
670 +}
671 +
672 +
673 +#define SIZE 1024
674 +static int squashfs_readpage(struct file *file, struct page *page)
675 +{
676 +       struct inode *inode = page->mapping->host;
677 +       squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;
678 +       squashfs_super_block *sBlk = &msBlk->sBlk;
679 +       unsigned char block_list[SIZE];
680 +       unsigned short *block_listp;
681 +       int index = sBlk->block_log > PAGE_CACHE_SHIFT ?
682 +               page->index >> (sBlk->block_log - PAGE_CACHE_SHIFT) :
683 +               page->index << (PAGE_CACHE_SHIFT - sBlk->block_log);
684 +       int block = inode->u.squashfs_i.start_block, i = 0;
685 +       int bytes = inode->u.squashfs_i.block_list_start;
686 +       int offset = inode->u.squashfs_i.offset;
687 +       int file_blocks = ((inode->i_size - 1) >> sBlk->block_log) + 1;
688 +       
689 +       TRACE("Entered squashfs_readpage, page index %d, start block %x\n", page->index,
690 +               inode->u.squashfs_i.start_block);
691 +
692 +       if(index > file_blocks)
693 +               goto skip_read;
694 +
695 +       for(;;) {
696 +               int blocks = (index + 1 - i) > (SIZE >> 1) ? SIZE >> 1 : (index + 1 - i);
697 +               if(msBlk->swap) {
698 +                       unsigned char sblock_list[SIZE];
699 +                       if(!squashfs_get_cached_block(inode->i_sb, (char *) sblock_list, bytes, offset, blocks << 1, &bytes, &offset)) {
700 +                               ERROR("Unable to read block list [%d:%x]\n", bytes, offset);
701 +                               goto skip_read;
702 +                       }
703 +                       SQUASHFS_SWAP_SHORTS(((unsigned short *)block_list), ((unsigned short *)sblock_list), blocks);
704 +               } else
705 +                       if(!squashfs_get_cached_block(inode->i_sb, (char *) block_list, bytes, offset, blocks << 1, &bytes, &offset)) {
706 +                               ERROR("Unable to read block list [%d:%x]\n", bytes, offset);
707 +                               goto skip_read;
708 +                       }
709 +               for(block_listp = (unsigned short *) block_list; i < index && blocks; i ++, block_listp ++, blocks --)
710 +                       block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
711 +               if(blocks)
712 +                       break;
713 +       }
714 +
715 +       if(sBlk->block_log > PAGE_CACHE_SHIFT) {
716 +               int mask = (1 << (sBlk->block_log - PAGE_CACHE_SHIFT)) - 1;
717 +               int start_index = page->index & ~mask;
718 +               int end_index = start_index | mask;
719 +               int byte_offset = 0;
720 +
721 +               down(&msBlk->read_page_mutex);
722 +               if(!(bytes = read_data(inode->i_sb, msBlk->read_page, block, *block_listp, NULL))) {
723 +                       ERROR("Unable to read page, block %x, size %x\n", block, (int) *block_listp);
724 +                       goto skip_read;
725 +               }
726 +
727 +               for(i = start_index; i <= end_index && byte_offset < bytes; i++, byte_offset += PAGE_CACHE_SIZE) {
728 +                       int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : bytes - byte_offset;
729 +
730 +                       TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", bytes, i, byte_offset, available_bytes);
731 +
732 +                       if(i == page->index)  {
733 +                               memcpy(page_address(page), msBlk->read_page + byte_offset, available_bytes);
734 +                               memset(page_address(page) + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes);
735 +                               flush_dcache_page(page);
736 +                               SetPageUptodate(page);
737 +                               UnlockPage(page);
738 +                       }  else {
739 +                               struct page *push_page;
740 +
741 +                               if(push_page = grab_cache_page_nowait(page->mapping, i)) {
742 +                                       memcpy(page_address(push_page), msBlk->read_page + byte_offset, available_bytes);
743 +                                       memset(page_address(push_page) + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes);
744 +                                       flush_dcache_page(push_page);
745 +                                       SetPageUptodate(push_page);
746 +                                       UnlockPage(push_page);
747 +                                       page_cache_release(push_page);
748 +                               }
749 +                       }
750 +               }
751 +               up( &msBlk->read_page_mutex);
752 +
753 +               return 0;
754 +
755 +       } else if(sBlk->block_log == PAGE_CACHE_SHIFT) {
756 +               if(!(bytes = read_data(inode->i_sb, page_address(page), block, *block_listp, NULL)))
757 +                       ERROR("Unable to read page, block %x, size %x\n", block, (int) *block_listp);
758 +
759 +       } else {
760 +               int i_end = index + (1 << (PAGE_CACHE_SHIFT - sBlk->block_log));
761 +               char *p = (char *) page_address(page);
762 +               int byte;
763 +
764 +               if(i_end > file_blocks)
765 +                       i_end = file_blocks;
766 +
767 +               while(index < i_end) {
768 +                       if(!(byte = read_data(inode->i_sb, p, block, *block_listp, NULL))) {
769 +                               ERROR("Unable to read page, block %x, size %x\n", block, (int) *block_listp);
770 +                               goto skip_read;
771 +                       }
772 +                       block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
773 +                       p += byte;
774 +                       bytes += byte;
775 +                       index ++;
776 +                       block_listp ++;
777 +               }
778 +       }
779 +
780 +skip_read:
781 +       memset(page_address(page) + bytes, 0, PAGE_CACHE_SIZE - bytes);
782 +       flush_dcache_page(page);
783 +       SetPageUptodate(page);
784 +       UnlockPage(page);
785 +
786 +       return 0;
787 +}
788 +
789 +
790 +static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
791 +{
792 +       struct inode *i = file->f_dentry->d_inode;
793 +       squashfs_sb_info *msBlk = &i->i_sb->u.squashfs_sb;
794 +       squashfs_super_block *sBlk = &msBlk->sBlk;
795 +       int next_block = i->u.squashfs_i.start_block + sBlk->directory_table_start, next_offset =
796 +               i->u.squashfs_i.offset, length = 0, dirs_read = 0, dir_count, bytes;
797 +       squashfs_dir_header dirh;
798 +       char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
799 +       squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
800 +
801 +       TRACE("Entered squashfs_readdir [%x:%x]\n", next_block, next_offset);
802 +
803 +       while(length < i->i_size) {
804 +               /* read directory header */
805 +               if(msBlk->swap) {
806 +                       squashfs_dir_header sdirh;
807 +                       if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block,
808 +                                               next_offset, sizeof(sdirh), &next_block, &next_offset), !bytes)
809 +                               goto failed_read;
810 +                       SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
811 +               } else
812 +                       if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block,
813 +                                               next_offset, sizeof(dirh), &next_block, &next_offset), !bytes)
814 +                               goto failed_read;
815 +
816 +               dir_count = dirh.count + 1;
817 +               while(dir_count--) {
818 +                       if(msBlk->swap) {
819 +                               squashfs_dir_entry sdire;
820 +                               if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) &sdire, next_block,
821 +                                                       next_offset, sizeof(sdire), &next_block, &next_offset), !bytes)
822 +                                       goto failed_read;
823 +                               SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
824 +                       } else
825 +                               if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) dire, next_block,
826 +                                                       next_offset, sizeof(*dire), &next_block, &next_offset), !bytes)
827 +                                       goto failed_read;
828 +
829 +                       if(length += bytes = squashfs_get_cached_block(i->i_sb, dire->name, next_block,
830 +                                               next_offset, dire->size + 1, &next_block, &next_offset), !bytes)
831 +                               goto failed_read;
832 +
833 +                       if(file->f_pos >= length)
834 +                               continue;
835 +
836 +                       dire->name[dire->size + 1] = '\0';
837 +
838 +                       TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", dirent,
839 +                       dire->name, dire->size + 1, (int) file->f_pos,
840 +                       dirh.start_block, dire->offset, squashfs_filetype_table[dire->type]);
841 +
842 +                       if(filldir(dirent, dire->name, dire->size + 1, file->f_pos, SQUASHFS_MK_VFS_INODE(dirh.start_block,
843 +                                                       dire->offset), squashfs_filetype_table[dire->type]) < 0) {
844 +                               TRACE("Filldir returned less than 0\n");
845 +                               return dirs_read;
846 +                       }
847 +
848 +                       file->f_pos = length;
849 +                       dirs_read ++;
850 +               }
851 +       }
852 +
853 +       return dirs_read;
854 +
855 +failed_read:
856 +       ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);
857 +       return 0;
858 +}
859 +
860 +
861 +static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry)
862 +{
863 +       const char *name =dentry->d_name.name;
864 +       int len = dentry->d_name.len;
865 +       struct inode *inode = NULL;
866 +       squashfs_sb_info *msBlk = &i->i_sb->u.squashfs_sb;
867 +       squashfs_super_block *sBlk = &msBlk->sBlk;
868 +       int next_block = i->u.squashfs_i.start_block + sBlk->directory_table_start, next_offset =
869 +               i->u.squashfs_i.offset, length = 0, dir_count, bytes;
870 +       squashfs_dir_header dirh;
871 +       char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN];
872 +       squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
873 +
874 +       TRACE("Entered squashfs_lookup [%x:%x]\n", next_block, next_offset);
875 +
876 +       while(length < i->i_size) {
877 +               /* read directory header */
878 +               if(msBlk->swap) {
879 +                       squashfs_dir_header sdirh;
880 +                       if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, next_offset,
881 +                                               sizeof(sdirh), &next_block, &next_offset), !bytes)
882 +                               goto failed_read;
883 +                       SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
884 +               } else
885 +                       if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, next_offset,
886 +                                               sizeof(dirh), &next_block, &next_offset), !bytes)
887 +                               goto failed_read;
888 +
889 +               dir_count = dirh.count + 1;
890 +               while(dir_count--) {
891 +                       if(msBlk->swap) {
892 +                               squashfs_dir_entry sdire;
893 +                               if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) &sdire,
894 +                                                       next_block,next_offset, sizeof(sdire), &next_block, &next_offset), !bytes)
895 +                                       goto failed_read;
896 +                               SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
897 +                       } else
898 +                               if(length += bytes = squashfs_get_cached_block(i->i_sb, (char *) dire,
899 +                                                       next_block,next_offset, sizeof(*dire), &next_block, &next_offset), !bytes)
900 +                                       goto failed_read;
901 +
902 +                       if(length += bytes = squashfs_get_cached_block(i->i_sb, dire->name,
903 +                                               next_block, next_offset, dire->size + 1, &next_block, &next_offset), !bytes)
904 +                               goto failed_read;
905 +
906 +                       if((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
907 +                               squashfs_inode ino = SQUASHFS_MKINODE(dirh.start_block, dire->offset);
908 +
909 +                               TRACE("calling squashfs_iget for directory entry %s, inode %x:%x\n",
910 +                                               name, dirh.start_block, dire->offset);
911 +
912 +                               inode = squashfs_iget(i->i_sb, ino);
913 +
914 +                               goto exit_loop;
915 +                       }
916 +               }
917 +       }
918 +
919 +exit_loop:
920 +       d_add(dentry, inode);
921 +       return ERR_PTR(0);
922 +
923 +failed_read:
924 +       ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);
925 +       goto exit_loop;
926 +}
927 +
928 +
929 +static void squashfs_put_super(struct super_block *s)
930 +{
931 +       if(s->u.squashfs_sb.block_cache) kfree(s->u.squashfs_sb.block_cache);
932 +       if(s->u.squashfs_sb.read_data) kfree(s->u.squashfs_sb.read_data);
933 +       if(s->u.squashfs_sb.read_page) kfree(s->u.squashfs_sb.read_page);
934 +       if(s->u.squashfs_sb.uid) kfree(s->u.squashfs_sb.uid);
935 +       s->u.squashfs_sb.block_cache = (void *) s->u.squashfs_sb.uid =
936 +               s->u.squashfs_sb.read_data = s->u.squashfs_sb.read_page = NULL;
937 +}
938 +
939 +
940 +static int __init init_squashfs_fs(void)
941 +{
942 +
943 +       if(!(stream.workspace = (char *) vmalloc(zlib_inflate_workspacesize()))) {
944 +               ERROR("Failed to allocate zlib workspace\n");
945 +               return -ENOMEM;
946 +       }
947 +       return register_filesystem(&squashfs_fs_type);
948 +}
949 +
950 +
951 +static void __exit exit_squashfs_fs(void)
952 +{
953 +       vfree(stream.workspace);
954 +       unregister_filesystem(&squashfs_fs_type);
955 +}
956 +
957 +
958 +EXPORT_NO_SYMBOLS;
959 +
960 +module_init(init_squashfs_fs);
961 +module_exit(exit_squashfs_fs);
962 +MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
963 +MODULE_AUTHOR("Phillip Lougher <phillip@lougher.demon.co.uk>");
964 +MODULE_LICENSE("GPL");
965 diff --new-file -ur linux-2.4.20/include/linux/fs.h linux/include/linux/fs.h
966 --- linux-2.4.20/include/linux/fs.h     Thu Nov 28 23:53:15 2002
967 +++ linux/include/linux/fs.h    Thu Jan  9 03:50:56 2003
968 @@ -320,6 +320,7 @@
969  #include <linux/usbdev_fs_i.h>
970  #include <linux/jffs2_fs_i.h>
971  #include <linux/cramfs_fs_sb.h>
972 +#include <linux/squashfs_fs_i.h>
973  
974  /*
975   * Attribute flags.  These should be or-ed together to figure out what
976 @@ -510,6 +511,7 @@
977                 struct hostfs_inode_info        hostfs_i;
978                 struct hppfs_inode_info         hppfs_i;
979                 struct jffs2_inode_info         jffs2_i;
980 +               struct squashfs_inode_info      squashfs_i;
981                 void                            *generic_ip;
982         } u;
983  };
984 @@ -704,6 +706,7 @@
985  #include <linux/usbdev_fs_sb.h>
986  #include <linux/cramfs_fs_sb.h>
987  #include <linux/jffs2_fs_sb.h>
988 +#include <linux/squashfs_fs_sb.h>
989  
990  extern struct list_head super_blocks;
991  extern spinlock_t sb_lock;
992 @@ -762,6 +765,7 @@
993                 struct usbdev_sb_info   usbdevfs_sb;
994                 struct jffs2_sb_info    jffs2_sb;
995                 struct cramfs_sb_info   cramfs_sb;
996 +               struct squashfs_sb_info squashfs_sb;
997                 void                    *generic_sbp;
998         } u;
999         /*
1000 diff --new-file -ur linux-2.4.20/include/linux/squashfs_fs.h linux/include/linux/squashfs_fs.h
1001 --- linux-2.4.20/include/linux/squashfs_fs.h    Thu Jan  1 01:00:00 1970
1002 +++ linux/include/linux/squashfs_fs.h   Thu Jan  9 03:50:51 2003
1003 @@ -0,0 +1,304 @@
1004 +#ifndef SQUASHFS_FS
1005 +#define SQUASHFS_FS
1006 +/*
1007 + * Squashfs
1008 + *
1009 + * Copyright (c) 2002 Phillip Lougher <phillip@lougher.demon.co.uk>
1010 + *
1011 + * This program is free software; you can redistribute it and/or
1012 + * modify it under the terms of the GNU General Public License
1013 + * as published by the Free Software Foundation; either version
1014 + * 2 of the License, or (at your option) any later version.
1015 + *
1016 + * squashfs_fs.h
1017 + */
1018 +
1019 +#define SQUASHFS_MAJOR                 1
1020 +#define SQUASHFS_MINOR                 0
1021 +#define SQUASHFS_MAGIC                 0x73717368
1022 +#define SQUASHFS_MAGIC_SWAP            0x68737173
1023 +#define SQUASHFS_START                 0
1024 +
1025 +/* size of metadata (inode and directory) blocks */
1026 +#define SQUASHFS_METADATA_SIZE         8192
1027 +#define SQUASHFS_METADATA_LOG          13
1028 +
1029 +/* default size of data blocks */
1030 +#define SQUASHFS_FILE_SIZE             32768
1031 +#define SQUASHFS_FILE_LOG              15
1032 +
1033 +#define SQUASHFS_FILE_MAX_SIZE         32768
1034 +
1035 +/* Max number of uids and gids */
1036 +#define SQUASHFS_UIDS                  48
1037 +#define SQUASHFS_GUIDS                 15
1038 +
1039 +/* Max length of filename (not 255) */
1040 +#define SQUASHFS_NAME_LEN              256
1041 +
1042 +#define SQUASHFS_INVALID               ((long long) 0xffffffffffff)
1043 +#define SQUASHFS_INVALID_BLK           ((long long) 0xffffffff)
1044 +#define SQUASHFS_USED_BLK              ((long long) 0xfffffffe)
1045 +
1046 +/* Filesystem flags */
1047 +#define SQUASHFS_NOI                   1
1048 +#define SQUASHFS_NOD                   2
1049 +#define SQUASHFS_CHECK                 4
1050 +#define SQUASHFS_UNCOMPRESSED_INODES(flags)    (flags & SQUASHFS_NOI)
1051 +#define SQUASHFS_UNCOMPRESSED_DATA(flags)      (flags & SQUASHFS_NOD)
1052 +#define SQUASHFS_CHECK_DATA(flags)             (flags & SQUASHFS_CHECK)
1053 +#define SQUASHFS_MKFLAGS(noi, nod, check_data) (noi | (nod << 1) | (check_data << 2))
1054 +
1055 +/* Max number of types and file types */
1056 +#define SQUASHFS_TYPES                 5
1057 +#define SQUASHFS_DIR_TYPE              1
1058 +#define SQUASHFS_FILE_TYPE             2
1059 +#define SQUASHFS_SYMLINK_TYPE          3
1060 +#define SQUASHFS_BLKDEV_TYPE           4
1061 +#define SQUASHFS_CHRDEV_TYPE           5
1062 +
1063 +/* Flag whether block is compressed or uncompressed, bit is set if block is uncompressed */
1064 +#define SQUASHFS_COMPRESSED_BIT                (1 << 15)
1065 +#define SQUASHFS_COMPRESSED_SIZE(B)    (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
1066 +                                       (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
1067 +
1068 +#define SQUASHFS_COMPRESSED(B)         (!((B) & SQUASHFS_COMPRESSED_BIT))
1069 +
1070 +/*
1071 + * Inode number ops.  Inodes consist of a compressed block number, and an uncompressed
1072 + * offset within that block
1073 + */
1074 +#define SQUASHFS_INODE_BLK(a)          ((unsigned int) ((a) >> 16))
1075 +#define SQUASHFS_INODE_OFFSET(a)       ((unsigned int) ((a) & 0xffff))
1076 +#define SQUASHFS_MKINODE(A, B)         ((squashfs_inode)(((squashfs_inode) (A) << 16)\
1077 +                                       + (B)))
1078 +
1079 +/* Compute 32 bit VFS inode number from squashfs inode number */
1080 +#define SQUASHFS_MK_VFS_INODE(a, b)    ((unsigned int) (((a) << 8) + ((b) >> 2) + 1))
1081 +
1082 +/* Translate between VFS mode and squashfs mode */
1083 +#define SQUASHFS_MODE(a)               ((a) & 0xfff)
1084 +
1085 +/* cached data constants for filesystem */
1086 +#define SQUASHFS_CACHED_BLKS           8
1087 +
1088 +#define SQUASHFS_MAX_FILE_SIZE_LOG     32
1089 +#define SQUASHFS_MAX_FILE_SIZE         ((long long) 1 << SQUASHFS_MAX_FILE_SIZE_LOG - 1)
1090 +
1091 +#define SQUASHFS_MARKER_BYTE           0xff
1092 +
1093 +/*
1094 + * definitions for structures on disk
1095 + */
1096 +
1097 +typedef unsigned int           squashfs_block;
1098 +typedef long long              squashfs_inode;
1099 +
1100 +typedef unsigned int           squashfs_uid;
1101 +
1102 +typedef struct squashfs_super_block {
1103 +       unsigned int            s_magic __attribute__ ((packed));
1104 +       unsigned int            inodes __attribute__ ((packed));
1105 +       unsigned int            bytes_used __attribute__ ((packed));
1106 +       unsigned int            uid_start __attribute__ ((packed));
1107 +       unsigned int            guid_start __attribute__ ((packed));
1108 +       unsigned int            inode_table_start __attribute__ ((packed));
1109 +       unsigned int            directory_table_start __attribute__ ((packed));
1110 +       unsigned int            s_major:16 __attribute__ ((packed));
1111 +       unsigned int            s_minor:16 __attribute__ ((packed));
1112 +       unsigned int            block_size:16 __attribute__ ((packed));
1113 +       unsigned int            block_log:16 __attribute__ ((packed));
1114 +       unsigned int            flags:8 __attribute__ ((packed));
1115 +       unsigned int            no_uids:8 __attribute__ ((packed));
1116 +       unsigned int            no_guids:8 __attribute__ ((packed));
1117 +       time_t                  mkfs_time /* time of filesystem creation */ __attribute__ ((packed));
1118 +       squashfs_inode          root_inode __attribute__ ((packed));
1119 +} squashfs_super_block;
1120 +
1121 +typedef struct {
1122 +       unsigned int            inode_type:4 __attribute__ ((packed));
1123 +       unsigned int            mode:12 __attribute__ ((packed)); /* protection */
1124 +       unsigned int            uid:4 __attribute__ ((packed)); /* index into uid table */
1125 +       unsigned int            guid:4 __attribute__ ((packed)); /* index into guid table */
1126 +} squashfs_base_inode_header;
1127 +
1128 +typedef struct {
1129 +       unsigned int            inode_type:4 __attribute__ ((packed));
1130 +       unsigned int            mode:12 __attribute__ ((packed)); /* protection */
1131 +       unsigned int            uid:4 __attribute__ ((packed)); /* index into uid table */
1132 +       unsigned int            guid:4 __attribute__ ((packed)); /* index into guid table */
1133 +       unsigned short          rdev __attribute__ ((packed));
1134 +} squashfs_dev_inode_header;
1135 +       
1136 +typedef struct {
1137 +       unsigned int            inode_type:4 __attribute__ ((packed));
1138 +       unsigned int            mode:12 __attribute__ ((packed)); /* protection */
1139 +       unsigned int            uid:4 __attribute__ ((packed)); /* index into uid table */
1140 +       unsigned int            guid:4 __attribute__ ((packed)); /* index into guid table */
1141 +       unsigned short          symlink_size __attribute__ ((packed));
1142 +       char                    symlink[0] __attribute__ ((packed));
1143 +} squashfs_symlink_inode_header;
1144 +
1145 +typedef struct {
1146 +       unsigned int            inode_type:4 __attribute__ ((packed));
1147 +       unsigned int            mode:12 __attribute__ ((packed)); /* protection */
1148 +       unsigned int            uid:4 __attribute__ ((packed)); /* index into uid table */
1149 +       unsigned int            guid:4 __attribute__ ((packed)); /* index into guid table */
1150 +       time_t                  mtime __attribute__ ((packed));
1151 +       squashfs_block          start_block __attribute__ ((packed));
1152 +       unsigned int            file_size:SQUASHFS_MAX_FILE_SIZE_LOG __attribute__ ((packed));
1153 +       unsigned short          block_list[0]  __attribute__ ((packed));
1154 +} squashfs_reg_inode_header;
1155 +
1156 +typedef struct {
1157 +       unsigned int            inode_type:4 __attribute__ ((packed));
1158 +       unsigned int            mode:12 __attribute__ ((packed)); /* protection */
1159 +       unsigned int            uid:4 __attribute__ ((packed)); /* index into uid table */
1160 +       unsigned int            guid:4 __attribute__ ((packed)); /* index into guid table */
1161 +       unsigned int            file_size:19 __attribute__ ((packed));
1162 +       unsigned int            offset:13 __attribute__ ((packed));
1163 +       time_t                  mtime __attribute__ ((packed));
1164 +       unsigned int            start_block:24 __attribute__ ((packed));
1165 +} squashfs_dir_inode_header;
1166 +
1167 +typedef union {
1168 +       squashfs_base_inode_header      base;
1169 +       squashfs_dev_inode_header       dev;
1170 +       squashfs_symlink_inode_header   symlink;
1171 +       squashfs_reg_inode_header       reg;
1172 +       squashfs_dir_inode_header       dir;
1173 +} squashfs_inode_header;
1174 +       
1175 +typedef struct {
1176 +       unsigned int            offset:13 __attribute__ ((packed));
1177 +       unsigned int            type:3 __attribute__ ((packed));
1178 +       unsigned int            size:8 __attribute__ ((packed));
1179 +       char                    name[0] __attribute__ ((packed));
1180 +} squashfs_dir_entry;
1181 +
1182 +typedef struct {
1183 +       unsigned int            count:8 __attribute__ ((packed));
1184 +       unsigned int            start_block:24 __attribute__ ((packed));
1185 +} squashfs_dir_header;
1186 +
1187 +
1188 +extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
1189 +extern int squashfs_uncompress_init(void);
1190 +extern int squashfs_uncompress_exit(void);
1191 +
1192 +/*
1193 + * macros to convert each packed bitfield structure from little endian to big
1194 + * endian and vice versa.  These are needed when creating or using a filesystem on a
1195 + * machine with different byte ordering to the target architecture.
1196 + *
1197 + */
1198 +
1199 +#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
1200 +       SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\
1201 +       SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
1202 +       SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
1203 +       SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\
1204 +       SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\
1205 +       SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\
1206 +       SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\
1207 +       SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\
1208 +       SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
1209 +       SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
1210 +       SQUASHFS_SWAP((s)->block_size, d, 256, 16);\
1211 +       SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
1212 +       SQUASHFS_SWAP((s)->flags, d, 288, 8);\
1213 +       SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
1214 +       SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
1215 +       SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
1216 +       SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
1217 +}
1218 +
1219 +#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
1220 +       SQUASHFS_MEMSET(s, d, n);\
1221 +       SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
1222 +       SQUASHFS_SWAP((s)->mode, d, 4, 12);\
1223 +       SQUASHFS_SWAP((s)->uid, d, 16, 4);\
1224 +       SQUASHFS_SWAP((s)->guid, d, 20, 4);\
1225 +}
1226 +
1227 +#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
1228 +       SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dev_inode_header));\
1229 +       SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
1230 +}
1231 +
1232 +#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
1233 +       SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header));\
1234 +       SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
1235 +}
1236 +
1237 +#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
1238 +       SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header));\
1239 +       SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
1240 +       SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
1241 +       SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\
1242 +}
1243 +
1244 +#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
1245 +       SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header));\
1246 +       SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
1247 +       SQUASHFS_SWAP((s)->offset, d, 43, 13);\
1248 +       SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
1249 +       SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
1250 +}
1251 +
1252 +#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
1253 +       SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\
1254 +       SQUASHFS_SWAP((s)->count, d, 0, 8);\
1255 +       SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
1256 +}
1257 +
1258 +#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
1259 +       SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\
1260 +       SQUASHFS_SWAP((s)->offset, d, 0, 13);\
1261 +       SQUASHFS_SWAP((s)->type, d, 13, 3);\
1262 +       SQUASHFS_SWAP((s)->size, d, 16, 8);\
1263 +}
1264 +
1265 +#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
1266 +       int entry;\
1267 +       int bit_position;\
1268 +       SQUASHFS_MEMSET(s, d, n * 2);\
1269 +       for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 16)\
1270 +               SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
1271 +}
1272 +
1273 +#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
1274 +       int entry;\
1275 +       int bit_position;\
1276 +       SQUASHFS_MEMSET(s, d, n * bits / 8);\
1277 +       for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += bits)\
1278 +               SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
1279 +}
1280 +
1281 +#ifdef __KERNEL__
1282 +/*
1283 + * macros used to swap each structure entry, taking into account
1284 + * bitfields and different bitfield placing conventions on differing architectures
1285 + */
1286 +#include <asm/byteorder.h>
1287 +#ifdef __BIG_ENDIAN
1288 +       /* convert from little endian to big endian */
1289 +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos)
1290 +#else
1291 +       /* convert from big endian to little endian */ 
1292 +#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos)
1293 +#endif
1294 +
1295 +#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
1296 +       int bits;\
1297 +       int b_pos = pos % 8;\
1298 +       unsigned long long val = 0;\
1299 +       unsigned char *s = (unsigned char *)p + (pos / 8);\
1300 +       unsigned char *d = ((unsigned char *) &val) + 7;\
1301 +       for(bits = 0; bits < (tbits + b_pos); bits += 8) \
1302 +               *d-- = *s++;\
1303 +       value = val >> (SHIFT);\
1304 +}
1305 +#define SQUASHFS_MEMSET(s, d, n)       memset(s, 0, n);
1306 +#endif
1307 +#endif
1308 diff --new-file -ur linux-2.4.20/include/linux/squashfs_fs_i.h linux/include/linux/squashfs_fs_i.h
1309 --- linux-2.4.20/include/linux/squashfs_fs_i.h  Thu Jan  1 01:00:00 1970
1310 +++ linux/include/linux/squashfs_fs_i.h Sun Dec  1 05:40:22 2002
1311 @@ -0,0 +1,21 @@
1312 +#ifndef SQUASHFS_FS_I
1313 +#define SQUASHFS_FS_I
1314 +/*
1315 + * Squashfs
1316 + *
1317 + * Copyright (c) 2002 Phillip Lougher <phillip@lougher.demon.co.uk>
1318 + *
1319 + * This program is free software; you can redistribute it and/or
1320 + * modify it under the terms of the GNU General Public License
1321 + * as published by the Free Software Foundation; either version
1322 + * 2 of the License, or (at your option) any later version.
1323 + *
1324 + * squashfs_fs_i.h
1325 + */
1326 +
1327 +typedef struct squashfs_inode_info {
1328 +       unsigned int    start_block;
1329 +       unsigned int    block_list_start;
1330 +       unsigned int    offset;
1331 +       } squashfs_inode_info;
1332 +#endif
1333 diff --new-file -ur linux-2.4.20/include/linux/squashfs_fs_sb.h linux/include/linux/squashfs_fs_sb.h
1334 --- linux-2.4.20/include/linux/squashfs_fs_sb.h Thu Jan  1 01:00:00 1970
1335 +++ linux/include/linux/squashfs_fs_sb.h        Thu Jan  9 03:50:51 2003
1336 @@ -0,0 +1,41 @@
1337 +#ifndef SQUASHFS_FS_SB
1338 +#define SQUASHFS_FS_SB
1339 +/*
1340 + * Squashfs
1341 + *
1342 + * Copyright (c) 2002 Phillip Lougher <phillip@lougher.demon.co.uk>
1343 + *
1344 + * This program is free software; you can redistribute it and/or
1345 + * modify it under the terms of the GNU General Public License
1346 + * as published by the Free Software Foundation; either version
1347 + * 2 of the License, or (at your option) any later version.
1348 + *
1349 + * squashfs_fs_sb.h
1350 + */
1351 +
1352 +#include <linux/squashfs_fs.h>
1353 +
1354 +typedef struct {
1355 +       unsigned int    block;
1356 +       int             length;
1357 +       unsigned int    next_index;
1358 +       char            *data;
1359 +       } squashfs_cache;
1360 +
1361 +typedef struct squashfs_sb_info {
1362 +       squashfs_super_block    sBlk;
1363 +       int                     devblksize;
1364 +       int                     devblksize_log2;
1365 +       int                     swap;
1366 +       squashfs_cache          *block_cache;
1367 +       int                     next_cache;
1368 +       squashfs_uid            *uid;
1369 +       squashfs_uid            *guid;
1370 +       unsigned int            read_size;
1371 +       char                    *read_data;
1372 +       char                    *read_page;
1373 +       struct semaphore        read_page_mutex;
1374 +       struct semaphore        block_cache_mutex;
1375 +       wait_queue_head_t       waitq;
1376 +       } squashfs_sb_info;
1377 +#endif
1378 diff --new-file -ur linux-2.4.20/init/do_mounts.c linux/init/do_mounts.c
1379 --- linux-2.4.20/init/do_mounts.c       Thu Nov 28 23:53:15 2002
1380 +++ linux/init/do_mounts.c      Sun Dec  1 05:40:22 2002
1381 @@ -15,6 +15,7 @@
1382  #include <linux/minix_fs.h>
1383  #include <linux/ext2_fs.h>
1384  #include <linux/romfs_fs.h>
1385 +#include <linux/squashfs_fs.h>
1386  
1387  #define BUILD_CRAMDISK
1388  
1389 @@ -460,6 +461,7 @@
1390   *     ext2
1391   *     romfs
1392   *     gzip
1393 + *     squashfs
1394   */
1395  static int __init 
1396  identify_ramdisk_image(int fd, int start_block)
1397 @@ -468,6 +470,7 @@
1398         struct minix_super_block *minixsb;
1399         struct ext2_super_block *ext2sb;
1400         struct romfs_super_block *romfsb;
1401 +       struct squashfs_super_block *squashfsb;
1402         int nblocks = -1;
1403         unsigned char *buf;
1404  
1405 @@ -478,6 +481,7 @@
1406         minixsb = (struct minix_super_block *) buf;
1407         ext2sb = (struct ext2_super_block *) buf;
1408         romfsb = (struct romfs_super_block *) buf;
1409 +       squashfsb = (struct squashfs_super_block *) buf;
1410         memset(buf, 0xe5, size);
1411  
1412         /*
1413 @@ -507,6 +511,15 @@
1414                 goto done;
1415         }
1416  
1417 +       /* squashfs is at block zero too */
1418 +       if (squashfsb->s_magic == SQUASHFS_MAGIC) {
1419 +               printk(KERN_NOTICE
1420 +                      "RAMDISK: squashfs filesystem found at block %d\n",
1421 +                      start_block);
1422 +               nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
1423 +               goto done;
1424 +       }
1425 +
1426         /*
1427          * Read block 1 to test for minix and ext2 superblock
1428          */
This page took 0.191597 seconds and 3 git commands to generate.