]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.20-squashfs.patch
- obsolete
[packages/kernel.git] / linux-2.4.20-squashfs.patch
CommitLineData
cebf26ce 1diff --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
12diff --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 @@
cebf26ce 16 subdir-$(CONFIG_BEFS_FS) += befs
17 subdir-$(CONFIG_JFS_FS) += jfs
18c61c3d 18 subdir-$(CONFIG_XFS_FS) += xfs
cebf26ce 19+subdir-$(CONFIG_SQUASHFS) += squashfs
20
21
22 obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
23diff --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
38diff --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
b8c6f81c 40+++ linux/fs/squashfs/inode.c Tue Jan 14 04:44:35 2003
41@@ -0,0 +1,923 @@
cebf26ce 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>
bbb09630 67+#include <linux/zlib.h>
cebf26ce 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;
85c7054c 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)) {
cebf26ce 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+
cebf26ce 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;
b8c6f81c 719+ int byte_offset = 0;
cebf26ce 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);
b8c6f81c 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+ }
cebf26ce 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+
85c7054c 943+ if(!(stream.workspace = (char *) vmalloc(zlib_inflate_workspacesize()))) {
cebf26ce 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");
965diff --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
b8c6f81c 967+++ linux/include/linux/fs.h Thu Jan 9 03:50:56 2003
cebf26ce 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 @@
7f381142
JR
977 struct hostfs_inode_info hostfs_i;
978 struct hppfs_inode_info hppfs_i;
979 struct jffs2_inode_info jffs2_i;
cebf26ce 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 /*
1000diff --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
b8c6f81c 1002+++ linux/include/linux/squashfs_fs.h Thu Jan 9 03:50:51 2003
cebf26ce 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
1308diff --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
1333diff --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
b8c6f81c 1335+++ linux/include/linux/squashfs_fs_sb.h Thu Jan 9 03:50:51 2003
cebf26ce 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
1378diff --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;
85c7054c 1415 }
cebf26ce 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.39359 seconds and 4 git commands to generate.