[PATCH][2/2] SquashFS

From: Phillip Lougher
Date: Mon Mar 14 2005 - 12:53:46 EST


diff --new-file -urp linux-2.6.11.3/fs/Kconfig linux-2.6.11.3-squashfs/fs/Kconfig
--- linux-2.6.11.3/fs/Kconfig 2005-03-13 06:44:28.000000000 +0000
+++ linux-2.6.11.3-squashfs/fs/Kconfig 2005-03-14 00:53:28.011572040 +0000
@@ -1170,6 +1170,45 @@ config CRAMFS

If unsure, say N.

+config SQUASHFS
+ tristate "SquashFS 2.1 - Squashed file system support"
+ select ZLIB_INFLATE
+ help
+ Saying Y here includes support for SquashFS 2.1 (Compressed Read-Only
+ File System). SquashFS is a highly compressed read-only filesystem
+ for Linux. It uses zlib compression to compress both files, inodes
+ and directories. Inodes in the system are very small and all blocks
+ are packed to minimise data overhead. Block sizes greater than 4K are
+ supported up to a maximum of 64K.
+
+ SquashFS is intended for general read-only filesystem use, for
+ archival use (i.e. in cases where a .tar.gz file may be used), and in
+ embedded systems where low overhead is needed. Further information
+ and filesystem tools are available from
+ http://squashfs.sourceforge.net.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt>. The module
+ will be called squashfs. Note that the root file system (the one
+ containing the directory /) cannot be compiled as a module.
+
+ If unsure, say N.
+
+config SQUASHFS_1_0_COMPATIBILITY
+ bool "Include support for mounting SquashFS 1.x filesystems"
+ depends on SQUASHFS
+ default n
+ help
+ Saying Y here will include support for mounting SquashFS 1.x
+ filesystems. SquashFS 1.x filesystems were generated by earlier
+ versions of SquashFS, but there are quite a few systems around
+ which still use them. If you're going to be mounting
+ third party generated SquashFS filesystems and if you're
+ not sure the filesystems are 2.x, then say it's okay to say Y here.
+
+ If unsure, say N.
+
config VXFS_FS
tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
help
diff --new-file -urp linux-2.6.11.3/fs/Makefile linux-2.6.11.3-squashfs/fs/Makefile
--- linux-2.6.11.3/fs/Makefile 2005-03-13 06:44:28.000000000 +0000
+++ linux-2.6.11.3-squashfs/fs/Makefile 2005-03-14 00:53:28.017571128 +0000
@@ -52,6 +52,7 @@ obj-$(CONFIG_EXT3_FS) += ext3/ # Before
obj-$(CONFIG_JBD) += jbd/
obj-$(CONFIG_EXT2_FS) += ext2/
obj-$(CONFIG_CRAMFS) += cramfs/
+obj-$(CONFIG_SQUASHFS) += squashfs/
obj-$(CONFIG_RAMFS) += ramfs/
obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
obj-$(CONFIG_CODA_FS) += coda/
diff --new-file -urp linux-2.6.11.3/fs/squashfs/Makefile linux-2.6.11.3-squashfs/fs/squashfs/Makefile
--- linux-2.6.11.3/fs/squashfs/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.3-squashfs/fs/squashfs/Makefile 2005-03-14 00:53:28.043567176 +0000
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux squashfs routines.
+#
+
+obj-$(CONFIG_SQUASHFS) += squashfs.o
+
+squashfs-y := inode.o
+
+squashfs-$(CONFIG_SQUASHFS_1_0_COMPATIBILITY) += squashfs1_0.o
diff --new-file -urp linux-2.6.11.3/fs/squashfs/squashfs1_0.c linux-2.6.11.3-squashfs/fs/squashfs/squashfs1_0.c
--- linux-2.6.11.3/fs/squashfs/squashfs1_0.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.3-squashfs/fs/squashfs/squashfs1_0.c 2005-03-14 00:53:28.052565808 +0000
@@ -0,0 +1,439 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005
+ * Phillip Lougher <phillip@xxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs1_0.c
+ */
+#include <linux/types.h>
+#include <linux/squashfs_fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/squashfs_fs_sb.h>
+#include <linux/squashfs_fs_i.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/init.h>
+#include <linux/dcache.h>
+#include <asm/uaccess.h>
+#include <linux/wait.h>
+#include <asm/semaphore.h>
+#include <linux/zlib.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+#include "squashfs.h"
+
+static int squashfs_readpage_lessthan4K(struct file *file, struct page *page);
+static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode
+ inode);
+static unsigned int read_blocklist_1(struct inode *inode, int index, int
+ readahead_blks, char *block_list,
+ unsigned short **block_p, unsigned int *bsize);
+
+static struct address_space_operations squashfs_aops_lessthan4K = {
+ .readpage = squashfs_readpage_lessthan4K
+};
+
+int squashfs_1_0_supported(squashfs_sb_info *msBlk)
+{
+ msBlk->iget = squashfs_iget_1;
+ msBlk->read_blocklist = read_blocklist_1;
+ msBlk->sBlk.block_size = msBlk->sBlk.block_size_1;
+
+ return 1;
+}
+
+#define SIZE 256
+static int squashfs_readpage_lessthan4K(struct file *file, struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info;
+ squashfs_super_block *sBlk = &msBlk->sBlk;
+ unsigned char block_list[SIZE];
+ unsigned short *block_listp, block, bytes = 0;
+ int index = page->index << (PAGE_CACHE_SHIFT - sBlk->block_log);
+ int file_blocks = ((inode->i_size - 1) >> sBlk->block_log) + 1;
+ int readahead_blks = 1 << (PAGE_CACHE_SHIFT - sBlk->block_log);
+ void *pageaddr = kmap(page);
+
+ int i_end = index + (1 << (PAGE_CACHE_SHIFT - sBlk->block_log));
+ int byte;
+
+ TRACE("Entered squashfs_readpage_lessthan4K, page index %x, start "
+ "block %x\n", (unsigned int)
+ page->index, SQUASHFS_I(inode)->
+ start_block);
+ block = read_blocklist_1(inode, index, readahead_blks, block_list,
+ &block_listp, NULL);
+ if (i_end > file_blocks)
+ i_end = file_blocks;
+
+ while (index < i_end) {
+ int c_byte = !SQUASHFS_COMPRESSED(*block_listp) ?
+ SQUASHFS_COMPRESSED_SIZE(*block_listp) |
+ SQUASHFS_COMPRESSED_BIT_BLOCK :
+ *block_listp;
+
+ if (!(byte = squashfs_read_data(inode->i_sb, pageaddr, block,
+ c_byte, NULL))) {
+ ERROR("Unable to read page, block %x, size %x\n", block,
+ *block_listp);
+ goto skip_read;
+ }
+ block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
+ pageaddr += byte;
+ bytes += byte;
+ index ++;
+ block_listp ++;
+ }
+skip_read:
+ memset(pageaddr, 0, PAGE_CACHE_SIZE - bytes);
+ kunmap(page);
+ flush_dcache_page(page);
+ SetPageUptodate(page);
+ unlock_page(page);
+ return 0;
+}
+
+
+static unsigned int read_blocklist_1(struct inode *inode, int index, int
+ readahead_blks, char *block_list,
+ unsigned short **block_p, unsigned int *bsize)
+{
+ squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info;
+ unsigned short *block_listp;
+ int i = 0;
+ int block_ptr = SQUASHFS_I(inode)->block_list_start;
+ int offset = SQUASHFS_I(inode)->offset;
+ unsigned int block = SQUASHFS_I(inode)->start_block;
+
+ for (;;) {
+ int blocks = (index + readahead_blks - i);
+
+ if (blocks > (SIZE >> 1)) {
+ if ((index - i) <= (SIZE >> 1))
+ blocks = index - i;
+ else
+ blocks = SIZE >> 1;
+ }
+
+ if (msBlk->swap) {
+ unsigned char sblock_list[SIZE];
+
+ if (!squashfs_get_cached_block(inode->i_sb, (char *)
+ sblock_list, block_ptr, offset,
+ blocks << 1, &block_ptr, &offset)) {
+ ERROR("Unable to read block list [%d:%x]\n",
+ block_ptr, offset);
+ return 0;
+ }
+ SQUASHFS_SWAP_SHORTS(((unsigned short *)block_list),
+ ((unsigned short *)sblock_list),
+ blocks);
+ } else
+ if (!squashfs_get_cached_block(inode->i_sb, (char *)
+ block_list, block_ptr, offset,
+ blocks << 1, &block_ptr, &offset)) {
+ ERROR("Unable to read block list [%d:%x]\n",
+ block_ptr, offset);
+ return 0;
+ }
+
+ for (block_listp = (unsigned short *) block_list; i < index &&
+ blocks; i ++, block_listp ++, blocks --)
+ block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
+ if (blocks >= readahead_blks)
+ break;
+ }
+ if (bsize)
+ *bsize = SQUASHFS_COMPRESSED_SIZE(*block_listp) |
+ (!SQUASHFS_COMPRESSED(*block_listp) ?
+ SQUASHFS_COMPRESSED_BIT_BLOCK : 0);
+ else
+ *block_p = block_listp;
+ return block;
+}
+
+
+static struct inode *squashfs_new_inode(struct super_block *s,
+ squashfs_base_inode_header_1 *inodeb, unsigned int ino)
+{
+ squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+ squashfs_super_block *sBlk = &msBlk->sBlk;
+ struct inode *i = new_inode(s);
+
+ if (i) {
+ i->i_ino = ino;
+ i->i_nlink = 1;
+ i->i_mtime.tv_sec = sBlk->mkfs_time;
+ i->i_atime.tv_sec = sBlk->mkfs_time;
+ i->i_ctime.tv_sec = sBlk->mkfs_time;
+ i->i_mode = inodeb->mode;
+ i->i_size = 0;
+ if (inodeb->inode_type != SQUASHFS_IPC_TYPE)
+ i->i_uid = msBlk->uid[((inodeb->inode_type - 1) /
+ SQUASHFS_TYPES) * 16 + inodeb->uid];
+ }
+
+ return i;
+}
+
+static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode
+inode)
+{
+ struct inode *i;
+ squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+ squashfs_super_block *sBlk = &msBlk->sBlk;
+ unsigned int block = SQUASHFS_INODE_BLK(inode) +
+ sBlk->inode_table_start;
+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+ unsigned int ino = SQUASHFS_MK_VFS_INODE(block -
+ sBlk->inode_table_start, offset);
+ unsigned int next_block, next_offset;
+ squashfs_base_inode_header_1 inodeb;
+
+ TRACE("Entered squashfs_iget_1\n");
+
+ if (msBlk->swap) {
+ squashfs_base_inode_header_1 sinodeb;
+
+ if (!squashfs_get_cached_block(s, (char *) &sinodeb, block,
+ offset, sizeof(sinodeb),
+ &next_block, &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_BASE_INODE_HEADER_1(&inodeb, &sinodeb,
+ sizeof(sinodeb));
+ } else
+ if (!squashfs_get_cached_block(s, (char *) &inodeb, block,
+ offset, sizeof(inodeb),
+ &next_block, &next_offset))
+ goto failed_read;
+
+ switch(inodeb.inode_type == SQUASHFS_IPC_TYPE ? SQUASHFS_IPC_TYPE :
+ (inodeb.inode_type - 1) % SQUASHFS_TYPES + 1) {
+ case SQUASHFS_FILE_TYPE: {
+ squashfs_reg_inode_header_1 inodep;
+
+ if (msBlk->swap) {
+ squashfs_reg_inode_header_1 sinodep;
+
+ if (!squashfs_get_cached_block(s, (char *)
+ &sinodep, block, offset,
+ sizeof(sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_REG_INODE_HEADER_1(&inodep,
+ &sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ &inodep, block, offset,
+ sizeof(inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if ((i = squashfs_new_inode(s, &inodeb, ino)) == NULL)
+ goto failed_read1;
+ i->i_size = inodep.file_size;
+ i->i_fop = &generic_ro_fops;
+ i->i_mode |= S_IFREG;
+ i->i_mtime.tv_sec = inodep.mtime;
+ i->i_atime.tv_sec = inodep.mtime;
+ i->i_ctime.tv_sec = inodep.mtime;
+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+ i->i_blksize = PAGE_CACHE_SIZE;
+ SQUASHFS_I(i)->u.s1.fragment_start_block =
+ SQUASHFS_INVALID_BLK;
+ SQUASHFS_I(i)->u.s1.fragment_offset = 0;
+ SQUASHFS_I(i)->start_block = inodep.start_block;
+ SQUASHFS_I(i)->block_list_start = next_block;
+ SQUASHFS_I(i)->offset = next_offset;
+ if (sBlk->block_size > 4096)
+ i->i_data.a_ops = &squashfs_aops;
+ else if (sBlk->block_size == 4096)
+ i->i_data.a_ops = &squashfs_aops_4K;
+ else
+ i->i_data.a_ops = &squashfs_aops_lessthan4K;
+
+ TRACE("File inode %x:%x, start_block %x, "
+ "block_list_start %x, offset %x\n",
+ SQUASHFS_INODE_BLK(inode), offset,
+ inodep.start_block, next_block,
+ next_offset);
+ break;
+ }
+ case SQUASHFS_DIR_TYPE: {
+ squashfs_dir_inode_header_1 inodep;
+
+ if (msBlk->swap) {
+ squashfs_dir_inode_header_1 sinodep;
+
+ if (!squashfs_get_cached_block(s, (char *)
+ &sinodep, block, offset,
+ sizeof(sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_DIR_INODE_HEADER_1(&inodep,
+ &sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ &inodep, block, offset,
+ sizeof(inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if ((i = squashfs_new_inode(s, &inodeb, ino)) == NULL)
+ goto failed_read1;
+ i->i_size = inodep.file_size;
+ i->i_op = &squashfs_dir_inode_ops;
+ i->i_fop = &squashfs_dir_ops;
+ i->i_mode |= S_IFDIR;
+ i->i_mtime.tv_sec = inodep.mtime;
+ i->i_atime.tv_sec = inodep.mtime;
+ i->i_ctime.tv_sec = inodep.mtime;
+ SQUASHFS_I(i)->start_block = inodep.start_block;
+ SQUASHFS_I(i)->offset = inodep.offset;
+ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
+
+ TRACE("Directory inode %x:%x, start_block %x, offset "
+ "%x\n", SQUASHFS_INODE_BLK(inode),
+ offset, inodep.start_block,
+ inodep.offset);
+ break;
+ }
+ case SQUASHFS_SYMLINK_TYPE: {
+ squashfs_symlink_inode_header_1 inodep;
+
+ if (msBlk->swap) {
+ squashfs_symlink_inode_header_1 sinodep;
+
+ if (!squashfs_get_cached_block(s, (char *)
+ &sinodep, block, offset,
+ sizeof(sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(&inodep,
+ &sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ &inodep, block, offset,
+ sizeof(inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if ((i = squashfs_new_inode(s, &inodeb, ino)) == NULL)
+ goto failed_read1;
+ i->i_size = inodep.symlink_size;
+ i->i_op = &page_symlink_inode_operations;
+ i->i_data.a_ops = &squashfs_symlink_aops;
+ i->i_mode |= S_IFLNK;
+ SQUASHFS_I(i)->start_block = next_block;
+ SQUASHFS_I(i)->offset = next_offset;
+
+ TRACE("Symbolic link inode %x:%x, start_block %x, "
+ "offset %x\n",
+ SQUASHFS_INODE_BLK(inode),
+ offset, next_block,
+ next_offset);
+ break;
+ }
+ case SQUASHFS_BLKDEV_TYPE:
+ case SQUASHFS_CHRDEV_TYPE: {
+ squashfs_dev_inode_header_1 inodep;
+
+ if (msBlk->swap) {
+ squashfs_dev_inode_header_1 sinodep;
+
+ if (!squashfs_get_cached_block(s, (char *)
+ &sinodep, block, offset,
+ sizeof(sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_DEV_INODE_HEADER_1(&inodep,
+ &sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ &inodep, block, offset,
+ sizeof(inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if ((i = squashfs_new_inode(s, &inodeb, ino)) == NULL)
+ goto failed_read1;
+ i->i_mode |= (inodeb.inode_type ==
+ SQUASHFS_CHRDEV_TYPE) ?
+ S_IFCHR : S_IFBLK;
+ init_special_inode(i, i->i_mode,
+ old_decode_dev(inodep.rdev));
+
+ TRACE("Device inode %x:%x, rdev %x\n",
+ SQUASHFS_INODE_BLK(inode),
+ offset, inodep.rdev);
+ break;
+ }
+ case SQUASHFS_IPC_TYPE: {
+ squashfs_ipc_inode_header_1 inodep;
+
+ if (msBlk->swap) {
+ squashfs_ipc_inode_header_1 sinodep;
+
+ if (!squashfs_get_cached_block(s, (char *)
+ &sinodep, block, offset,
+ sizeof(sinodep), &next_block,
+ &next_offset))
+ goto failed_read;
+ SQUASHFS_SWAP_IPC_INODE_HEADER_1(&inodep,
+ &sinodep);
+ } else
+ if (!squashfs_get_cached_block(s, (char *)
+ &inodep, block, offset,
+ sizeof(inodep), &next_block,
+ &next_offset))
+ goto failed_read;
+
+ if ((i = squashfs_new_inode(s, &inodeb, ino)) == NULL)
+ goto failed_read1;
+ i->i_mode |= (inodep.type == SQUASHFS_FIFO_TYPE) ?
+ S_IFIFO : S_IFSOCK;
+ i->i_uid = msBlk->uid[inodep.offset * 16 + inodeb.uid];
+ init_special_inode(i, i->i_mode, 0);
+ break;
+ }
+ default:
+ ERROR("Unknown inode type %d in squashfs_iget!\n",
+ inodeb.inode_type);
+ goto failed_read1;
+ }
+
+ if (inodeb.guid == 15)
+ i->i_gid = i->i_uid;
+ else
+ i->i_gid = msBlk->guid[inodeb.guid];
+
+ insert_inode_hash(i);
+ return i;
+
+failed_read:
+ ERROR("Unable to read inode [%x:%x]\n", block, offset);
+
+failed_read1:
+ return NULL;
+}
diff --new-file -urp linux-2.6.11.3/fs/squashfs/squashfs.h linux-2.6.11.3-squashfs/fs/squashfs/squashfs.h
--- linux-2.6.11.3/fs/squashfs/squashfs.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.3-squashfs/fs/squashfs/squashfs.h 2005-03-14 00:53:28.058564896 +0000
@@ -0,0 +1,68 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005
+ * Phillip Lougher <phillip@xxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs.h
+ */
+
+
+#ifdef SQUASHFS_TRACE
+#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
+#else
+#define TRACE(s, args...) {}
+#endif
+
+#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
+
+#define SERROR(s, args...) do { \
+ if (!silent) \
+ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
+ } while(0)
+
+#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
+
+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
+ unsigned int index, unsigned int length,
+ unsigned int *next_index);
+extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
+ unsigned int block, unsigned int offset,
+ int length, unsigned int *next_block,
+ unsigned int *next_offset);
+
+extern struct address_space_operations squashfs_symlink_aops;
+extern struct address_space_operations squashfs_aops;
+extern struct address_space_operations squashfs_aops_4K;
+extern struct file_operations squashfs_dir_ops;
+extern struct inode_operations squashfs_dir_inode_ops;
+
+
+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
+{
+ return list_entry(inode, struct squashfs_inode_info, vfs_inode);
+}
+
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+extern int squashfs_1_0_supported(squashfs_sb_info *msBlk);
+#else
+static inline int squashfs_1_0_supported(squashfs_sb_info *msBlk)
+{
+ return 0;
+}
+#endif
diff --new-file -urp linux-2.6.11.3/include/linux/squashfs_fs.h linux-2.6.11.3-squashfs/include/linux/squashfs_fs.h
--- linux-2.6.11.3/include/linux/squashfs_fs.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.3-squashfs/include/linux/squashfs_fs.h 2005-03-14 00:53:28.068563376 +0000
@@ -0,0 +1,576 @@
+#ifndef SQUASHFS_FS
+#define SQUASHFS_FS
+
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005
+ * Phillip Lougher <phillip@xxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs.h
+ */
+
+#define SQUASHFS_MAJOR 2
+#define SQUASHFS_MINOR 1
+#define SQUASHFS_MAGIC 0x73717368
+#define SQUASHFS_MAGIC_SWAP 0x68737173
+#define SQUASHFS_START 0
+
+/* size of metadata (inode and directory) blocks */
+#define SQUASHFS_METADATA_SIZE 8192
+#define SQUASHFS_METADATA_LOG 13
+
+/* default size of data blocks */
+#define SQUASHFS_FILE_SIZE 65536
+#define SQUASHFS_FILE_LOG 16
+
+#define SQUASHFS_FILE_MAX_SIZE 65536
+
+/* Max number of uids and gids */
+#define SQUASHFS_UIDS 256
+#define SQUASHFS_GUIDS 255
+
+/* Max length of filename (not 255) */
+#define SQUASHFS_NAME_LEN 256
+
+#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
+#define SQUASHFS_INVALID_BLK ((long long) 0xffffffff)
+#define SQUASHFS_USED_BLK ((long long) 0xfffffffe)
+
+/* Filesystem flags */
+#define SQUASHFS_NOI 0
+#define SQUASHFS_NOD 1
+#define SQUASHFS_CHECK 2
+#define SQUASHFS_NOF 3
+#define SQUASHFS_NO_FRAG 4
+#define SQUASHFS_ALWAYS_FRAG 5
+#define SQUASHFS_DUPLICATE 6
+
+#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
+
+#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOI)
+
+#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOD)
+
+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NOF)
+
+#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_NO_FRAG)
+
+#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_ALWAYS_FRAG)
+
+#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_DUPLICATE)
+
+#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
+ SQUASHFS_CHECK)
+
+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
+ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \
+ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
+ (duplicate_checking << 6))
+
+/* Max number of types and file types */
+#define SQUASHFS_DIR_TYPE 1
+#define SQUASHFS_FILE_TYPE 2
+#define SQUASHFS_SYMLINK_TYPE 3
+#define SQUASHFS_BLKDEV_TYPE 4
+#define SQUASHFS_CHRDEV_TYPE 5
+#define SQUASHFS_FIFO_TYPE 6
+#define SQUASHFS_SOCKET_TYPE 7
+#define SQUASHFS_LDIR_TYPE 8
+
+/* 1.0 filesystem type definitions */
+#define SQUASHFS_TYPES 5
+#define SQUASHFS_IPC_TYPE 0
+
+/* Flag whether block is compressed or uncompressed, bit is set if block is
+ * uncompressed */
+#define SQUASHFS_COMPRESSED_BIT (1 << 15)
+
+#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
+ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
+
+#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
+
+#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
+
+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
+ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
+ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
+
+#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
+
+/*
+ * Inode number ops. Inodes consist of a compressed block number, and an
+ * uncompressed offset within that block
+ */
+#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
+
+#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
+
+#define SQUASHFS_MKINODE(A, B) ((squashfs_inode)(((squashfs_inode) (A)\
+ << 16) + (B)))
+
+/* Compute 32 bit VFS inode number from squashfs inode number */
+#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
+ ((b) >> 2) + 1))
+
+/* Translate between VFS mode and squashfs mode */
+#define SQUASHFS_MODE(a) ((a) & 0xfff)
+
+/* fragment and fragment table defines */
+typedef unsigned int squashfs_fragment_index;
+#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(squashfs_fragment_entry))
+
+#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
+ SQUASHFS_METADATA_SIZE - 1) / \
+ SQUASHFS_METADATA_SIZE)
+
+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
+ sizeof(squashfs_fragment_index))
+
+#define SQUASHFS_CACHED_FRAGMENTS 3
+
+/* cached data constants for filesystem */
+#define SQUASHFS_CACHED_BLKS 8
+
+#define SQUASHFS_MAX_FILE_SIZE_LOG 32
+
+#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
+ (SQUASHFS_MAX_FILE_SIZE_LOG - 1))
+
+#define SQUASHFS_MARKER_BYTE 0xff
+
+
+/*
+ * definitions for structures on disk
+ */
+
+typedef unsigned int squashfs_block;
+typedef long long squashfs_inode;
+
+typedef unsigned int squashfs_uid;
+
+typedef struct squashfs_super_block {
+ unsigned int s_magic;
+ unsigned int inodes;
+ unsigned int bytes_used;
+ unsigned int uid_start;
+ unsigned int guid_start;
+ unsigned int inode_table_start;
+ unsigned int directory_table_start;
+ unsigned int s_major:16;
+ unsigned int s_minor:16;
+ unsigned int block_size_1:16;
+ unsigned int block_log:16;
+ unsigned int flags:8;
+ unsigned int no_uids:8;
+ unsigned int no_guids:8;
+ unsigned int mkfs_time /* time of filesystem creation */;
+ squashfs_inode root_inode;
+ unsigned int block_size;
+ unsigned int fragments;
+ unsigned int fragment_table_start;
+} __attribute__ ((packed)) squashfs_super_block;
+
+typedef struct {
+ unsigned int index:27;
+ unsigned int start_block:29;
+ unsigned char size;
+ unsigned char name[0];
+} __attribute__ ((packed)) squashfs_dir_index;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+} __attribute__ ((packed)) squashfs_base_inode_header;
+
+typedef squashfs_base_inode_header squashfs_ipc_inode_header;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned short rdev;
+} __attribute__ ((packed)) squashfs_dev_inode_header;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned short symlink_size;
+ char symlink[0];
+} __attribute__ ((packed)) squashfs_symlink_inode_header;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int mtime;
+ squashfs_block start_block;
+ unsigned int fragment;
+ unsigned int offset;
+ unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+ unsigned short block_list[0];
+} __attribute__ ((packed)) squashfs_reg_inode_header;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int file_size:19;
+ unsigned int offset:13;
+ unsigned int mtime;
+ unsigned int start_block:24;
+} __attribute__ ((packed)) squashfs_dir_inode_header;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:8; /* index into uid table */
+ unsigned int guid:8; /* index into guid table */
+ unsigned int file_size:27;
+ unsigned int offset:13;
+ unsigned int mtime;
+ unsigned int start_block:24;
+ unsigned int i_count:16;
+ squashfs_dir_index index[0];
+} __attribute__ ((packed)) squashfs_ldir_inode_header;
+
+typedef union {
+ squashfs_base_inode_header base;
+ squashfs_dev_inode_header dev;
+ squashfs_symlink_inode_header symlink;
+ squashfs_reg_inode_header reg;
+ squashfs_dir_inode_header dir;
+ squashfs_ldir_inode_header ldir;
+ squashfs_ipc_inode_header ipc;
+} squashfs_inode_header;
+
+typedef struct {
+ unsigned int offset:13;
+ unsigned int type:3;
+ unsigned int size:8;
+ char name[0];
+} __attribute__ ((packed)) squashfs_dir_entry;
+
+typedef struct {
+ unsigned int count:8;
+ unsigned int start_block:24;
+} __attribute__ ((packed)) squashfs_dir_header;
+
+typedef struct {
+ unsigned int start_block;
+ unsigned int size;
+} __attribute__ ((packed)) squashfs_fragment_entry;
+
+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
+extern int squashfs_uncompress_init(void);
+extern int squashfs_uncompress_exit(void);
+
+/*
+ * macros to convert each packed bitfield structure from little endian to big
+ * endian and vice versa. These are needed when creating or using a filesystem
+ * on a machine with different byte ordering to the target architecture.
+ *
+ */
+
+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
+ SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\
+ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
+ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
+ SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\
+ SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\
+ SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\
+ SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\
+ SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\
+ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
+ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
+ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
+ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
+ SQUASHFS_SWAP((s)->flags, d, 288, 8);\
+ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
+ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
+ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
+ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
+ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
+ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
+ SQUASHFS_SWAP((s)->fragment_table_start, d, 472, 32);\
+}
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
+ SQUASHFS_MEMSET(s, d, n);\
+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) \
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ipc_inode_header))
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_dev_inode_header)); \
+ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_symlink_inode_header));\
+ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_reg_inode_header));\
+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
+ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
+ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_dir_inode_header));\
+ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
+ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
+ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
+}
+
+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_ldir_inode_header));\
+ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
+ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
+ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
+ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
+}
+
+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
+ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_index));\
+ SQUASHFS_SWAP((s)->index, d, 0, 27);\
+ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
+ SQUASHFS_SWAP((s)->size, d, 56, 8);\
+}
+
+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
+ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\
+ SQUASHFS_SWAP((s)->count, d, 0, 8);\
+ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
+}
+
+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
+ SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\
+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
+ SQUASHFS_SWAP((s)->type, d, 13, 3);\
+ SQUASHFS_SWAP((s)->size, d, 16, 8);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
+ SQUASHFS_MEMSET(s, d, sizeof(squashfs_fragment_entry));\
+ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
+ SQUASHFS_SWAP((s)->size, d, 32, 32);\
+}
+
+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
+ int entry;\
+ int bit_position;\
+ SQUASHFS_MEMSET(s, d, n * 2);\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 16)\
+ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
+}
+
+#define SQUASHFS_SWAP_INTS(s, d, n) {\
+ int entry;\
+ int bit_position;\
+ SQUASHFS_MEMSET(s, d, n * 4);\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ 32)\
+ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
+}
+
+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
+ int entry;\
+ int bit_position;\
+ SQUASHFS_MEMSET(s, d, n * bits / 8);\
+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
+ bits)\
+ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
+
+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:4; /* index into uid table */
+ unsigned int guid:4; /* index into guid table */
+} __attribute__ ((packed)) squashfs_base_inode_header_1;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:4; /* index into uid table */
+ unsigned int guid:4; /* index into guid table */
+ unsigned int type:4;
+ unsigned int offset:4;
+} __attribute__ ((packed)) squashfs_ipc_inode_header_1;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:4; /* index into uid table */
+ unsigned int guid:4; /* index into guid table */
+ unsigned short rdev;
+} __attribute__ ((packed)) squashfs_dev_inode_header_1;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:4; /* index into uid table */
+ unsigned int guid:4; /* index into guid table */
+ unsigned short symlink_size;
+ char symlink[0];
+} __attribute__ ((packed)) squashfs_symlink_inode_header_1;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:4; /* index into uid table */
+ unsigned int guid:4; /* index into guid table */
+ unsigned int mtime;
+ squashfs_block start_block;
+ unsigned int file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+ unsigned short block_list[0];
+} __attribute__ ((packed)) squashfs_reg_inode_header_1;
+
+typedef struct {
+ unsigned int inode_type:4;
+ unsigned int mode:12; /* protection */
+ unsigned int uid:4; /* index into uid table */
+ unsigned int guid:4; /* index into guid table */
+ unsigned int file_size:19;
+ unsigned int offset:13;
+ unsigned int mtime;
+ unsigned int start_block:24;
+} __attribute__ ((packed)) squashfs_dir_inode_header_1;
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
+ SQUASHFS_MEMSET(s, d, n);\
+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+ SQUASHFS_SWAP((s)->uid, d, 16, 4);\
+ SQUASHFS_SWAP((s)->guid, d, 20, 4);\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, \
+ sizeof(squashfs_ipc_inode_header_1));\
+ SQUASHFS_SWAP((s)->type, d, 24, 4);\
+ SQUASHFS_SWAP((s)->offset, d, 28, 4);\
+}
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, \
+ sizeof(squashfs_dev_inode_header_1));\
+ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_symlink_inode_header_1));\
+ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_reg_inode_header_1));\
+ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
+ SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
+ SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, \
+ sizeof(squashfs_dir_inode_header_1));\
+ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
+ SQUASHFS_SWAP((s)->offset, d, 43, 13);\
+ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
+ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
+}
+
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * macros used to swap each structure entry, taking into account
+ * bitfields and different bitfield placing conventions on differing
+ * architectures
+ */
+
+#include <asm/byteorder.h>
+
+#ifdef __BIG_ENDIAN
+ /* convert from little endian to big endian */
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+ tbits, b_pos)
+#else
+ /* convert from big endian to little endian */
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
+ tbits, 64 - tbits - b_pos)
+#endif
+
+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
+ int bits;\
+ int b_pos = pos % 8;\
+ unsigned long long val = 0;\
+ unsigned char *s = (unsigned char *)p + (pos / 8);\
+ unsigned char *d = ((unsigned char *) &val) + 7;\
+ for(bits = 0; bits < (tbits + b_pos); bits += 8) \
+ *d-- = *s++;\
+ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
+}
+
+#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
+
+#endif
+#endif
diff --new-file -urp linux-2.6.11.3/include/linux/squashfs_fs_i.h linux-2.6.11.3-squashfs/include/linux/squashfs_fs_i.h
--- linux-2.6.11.3/include/linux/squashfs_fs_i.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.3-squashfs/include/linux/squashfs_fs_i.h 2005-03-14 00:53:28.078561856 +0000
@@ -0,0 +1,44 @@
+#ifndef SQUASHFS_FS_I
+#define SQUASHFS_FS_I
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005
+ * Phillip Lougher <phillip@xxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs_i.h
+ */
+
+typedef struct squashfs_inode_info {
+ unsigned int start_block;
+ unsigned int block_list_start;
+ unsigned int offset;
+ union {
+ struct {
+ unsigned int fragment_start_block;
+ unsigned int fragment_size;
+ unsigned int fragment_offset;
+ } s1;
+ struct {
+ unsigned int directory_index_start;
+ unsigned int directory_index_offset;
+ unsigned int directory_index_count;
+ } s2;
+ } u;
+ struct inode vfs_inode;
+ } squashfs_inode_info;
+#endif
diff --new-file -urp linux-2.6.11.3/include/linux/squashfs_fs_sb.h linux-2.6.11.3-squashfs/include/linux/squashfs_fs_sb.h
--- linux-2.6.11.3/include/linux/squashfs_fs_sb.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.11.3-squashfs/include/linux/squashfs_fs_sb.h 2005-03-14 00:53:28.085560792 +0000
@@ -0,0 +1,68 @@
+#ifndef SQUASHFS_FS_SB
+#define SQUASHFS_FS_SB
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005
+ * Phillip Lougher <phillip@xxxxxxxxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs_sb.h
+ */
+
+#include <linux/squashfs_fs.h>
+
+typedef struct {
+ unsigned int block;
+ int length;
+ unsigned int next_index;
+ char *data;
+ } squashfs_cache;
+
+struct squashfs_fragment_cache {
+ unsigned int block;
+ int length;
+ unsigned int locked;
+ char *data;
+ };
+
+typedef struct squashfs_sb_info {
+ squashfs_super_block sBlk;
+ int devblksize;
+ int devblksize_log2;
+ int swap;
+ squashfs_cache *block_cache;
+ struct squashfs_fragment_cache *fragment;
+ int next_cache;
+ int next_fragment;
+ squashfs_uid *uid;
+ squashfs_uid *guid;
+ squashfs_fragment_index *fragment_index;
+ unsigned int read_size;
+ char *read_data;
+ char *read_page;
+ struct semaphore read_page_mutex;
+ struct semaphore block_cache_mutex;
+ struct semaphore fragment_mutex;
+ wait_queue_head_t waitq;
+ wait_queue_head_t fragment_wait_queue;
+ struct inode *(*iget)(struct super_block *s, squashfs_inode \
+ inode);
+ unsigned int (*read_blocklist)(struct inode *inode, int \
+ index, int readahead_blks, char *block_list, \
+ unsigned short **block_p, unsigned int *bsize);
+ } squashfs_sb_info;
+#endif
diff --new-file -urp linux-2.6.11.3/init/do_mounts_rd.c linux-2.6.11.3-squashfs/init/do_mounts_rd.c
--- linux-2.6.11.3/init/do_mounts_rd.c 2005-03-13 06:44:30.000000000 +0000
+++ linux-2.6.11.3-squashfs/init/do_mounts_rd.c 2005-03-14 00:53:28.092559728 +0000
@@ -5,6 +5,7 @@
#include <linux/ext2_fs.h>
#include <linux/romfs_fs.h>
#include <linux/cramfs_fs.h>
+#include <linux/squashfs_fs.h>
#include <linux/initrd.h>
#include <linux/string.h>

@@ -39,6 +40,7 @@ static int __init crd_load(int in_fd, in
* numbers could not be found.
*
* We currently check for the following magic numbers:
+ * squashfs
* minix
* ext2
* romfs
@@ -53,6 +55,7 @@ identify_ramdisk_image(int fd, int start
struct ext2_super_block *ext2sb;
struct romfs_super_block *romfsb;
struct cramfs_super *cramfsb;
+ struct squashfs_super_block *squashfsb;
int nblocks = -1;
unsigned char *buf;

@@ -64,6 +67,7 @@ identify_ramdisk_image(int fd, int start
ext2sb = (struct ext2_super_block *) buf;
romfsb = (struct romfs_super_block *) buf;
cramfsb = (struct cramfs_super *) buf;
+ squashfsb = (struct squashfs_super_block *) buf;
memset(buf, 0xe5, size);

/*
@@ -101,6 +105,15 @@ identify_ramdisk_image(int fd, int start
goto done;
}

+ /* squashfs is at block zero too */
+ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
+ printk(KERN_NOTICE
+ "RAMDISK: squashfs filesystem found at block %d\n",
+ start_block);
+ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
+ goto done;
+ }
+
/*
* Read block 1 to test for minix and ext2 superblock
*/
diff --new-file -urp linux-2.6.11.3/MAINTAINERS linux-2.6.11.3-squashfs/MAINTAINERS
--- linux-2.6.11.3/MAINTAINERS 2005-03-13 06:44:28.000000000 +0000
+++ linux-2.6.11.3-squashfs/MAINTAINERS 2005-03-14 00:53:28.101558360 +0000
@@ -2125,6 +2125,13 @@ M: jschlst@xxxxxxxxx
L: linux-net@xxxxxxxxxxxxxxx
S: Supported

+SQUASHFS FILESYSTEM
+P: Phillip Lougher
+M: phillip@xxxxxxxxxxxxxxxxxxx
+W: http://squashfs.sourceforge.net
+L: squashfs-devel@xxxxxxxxxxxxxxxxxxxxx
+S: Maintained
+
SRM (Alpha) environment access
P: Jan-Benedict Glaw
M: jbglaw@xxxxxxxxxx