From 4f82c5078e46fa0799038df33ad1cd624cf54bde Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 10 Sep 2008 15:37:14 +0000 Subject: linux-moblin2: Add moblin2 kernel git-svn-id: https://svn.o-hand.com/repos/poky/trunk@5166 311d38ba-8fff-0310-9ca6-ca027cbcb966 --- .../0009-squashfs3.3-2.6.27.patch | 6727 ++++++++++++++++++++ 1 file changed, 6727 insertions(+) create mode 100644 meta/packages/linux/linux-moblin2-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch (limited to 'meta/packages/linux/linux-moblin2-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch') diff --git a/meta/packages/linux/linux-moblin2-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch b/meta/packages/linux/linux-moblin2-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch new file mode 100644 index 000000000..4de9839c7 --- /dev/null +++ b/meta/packages/linux/linux-moblin2-2.6.27-rc1/0009-squashfs3.3-2.6.27.patch @@ -0,0 +1,6727 @@ +diff -uNr a/fs/Kconfig b/fs/Kconfig +--- a/fs/Kconfig 2008-07-28 19:40:31.000000000 -0700 ++++ b/fs/Kconfig 2008-08-13 16:19:56.000000000 -0700 +@@ -1348,6 +1348,56 @@ + + If unsure, say N. + ++config SQUASHFS ++ tristate "SquashFS 3.3 - Squashed file system support" ++ select ZLIB_INFLATE ++ help ++ Saying Y here includes support for SquashFS 3.3 (a 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 1 Mbytes (default ++ block size 128K). SquashFS 3.3 supports 64 bit filesystems and files ++ (larger than 4GB), full uid/gid information, hard links and timestamps. ++ ++ 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 . 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_EMBEDDED ++ ++ bool "Additional option for memory-constrained systems" ++ depends on SQUASHFS ++ default n ++ help ++ Saying Y here allows you to specify cache size. ++ ++ If unsure, say N. ++ ++config SQUASHFS_FRAGMENT_CACHE_SIZE ++ int "Number of fragments cached" if SQUASHFS_EMBEDDED ++ depends on SQUASHFS ++ default "3" ++ help ++ By default SquashFS caches the last 3 fragments read from ++ the filesystem. Increasing this amount may mean SquashFS ++ has to re-read fragments less often from disk, at the expense ++ of extra system memory. Decreasing this amount will mean ++ SquashFS uses less memory at the expense of extra reads from disk. ++ ++ Note there must be at least one cached fragment. Anything ++ much more than three will probably not make much difference. ++ + config VXFS_FS + tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" + depends on BLOCK +diff -uNr a/fs/Kconfig.orig b/fs/Kconfig.orig +--- a/fs/Kconfig.orig 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/Kconfig.orig 2008-07-28 19:40:31.000000000 -0700 +@@ -0,0 +1,2097 @@ ++# ++# File system configuration ++# ++ ++menu "File systems" ++ ++if BLOCK ++ ++config EXT2_FS ++ tristate "Second extended fs support" ++ help ++ Ext2 is a standard Linux file system for hard disks. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called ext2. ++ ++ If unsure, say Y. ++ ++config EXT2_FS_XATTR ++ bool "Ext2 extended attributes" ++ depends on EXT2_FS ++ help ++ Extended attributes are name:value pairs associated with inodes by ++ the kernel or by users (see the attr(5) manual page, or visit ++ for details). ++ ++ If unsure, say N. ++ ++config EXT2_FS_POSIX_ACL ++ bool "Ext2 POSIX Access Control Lists" ++ depends on EXT2_FS_XATTR ++ select FS_POSIX_ACL ++ help ++ Posix Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the Posix ACLs for ++ Linux website . ++ ++ If you don't know what Access Control Lists are, say N ++ ++config EXT2_FS_SECURITY ++ bool "Ext2 Security Labels" ++ depends on EXT2_FS_XATTR ++ help ++ Security labels support alternative access control models ++ implemented by security modules like SELinux. This option ++ enables an extended attribute handler for file security ++ labels in the ext2 filesystem. ++ ++ If you are not using a security module that requires using ++ extended attributes for file security labels, say N. ++ ++config EXT2_FS_XIP ++ bool "Ext2 execute in place support" ++ depends on EXT2_FS && MMU ++ help ++ Execute in place can be used on memory-backed block devices. If you ++ enable this option, you can select to mount block devices which are ++ capable of this feature without using the page cache. ++ ++ If you do not use a block device that is capable of using this, ++ or if unsure, say N. ++ ++config FS_XIP ++# execute in place ++ bool ++ depends on EXT2_FS_XIP ++ default y ++ ++config EXT3_FS ++ tristate "Ext3 journalling file system support" ++ select JBD ++ help ++ This is the journalling version of the Second extended file system ++ (often called ext3), the de facto standard Linux file system ++ (method to organize files on a storage device) for hard disks. ++ ++ The journalling code included in this driver means you do not have ++ to run e2fsck (file system checker) on your file systems after a ++ crash. The journal keeps track of any changes that were being made ++ at the time the system crashed, and can ensure that your file system ++ is consistent without the need for a lengthy check. ++ ++ Other than adding the journal to the file system, the on-disk format ++ of ext3 is identical to ext2. It is possible to freely switch ++ between using the ext3 driver and the ext2 driver, as long as the ++ file system has been cleanly unmounted, or e2fsck is run on the file ++ system. ++ ++ To add a journal on an existing ext2 file system or change the ++ behavior of ext3 file systems, you can use the tune2fs utility ("man ++ tune2fs"). To modify attributes of files and directories on ext3 ++ file systems, use chattr ("man chattr"). You need to be using ++ e2fsprogs version 1.20 or later in order to create ext3 journals ++ (available at ). ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called ext3. ++ ++config EXT3_FS_XATTR ++ bool "Ext3 extended attributes" ++ depends on EXT3_FS ++ default y ++ help ++ Extended attributes are name:value pairs associated with inodes by ++ the kernel or by users (see the attr(5) manual page, or visit ++ for details). ++ ++ If unsure, say N. ++ ++ You need this for POSIX ACL support on ext3. ++ ++config EXT3_FS_POSIX_ACL ++ bool "Ext3 POSIX Access Control Lists" ++ depends on EXT3_FS_XATTR ++ select FS_POSIX_ACL ++ help ++ Posix Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the Posix ACLs for ++ Linux website . ++ ++ If you don't know what Access Control Lists are, say N ++ ++config EXT3_FS_SECURITY ++ bool "Ext3 Security Labels" ++ depends on EXT3_FS_XATTR ++ help ++ Security labels support alternative access control models ++ implemented by security modules like SELinux. This option ++ enables an extended attribute handler for file security ++ labels in the ext3 filesystem. ++ ++ If you are not using a security module that requires using ++ extended attributes for file security labels, say N. ++ ++config EXT4DEV_FS ++ tristate "Ext4dev/ext4 extended fs support development (EXPERIMENTAL)" ++ depends on EXPERIMENTAL ++ select JBD2 ++ select CRC16 ++ help ++ Ext4dev is a predecessor filesystem of the next generation ++ extended fs ext4, based on ext3 filesystem code. It will be ++ renamed ext4 fs later, once ext4dev is mature and stabilized. ++ ++ Unlike the change from ext2 filesystem to ext3 filesystem, ++ the on-disk format of ext4dev is not the same as ext3 any more: ++ it is based on extent maps and it supports 48-bit physical block ++ numbers. These combined on-disk format changes will allow ++ ext4dev/ext4 to handle more than 16 TB filesystem volumes -- ++ a hard limit that ext3 cannot overcome without changing the ++ on-disk format. ++ ++ Other than extent maps and 48-bit block numbers, ext4dev also is ++ likely to have other new features such as persistent preallocation, ++ high resolution time stamps, and larger file support etc. These ++ features will be added to ext4dev gradually. ++ ++ To compile this file system support as a module, choose M here. The ++ module will be called ext4dev. ++ ++ If unsure, say N. ++ ++config EXT4DEV_FS_XATTR ++ bool "Ext4dev extended attributes" ++ depends on EXT4DEV_FS ++ default y ++ help ++ Extended attributes are name:value pairs associated with inodes by ++ the kernel or by users (see the attr(5) manual page, or visit ++ for details). ++ ++ If unsure, say N. ++ ++ You need this for POSIX ACL support on ext4dev/ext4. ++ ++config EXT4DEV_FS_POSIX_ACL ++ bool "Ext4dev POSIX Access Control Lists" ++ depends on EXT4DEV_FS_XATTR ++ select FS_POSIX_ACL ++ help ++ POSIX Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the POSIX ACLs for ++ Linux website . ++ ++ If you don't know what Access Control Lists are, say N ++ ++config EXT4DEV_FS_SECURITY ++ bool "Ext4dev Security Labels" ++ depends on EXT4DEV_FS_XATTR ++ help ++ Security labels support alternative access control models ++ implemented by security modules like SELinux. This option ++ enables an extended attribute handler for file security ++ labels in the ext4dev/ext4 filesystem. ++ ++ If you are not using a security module that requires using ++ extended attributes for file security labels, say N. ++ ++config JBD ++ tristate ++ help ++ This is a generic journalling layer for block devices. It is ++ currently used by the ext3 and OCFS2 file systems, but it could ++ also be used to add journal support to other file systems or block ++ devices such as RAID or LVM. ++ ++ If you are using the ext3 or OCFS2 file systems, you need to ++ say Y here. If you are not using ext3 OCFS2 then you will probably ++ want to say N. ++ ++ To compile this device as a module, choose M here: the module will be ++ called jbd. If you are compiling ext3 or OCFS2 into the kernel, ++ you cannot compile this code as a module. ++ ++config JBD_DEBUG ++ bool "JBD (ext3) debugging support" ++ depends on JBD && DEBUG_FS ++ help ++ If you are using the ext3 journaled file system (or potentially any ++ other file system/device using JBD), this option allows you to ++ enable debugging output while the system is running, in order to ++ help track down any problems you are having. By default the ++ debugging output will be turned off. ++ ++ If you select Y here, then you will be able to turn on debugging ++ with "echo N > /sys/kernel/debug/jbd/jbd-debug", where N is a ++ number between 1 and 5, the higher the number, the more debugging ++ output is generated. To turn debugging off again, do ++ "echo 0 > /sys/kernel/debug/jbd/jbd-debug". ++ ++config JBD2 ++ tristate ++ select CRC32 ++ help ++ This is a generic journaling layer for block devices that support ++ both 32-bit and 64-bit block numbers. It is currently used by ++ the ext4dev/ext4 filesystem, but it could also be used to add ++ journal support to other file systems or block devices such ++ as RAID or LVM. ++ ++ If you are using ext4dev/ext4, you need to say Y here. If you are not ++ using ext4dev/ext4 then you will probably want to say N. ++ ++ To compile this device as a module, choose M here. The module will be ++ called jbd2. If you are compiling ext4dev/ext4 into the kernel, ++ you cannot compile this code as a module. ++ ++config JBD2_DEBUG ++ bool "JBD2 (ext4dev/ext4) debugging support" ++ depends on JBD2 && DEBUG_FS ++ help ++ If you are using the ext4dev/ext4 journaled file system (or ++ potentially any other filesystem/device using JBD2), this option ++ allows you to enable debugging output while the system is running, ++ in order to help track down any problems you are having. ++ By default, the debugging output will be turned off. ++ ++ If you select Y here, then you will be able to turn on debugging ++ with "echo N > /sys/kernel/debug/jbd2/jbd2-debug", where N is a ++ number between 1 and 5. The higher the number, the more debugging ++ output is generated. To turn debugging off again, do ++ "echo 0 > /sys/kernel/debug/jbd2/jbd2-debug". ++ ++config FS_MBCACHE ++# Meta block cache for Extended Attributes (ext2/ext3/ext4) ++ tristate ++ depends on EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4DEV_FS_XATTR ++ default y if EXT2_FS=y || EXT3_FS=y || EXT4DEV_FS=y ++ default m if EXT2_FS=m || EXT3_FS=m || EXT4DEV_FS=m ++ ++config REISERFS_FS ++ tristate "Reiserfs support" ++ help ++ Stores not just filenames but the files themselves in a balanced ++ tree. Uses journalling. ++ ++ Balanced trees are more efficient than traditional file system ++ architectural foundations. ++ ++ In general, ReiserFS is as fast as ext2, but is very efficient with ++ large directories and small files. Additional patches are needed ++ for NFS and quotas, please see for links. ++ ++ It is more easily extended to have features currently found in ++ database and keyword search systems than block allocation based file ++ systems are. The next version will be so extended, and will support ++ plugins consistent with our motto ``It takes more than a license to ++ make source code open.'' ++ ++ Read to learn more about reiserfs. ++ ++ Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com. ++ ++ If you like it, you can pay us to add new features to it that you ++ need, buy a support contract, or pay us to port it to another OS. ++ ++config REISERFS_CHECK ++ bool "Enable reiserfs debug mode" ++ depends on REISERFS_FS ++ help ++ If you set this to Y, then ReiserFS will perform every check it can ++ possibly imagine of its internal consistency throughout its ++ operation. It will also go substantially slower. More than once we ++ have forgotten that this was on, and then gone despondent over the ++ latest benchmarks.:-) Use of this option allows our team to go all ++ out in checking for consistency when debugging without fear of its ++ effect on end users. If you are on the verge of sending in a bug ++ report, say Y and you might get a useful error message. Almost ++ everyone should say N. ++ ++config REISERFS_PROC_INFO ++ bool "Stats in /proc/fs/reiserfs" ++ depends on REISERFS_FS && PROC_FS ++ help ++ Create under /proc/fs/reiserfs a hierarchy of files, displaying ++ various ReiserFS statistics and internal data at the expense of ++ making your kernel or module slightly larger (+8 KB). This also ++ increases the amount of kernel memory required for each mount. ++ Almost everyone but ReiserFS developers and people fine-tuning ++ reiserfs or tracing problems should say N. ++ ++config REISERFS_FS_XATTR ++ bool "ReiserFS extended attributes" ++ depends on REISERFS_FS ++ help ++ Extended attributes are name:value pairs associated with inodes by ++ the kernel or by users (see the attr(5) manual page, or visit ++ for details). ++ ++ If unsure, say N. ++ ++config REISERFS_FS_POSIX_ACL ++ bool "ReiserFS POSIX Access Control Lists" ++ depends on REISERFS_FS_XATTR ++ select FS_POSIX_ACL ++ help ++ Posix Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the Posix ACLs for ++ Linux website . ++ ++ If you don't know what Access Control Lists are, say N ++ ++config REISERFS_FS_SECURITY ++ bool "ReiserFS Security Labels" ++ depends on REISERFS_FS_XATTR ++ help ++ Security labels support alternative access control models ++ implemented by security modules like SELinux. This option ++ enables an extended attribute handler for file security ++ labels in the ReiserFS filesystem. ++ ++ If you are not using a security module that requires using ++ extended attributes for file security labels, say N. ++ ++config JFS_FS ++ tristate "JFS filesystem support" ++ select NLS ++ help ++ This is a port of IBM's Journaled Filesystem . More information is ++ available in the file . ++ ++ If you do not intend to use the JFS filesystem, say N. ++ ++config JFS_POSIX_ACL ++ bool "JFS POSIX Access Control Lists" ++ depends on JFS_FS ++ select FS_POSIX_ACL ++ help ++ Posix Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the Posix ACLs for ++ Linux website . ++ ++ If you don't know what Access Control Lists are, say N ++ ++config JFS_SECURITY ++ bool "JFS Security Labels" ++ depends on JFS_FS ++ help ++ Security labels support alternative access control models ++ implemented by security modules like SELinux. This option ++ enables an extended attribute handler for file security ++ labels in the jfs filesystem. ++ ++ If you are not using a security module that requires using ++ extended attributes for file security labels, say N. ++ ++config JFS_DEBUG ++ bool "JFS debugging" ++ depends on JFS_FS ++ help ++ If you are experiencing any problems with the JFS filesystem, say ++ Y here. This will result in additional debugging messages to be ++ written to the system log. Under normal circumstances, this ++ results in very little overhead. ++ ++config JFS_STATISTICS ++ bool "JFS statistics" ++ depends on JFS_FS ++ help ++ Enabling this option will cause statistics from the JFS file system ++ to be made available to the user in the /proc/fs/jfs/ directory. ++ ++config FS_POSIX_ACL ++# Posix ACL utility routines (for now, only ext2/ext3/jfs/reiserfs/nfs4) ++# ++# NOTE: you can implement Posix ACLs without these helpers (XFS does). ++# Never use this symbol for ifdefs. ++# ++ bool ++ default n ++ ++source "fs/xfs/Kconfig" ++source "fs/gfs2/Kconfig" ++ ++config OCFS2_FS ++ tristate "OCFS2 file system support" ++ depends on NET && SYSFS ++ select CONFIGFS_FS ++ select JBD ++ select CRC32 ++ help ++ OCFS2 is a general purpose extent based shared disk cluster file ++ system with many similarities to ext3. It supports 64 bit inode ++ numbers, and has automatically extending metadata groups which may ++ also make it attractive for non-clustered use. ++ ++ You'll want to install the ocfs2-tools package in order to at least ++ get "mount.ocfs2". ++ ++ Project web page: http://oss.oracle.com/projects/ocfs2 ++ Tools web page: http://oss.oracle.com/projects/ocfs2-tools ++ OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/ ++ ++ For more information on OCFS2, see the file ++ . ++ ++config OCFS2_FS_O2CB ++ tristate "O2CB Kernelspace Clustering" ++ depends on OCFS2_FS ++ default y ++ help ++ OCFS2 includes a simple kernelspace clustering package, the OCFS2 ++ Cluster Base. It only requires a very small userspace component ++ to configure it. This comes with the standard ocfs2-tools package. ++ O2CB is limited to maintaining a cluster for OCFS2 file systems. ++ It cannot manage any other cluster applications. ++ ++ It is always safe to say Y here, as the clustering method is ++ run-time selectable. ++ ++config OCFS2_FS_USERSPACE_CLUSTER ++ tristate "OCFS2 Userspace Clustering" ++ depends on OCFS2_FS && DLM ++ default y ++ help ++ This option will allow OCFS2 to use userspace clustering services ++ in conjunction with the DLM in fs/dlm. If you are using a ++ userspace cluster manager, say Y here. ++ ++ It is safe to say Y, as the clustering method is run-time ++ selectable. ++ ++config OCFS2_FS_STATS ++ bool "OCFS2 statistics" ++ depends on OCFS2_FS ++ default y ++ help ++ This option allows some fs statistics to be captured. Enabling ++ this option may increase the memory consumption. ++ ++config OCFS2_DEBUG_MASKLOG ++ bool "OCFS2 logging support" ++ depends on OCFS2_FS ++ default y ++ help ++ The ocfs2 filesystem has an extensive logging system. The system ++ allows selection of events to log via files in /sys/o2cb/logmask/. ++ This option will enlarge your kernel, but it allows debugging of ++ ocfs2 filesystem issues. ++ ++config OCFS2_DEBUG_FS ++ bool "OCFS2 expensive checks" ++ depends on OCFS2_FS ++ default n ++ help ++ This option will enable expensive consistency checks. Enable ++ this option for debugging only as it is likely to decrease ++ performance of the filesystem. ++ ++endif # BLOCK ++ ++config DNOTIFY ++ bool "Dnotify support" ++ default y ++ help ++ Dnotify is a directory-based per-fd file change notification system ++ that uses signals to communicate events to user-space. There exist ++ superior alternatives, but some applications may still rely on ++ dnotify. ++ ++ If unsure, say Y. ++ ++config INOTIFY ++ bool "Inotify file change notification support" ++ default y ++ ---help--- ++ Say Y here to enable inotify support. Inotify is a file change ++ notification system and a replacement for dnotify. Inotify fixes ++ numerous shortcomings in dnotify and introduces several new features ++ including multiple file events, one-shot support, and unmount ++ notification. ++ ++ For more information, see ++ ++ If unsure, say Y. ++ ++config INOTIFY_USER ++ bool "Inotify support for userspace" ++ depends on INOTIFY ++ default y ++ ---help--- ++ Say Y here to enable inotify support for userspace, including the ++ associated system calls. Inotify allows monitoring of both files and ++ directories via a single open fd. Events are read from the file ++ descriptor, which is also select()- and poll()-able. ++ ++ For more information, see ++ ++ If unsure, say Y. ++ ++config QUOTA ++ bool "Quota support" ++ help ++ If you say Y here, you will be able to set per user limits for disk ++ usage (also called disk quotas). Currently, it works for the ++ ext2, ext3, and reiserfs file system. ext3 also supports journalled ++ quotas for which you don't need to run quotacheck(8) after an unclean ++ shutdown. ++ For further details, read the Quota mini-HOWTO, available from ++ , or the documentation provided ++ with the quota tools. Probably the quota support is only useful for ++ multi user systems. If unsure, say N. ++ ++config QUOTA_NETLINK_INTERFACE ++ bool "Report quota messages through netlink interface" ++ depends on QUOTA && NET ++ help ++ If you say Y here, quota warnings (about exceeding softlimit, reaching ++ hardlimit, etc.) will be reported through netlink interface. If unsure, ++ say Y. ++ ++config PRINT_QUOTA_WARNING ++ bool "Print quota warnings to console (OBSOLETE)" ++ depends on QUOTA ++ default y ++ help ++ If you say Y here, quota warnings (about exceeding softlimit, reaching ++ hardlimit, etc.) will be printed to the process' controlling terminal. ++ Note that this behavior is currently deprecated and may go away in ++ future. Please use notification via netlink socket instead. ++ ++config QFMT_V1 ++ tristate "Old quota format support" ++ depends on QUOTA ++ help ++ This quota format was (is) used by kernels earlier than 2.4.22. If ++ you have quota working and you don't want to convert to new quota ++ format say Y here. ++ ++config QFMT_V2 ++ tristate "Quota format v2 support" ++ depends on QUOTA ++ help ++ This quota format allows using quotas with 32-bit UIDs/GIDs. If you ++ need this functionality say Y here. ++ ++config QUOTACTL ++ bool ++ depends on XFS_QUOTA || QUOTA ++ default y ++ ++config AUTOFS_FS ++ tristate "Kernel automounter support" ++ help ++ The automounter is a tool to automatically mount remote file systems ++ on demand. This implementation is partially kernel-based to reduce ++ overhead in the already-mounted case; this is unlike the BSD ++ automounter (amd), which is a pure user space daemon. ++ ++ To use the automounter you need the user-space tools from the autofs ++ package; you can find the location in . ++ You also want to answer Y to "NFS file system support", below. ++ ++ If you want to use the newer version of the automounter with more ++ features, say N here and say Y to "Kernel automounter v4 support", ++ below. ++ ++ To compile this support as a module, choose M here: the module will be ++ called autofs. ++ ++ If you are not a part of a fairly large, distributed network, you ++ probably do not need an automounter, and can say N here. ++ ++config AUTOFS4_FS ++ tristate "Kernel automounter version 4 support (also supports v3)" ++ help ++ The automounter is a tool to automatically mount remote file systems ++ on demand. This implementation is partially kernel-based to reduce ++ overhead in the already-mounted case; this is unlike the BSD ++ automounter (amd), which is a pure user space daemon. ++ ++ To use the automounter you need the user-space tools from ++ ; you also ++ want to answer Y to "NFS file system support", below. ++ ++ To compile this support as a module, choose M here: the module will be ++ called autofs4. You will need to add "alias autofs autofs4" to your ++ modules configuration file. ++ ++ If you are not a part of a fairly large, distributed network or ++ don't have a laptop which needs to dynamically reconfigure to the ++ local network, you probably do not need an automounter, and can say ++ N here. ++ ++config FUSE_FS ++ tristate "Filesystem in Userspace support" ++ help ++ With FUSE it is possible to implement a fully functional filesystem ++ in a userspace program. ++ ++ There's also companion library: libfuse. This library along with ++ utilities is available from the FUSE homepage: ++ ++ ++ See for more information. ++ See for needed library/utility version. ++ ++ If you want to develop a userspace FS, or if you want to use ++ a filesystem based on FUSE, answer Y or M. ++ ++config GENERIC_ACL ++ bool ++ select FS_POSIX_ACL ++ ++if BLOCK ++menu "CD-ROM/DVD Filesystems" ++ ++config ISO9660_FS ++ tristate "ISO 9660 CDROM file system support" ++ help ++ This is the standard file system used on CD-ROMs. It was previously ++ known as "High Sierra File System" and is called "hsfs" on other ++ Unix systems. The so-called Rock-Ridge extensions which allow for ++ long Unix filenames and symbolic links are also supported by this ++ driver. If you have a CD-ROM drive and want to do more with it than ++ just listen to audio CDs and watch its LEDs, say Y (and read ++ and the CD-ROM-HOWTO, ++ available from ), thereby ++ enlarging your kernel by about 27 KB; otherwise say N. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called isofs. ++ ++config JOLIET ++ bool "Microsoft Joliet CDROM extensions" ++ depends on ISO9660_FS ++ select NLS ++ help ++ Joliet is a Microsoft extension for the ISO 9660 CD-ROM file system ++ which allows for long filenames in unicode format (unicode is the ++ new 16 bit character code, successor to ASCII, which encodes the ++ characters of almost all languages of the world; see ++ for more information). Say Y here if you ++ want to be able to read Joliet CD-ROMs under Linux. ++ ++config ZISOFS ++ bool "Transparent decompression extension" ++ depends on ISO9660_FS ++ select ZLIB_INFLATE ++ help ++ This is a Linux-specific extension to RockRidge which lets you store ++ data in compressed form on a CD-ROM and have it transparently ++ decompressed when the CD-ROM is accessed. See ++ for the tools ++ necessary to create such a filesystem. Say Y here if you want to be ++ able to read such compressed CD-ROMs. ++ ++config UDF_FS ++ tristate "UDF file system support" ++ select CRC_ITU_T ++ help ++ This is the new file system used on some CD-ROMs and DVDs. Say Y if ++ you intend to mount DVD discs or CDRW's written in packet mode, or ++ if written to by other UDF utilities, such as DirectCD. ++ Please read . ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called udf. ++ ++ If unsure, say N. ++ ++config UDF_NLS ++ bool ++ default y ++ depends on (UDF_FS=m && NLS) || (UDF_FS=y && NLS=y) ++ ++endmenu ++endif # BLOCK ++ ++if BLOCK ++menu "DOS/FAT/NT Filesystems" ++ ++config FAT_FS ++ tristate ++ select NLS ++ help ++ If you want to use one of the FAT-based file systems (the MS-DOS and ++ VFAT (Windows 95) file systems), then you must say Y or M here ++ to include FAT support. You will then be able to mount partitions or ++ diskettes with FAT-based file systems and transparently access the ++ files on them, i.e. MSDOS files will look and behave just like all ++ other Unix files. ++ ++ This FAT support is not a file system in itself, it only provides ++ the foundation for the other file systems. You will have to say Y or ++ M to at least one of "MSDOS fs support" or "VFAT fs support" in ++ order to make use of it. ++ ++ Another way to read and write MSDOS floppies and hard drive ++ partitions from within Linux (but not transparently) is with the ++ mtools ("man mtools") program suite. You don't need to say Y here in ++ order to do that. ++ ++ If you need to move large files on floppies between a DOS and a ++ Linux box, say Y here, mount the floppy under Linux with an MSDOS ++ file system and use GNU tar's M option. GNU tar is a program ++ available for Unix and DOS ("man tar" or "info tar"). ++ ++ The FAT support will enlarge your kernel by about 37 KB. If unsure, ++ say Y. ++ ++ To compile this as a module, choose M here: the module will be called ++ fat. Note that if you compile the FAT support as a module, you ++ cannot compile any of the FAT-based file systems into the kernel ++ -- they will have to be modules as well. ++ ++config MSDOS_FS ++ tristate "MSDOS fs support" ++ select FAT_FS ++ help ++ This allows you to mount MSDOS partitions of your hard drive (unless ++ they are compressed; to access compressed MSDOS partitions under ++ Linux, you can either use the DOS emulator DOSEMU, described in the ++ DOSEMU-HOWTO, available from ++ , or try dmsdosfs in ++ . If you ++ intend to use dosemu with a non-compressed MSDOS partition, say Y ++ here) and MSDOS floppies. This means that file access becomes ++ transparent, i.e. the MSDOS files look and behave just like all ++ other Unix files. ++ ++ If you have Windows 95 or Windows NT installed on your MSDOS ++ partitions, you should use the VFAT file system (say Y to "VFAT fs ++ support" below), or you will not be able to see the long filenames ++ generated by Windows 95 / Windows NT. ++ ++ This option will enlarge your kernel by about 7 KB. If unsure, ++ answer Y. This will only work if you said Y to "DOS FAT fs support" ++ as well. To compile this as a module, choose M here: the module will ++ be called msdos. ++ ++config VFAT_FS ++ tristate "VFAT (Windows-95) fs support" ++ select FAT_FS ++ help ++ This option provides support for normal Windows file systems with ++ long filenames. That includes non-compressed FAT-based file systems ++ used by Windows 95, Windows 98, Windows NT 4.0, and the Unix ++ programs from the mtools package. ++ ++ The VFAT support enlarges your kernel by about 10 KB and it only ++ works if you said Y to the "DOS FAT fs support" above. Please read ++ the file for details. If ++ unsure, say Y. ++ ++ To compile this as a module, choose M here: the module will be called ++ vfat. ++ ++config FAT_DEFAULT_CODEPAGE ++ int "Default codepage for FAT" ++ depends on MSDOS_FS || VFAT_FS ++ default 437 ++ help ++ This option should be set to the codepage of your FAT filesystems. ++ It can be overridden with the "codepage" mount option. ++ See for more information. ++ ++config FAT_DEFAULT_IOCHARSET ++ string "Default iocharset for FAT" ++ depends on VFAT_FS ++ default "iso8859-1" ++ help ++ Set this to the default input/output character set you'd ++ like FAT to use. It should probably match the character set ++ that most of your FAT filesystems use, and can be overridden ++ with the "iocharset" mount option for FAT filesystems. ++ Note that "utf8" is not recommended for FAT filesystems. ++ If unsure, you shouldn't set "utf8" here. ++ See for more information. ++ ++config NTFS_FS ++ tristate "NTFS file system support" ++ select NLS ++ help ++ NTFS is the file system of Microsoft Windows NT, 2000, XP and 2003. ++ ++ Saying Y or M here enables read support. There is partial, but ++ safe, write support available. For write support you must also ++ say Y to "NTFS write support" below. ++ ++ There are also a number of user-space tools available, called ++ ntfsprogs. These include ntfsundelete and ntfsresize, that work ++ without NTFS support enabled in the kernel. ++ ++ This is a rewrite from scratch of Linux NTFS support and replaced ++ the old NTFS code starting with Linux 2.5.11. A backport to ++ the Linux 2.4 kernel series is separately available as a patch ++ from the project web site. ++ ++ For more information see ++ and . ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called ntfs. ++ ++ If you are not using Windows NT, 2000, XP or 2003 in addition to ++ Linux on your computer it is safe to say N. ++ ++config NTFS_DEBUG ++ bool "NTFS debugging support" ++ depends on NTFS_FS ++ help ++ If you are experiencing any problems with the NTFS file system, say ++ Y here. This will result in additional consistency checks to be ++ performed by the driver as well as additional debugging messages to ++ be written to the system log. Note that debugging messages are ++ disabled by default. To enable them, supply the option debug_msgs=1 ++ at the kernel command line when booting the kernel or as an option ++ to insmod when loading the ntfs module. Once the driver is active, ++ you can enable debugging messages by doing (as root): ++ echo 1 > /proc/sys/fs/ntfs-debug ++ Replacing the "1" with "0" would disable debug messages. ++ ++ If you leave debugging messages disabled, this results in little ++ overhead, but enabling debug messages results in very significant ++ slowdown of the system. ++ ++ When reporting bugs, please try to have available a full dump of ++ debugging messages while the misbehaviour was occurring. ++ ++config NTFS_RW ++ bool "NTFS write support" ++ depends on NTFS_FS ++ help ++ This enables the partial, but safe, write support in the NTFS driver. ++ ++ The only supported operation is overwriting existing files, without ++ changing the file length. No file or directory creation, deletion or ++ renaming is possible. Note only non-resident files can be written to ++ so you may find that some very small files (<500 bytes or so) cannot ++ be written to. ++ ++ While we cannot guarantee that it will not damage any data, we have ++ so far not received a single report where the driver would have ++ damaged someones data so we assume it is perfectly safe to use. ++ ++ Note: While write support is safe in this version (a rewrite from ++ scratch of the NTFS support), it should be noted that the old NTFS ++ write support, included in Linux 2.5.10 and before (since 1997), ++ is not safe. ++ ++ This is currently useful with TopologiLinux. TopologiLinux is run ++ on top of any DOS/Microsoft Windows system without partitioning your ++ hard disk. Unlike other Linux distributions TopologiLinux does not ++ need its own partition. For more information see ++ ++ ++ It is perfectly safe to say N here. ++ ++endmenu ++endif # BLOCK ++ ++menu "Pseudo filesystems" ++ ++source "fs/proc/Kconfig" ++ ++config SYSFS ++ bool "sysfs file system support" if EMBEDDED ++ default y ++ help ++ The sysfs filesystem is a virtual filesystem that the kernel uses to ++ export internal kernel objects, their attributes, and their ++ relationships to one another. ++ ++ Users can use sysfs to ascertain useful information about the running ++ kernel, such as the devices the kernel has discovered on each bus and ++ which driver each is bound to. sysfs can also be used to tune devices ++ and other kernel subsystems. ++ ++ Some system agents rely on the information in sysfs to operate. ++ /sbin/hotplug uses device and object attributes in sysfs to assist in ++ delegating policy decisions, like persistently naming devices. ++ ++ sysfs is currently used by the block subsystem to mount the root ++ partition. If sysfs is disabled you must specify the boot device on ++ the kernel boot command line via its major and minor numbers. For ++ example, "root=03:01" for /dev/hda1. ++ ++ Designers of embedded systems may wish to say N here to conserve space. ++ ++config TMPFS ++ bool "Virtual memory file system support (former shm fs)" ++ help ++ Tmpfs is a file system which keeps all files in virtual memory. ++ ++ Everything in tmpfs is temporary in the sense that no files will be ++ created on your hard drive. The files live in memory and swap ++ space. If you unmount a tmpfs instance, everything stored therein is ++ lost. ++ ++ See for details. ++ ++config TMPFS_POSIX_ACL ++ bool "Tmpfs POSIX Access Control Lists" ++ depends on TMPFS ++ select GENERIC_ACL ++ help ++ POSIX Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the POSIX ACLs for ++ Linux website . ++ ++ If you don't know what Access Control Lists are, say N. ++ ++config HUGETLBFS ++ bool "HugeTLB file system support" ++ depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || \ ++ (S390 && 64BIT) || BROKEN ++ help ++ hugetlbfs is a filesystem backing for HugeTLB pages, based on ++ ramfs. For architectures that support it, say Y here and read ++ for details. ++ ++ If unsure, say N. ++ ++config HUGETLB_PAGE ++ def_bool HUGETLBFS ++ ++config CONFIGFS_FS ++ tristate "Userspace-driven configuration filesystem" ++ depends on SYSFS ++ help ++ configfs is a ram-based filesystem that provides the converse ++ of sysfs's functionality. Where sysfs is a filesystem-based ++ view of kernel objects, configfs is a filesystem-based manager ++ of kernel objects, or config_items. ++ ++ Both sysfs and configfs can and should exist together on the ++ same system. One is not a replacement for the other. ++ ++endmenu ++ ++menu "Miscellaneous filesystems" ++ ++config ADFS_FS ++ tristate "ADFS file system support (EXPERIMENTAL)" ++ depends on BLOCK && EXPERIMENTAL ++ help ++ The Acorn Disc Filing System is the standard file system of the ++ RiscOS operating system which runs on Acorn's ARM-based Risc PC ++ systems and the Acorn Archimedes range of machines. If you say Y ++ here, Linux will be able to read from ADFS partitions on hard drives ++ and from ADFS-formatted floppy discs. If you also want to be able to ++ write to those devices, say Y to "ADFS write support" below. ++ ++ The ADFS partition should be the first partition (i.e., ++ /dev/[hs]d?1) on each of your drives. Please read the file ++ for further details. ++ ++ To compile this code as a module, choose M here: the module will be ++ called adfs. ++ ++ If unsure, say N. ++ ++config ADFS_FS_RW ++ bool "ADFS write support (DANGEROUS)" ++ depends on ADFS_FS ++ help ++ If you say Y here, you will be able to write to ADFS partitions on ++ hard drives and ADFS-formatted floppy disks. This is experimental ++ codes, so if you're unsure, say N. ++ ++config AFFS_FS ++ tristate "Amiga FFS file system support (EXPERIMENTAL)" ++ depends on BLOCK && EXPERIMENTAL ++ help ++ The Fast File System (FFS) is the common file system used on hard ++ disks by Amiga(tm) systems since AmigaOS Version 1.3 (34.20). Say Y ++ if you want to be able to read and write files from and to an Amiga ++ FFS partition on your hard drive. Amiga floppies however cannot be ++ read with this driver due to an incompatibility of the floppy ++ controller used in an Amiga and the standard floppy controller in ++ PCs and workstations. Read ++ and . ++ ++ With this driver you can also mount disk files used by Bernd ++ Schmidt's Un*X Amiga Emulator ++ (). ++ If you want to do this, you will also need to say Y or M to "Loop ++ device support", above. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called affs. If unsure, say N. ++ ++config ECRYPT_FS ++ tristate "eCrypt filesystem layer support (EXPERIMENTAL)" ++ depends on EXPERIMENTAL && KEYS && CRYPTO && NET ++ help ++ Encrypted filesystem that operates on the VFS layer. See ++ to learn more about ++ eCryptfs. Userspace components are required and can be ++ obtained from . ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called ecryptfs. ++ ++config HFS_FS ++ tristate "Apple Macintosh file system support (EXPERIMENTAL)" ++ depends on BLOCK && EXPERIMENTAL ++ select NLS ++ help ++ If you say Y here, you will be able to mount Macintosh-formatted ++ floppy disks and hard drive partitions with full read-write access. ++ Please read to learn about ++ the available mount options. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called hfs. ++ ++config HFSPLUS_FS ++ tristate "Apple Extended HFS file system support" ++ depends on BLOCK ++ select NLS ++ select NLS_UTF8 ++ help ++ If you say Y here, you will be able to mount extended format ++ Macintosh-formatted hard drive partitions with full read-write access. ++ ++ This file system is often called HFS+ and was introduced with ++ MacOS 8. It includes all Mac specific filesystem data such as ++ data forks and creator codes, but it also has several UNIX ++ style features such as file ownership and permissions. ++ ++config BEFS_FS ++ tristate "BeOS file system (BeFS) support (read only) (EXPERIMENTAL)" ++ depends on BLOCK && EXPERIMENTAL ++ select NLS ++ help ++ The BeOS File System (BeFS) is the native file system of Be, Inc's ++ BeOS. Notable features include support for arbitrary attributes ++ on files and directories, and database-like indices on selected ++ attributes. (Also note that this driver doesn't make those features ++ available at this time). It is a 64 bit filesystem, so it supports ++ extremely large volumes and files. ++ ++ If you use this filesystem, you should also say Y to at least one ++ of the NLS (native language support) options below. ++ ++ If you don't know what this is about, say N. ++ ++ To compile this as a module, choose M here: the module will be ++ called befs. ++ ++config BEFS_DEBUG ++ bool "Debug BeFS" ++ depends on BEFS_FS ++ help ++ If you say Y here, you can use the 'debug' mount option to enable ++ debugging output from the driver. ++ ++config BFS_FS ++ tristate "BFS file system support (EXPERIMENTAL)" ++ depends on BLOCK && EXPERIMENTAL ++ help ++ Boot File System (BFS) is a file system used under SCO UnixWare to ++ allow the bootloader access to the kernel image and other important ++ files during the boot process. It is usually mounted under /stand ++ and corresponds to the slice marked as "STAND" in the UnixWare ++ partition. You should say Y if you want to read or write the files ++ on your /stand slice from within Linux. You then also need to say Y ++ to "UnixWare slices support", below. More information about the BFS ++ file system is contained in the file ++ . ++ ++ If you don't know what this is about, say N. ++ ++ To compile this as a module, choose M here: the module will be called ++ bfs. Note that the file system of your root partition (the one ++ containing the directory /) cannot be compiled as a module. ++ ++ ++ ++config EFS_FS ++ tristate "EFS file system support (read only) (EXPERIMENTAL)" ++ depends on BLOCK && EXPERIMENTAL ++ help ++ EFS is an older file system used for non-ISO9660 CD-ROMs and hard ++ disk partitions by SGI's IRIX operating system (IRIX 6.0 and newer ++ uses the XFS file system for hard disk partitions however). ++ ++ This implementation only offers read-only access. If you don't know ++ what all this is about, it's safe to say N. For more information ++ about EFS see its home page at . ++ ++ To compile the EFS file system support as a module, choose M here: the ++ module will be called efs. ++ ++config JFFS2_FS ++ tristate "Journalling Flash File System v2 (JFFS2) support" ++ select CRC32 ++ depends on MTD ++ help ++ JFFS2 is the second generation of the Journalling Flash File System ++ for use on diskless embedded devices. It provides improved wear ++ levelling, compression and support for hard links. You cannot use ++ this on normal block devices, only on 'MTD' devices. ++ ++ Further information on the design and implementation of JFFS2 is ++ available at . ++ ++config JFFS2_FS_DEBUG ++ int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)" ++ depends on JFFS2_FS ++ default "0" ++ help ++ This controls the amount of debugging messages produced by the JFFS2 ++ code. Set it to zero for use in production systems. For evaluation, ++ testing and debugging, it's advisable to set it to one. This will ++ enable a few assertions and will print debugging messages at the ++ KERN_DEBUG loglevel, where they won't normally be visible. Level 2 ++ is unlikely to be useful - it enables extra debugging in certain ++ areas which at one point needed debugging, but when the bugs were ++ located and fixed, the detailed messages were relegated to level 2. ++ ++ If reporting bugs, please try to have available a full dump of the ++ messages at debug level 1 while the misbehaviour was occurring. ++ ++config JFFS2_FS_WRITEBUFFER ++ bool "JFFS2 write-buffering support" ++ depends on JFFS2_FS ++ default y ++ help ++ This enables the write-buffering support in JFFS2. ++ ++ This functionality is required to support JFFS2 on the following ++ types of flash devices: ++ - NAND flash ++ - NOR flash with transparent ECC ++ - DataFlash ++ ++config JFFS2_FS_WBUF_VERIFY ++ bool "Verify JFFS2 write-buffer reads" ++ depends on JFFS2_FS_WRITEBUFFER ++ default n ++ help ++ This causes JFFS2 to read back every page written through the ++ write-buffer, and check for errors. ++ ++config JFFS2_SUMMARY ++ bool "JFFS2 summary support (EXPERIMENTAL)" ++ depends on JFFS2_FS && EXPERIMENTAL ++ default n ++ help ++ This feature makes it possible to use summary information ++ for faster filesystem mount. ++ ++ The summary information can be inserted into a filesystem image ++ by the utility 'sumtool'. ++ ++ If unsure, say 'N'. ++ ++config JFFS2_FS_XATTR ++ bool "JFFS2 XATTR support (EXPERIMENTAL)" ++ depends on JFFS2_FS && EXPERIMENTAL ++ default n ++ help ++ Extended attributes are name:value pairs associated with inodes by ++ the kernel or by users (see the attr(5) manual page, or visit ++ for details). ++ ++ If unsure, say N. ++ ++config JFFS2_FS_POSIX_ACL ++ bool "JFFS2 POSIX Access Control Lists" ++ depends on JFFS2_FS_XATTR ++ default y ++ select FS_POSIX_ACL ++ help ++ Posix Access Control Lists (ACLs) support permissions for users and ++ groups beyond the owner/group/world scheme. ++ ++ To learn more about Access Control Lists, visit the Posix ACLs for ++ Linux website . ++ ++ If you don't know what Access Control Lists are, say N ++ ++config JFFS2_FS_SECURITY ++ bool "JFFS2 Security Labels" ++ depends on JFFS2_FS_XATTR ++ default y ++ help ++ Security labels support alternative access control models ++ implemented by security modules like SELinux. This option ++ enables an extended attribute handler for file security ++ labels in the jffs2 filesystem. ++ ++ If you are not using a security module that requires using ++ extended attributes for file security labels, say N. ++ ++config JFFS2_COMPRESSION_OPTIONS ++ bool "Advanced compression options for JFFS2" ++ depends on JFFS2_FS ++ default n ++ help ++ Enabling this option allows you to explicitly choose which ++ compression modules, if any, are enabled in JFFS2. Removing ++ compressors can mean you cannot read existing file systems, ++ and enabling experimental compressors can mean that you ++ write a file system which cannot be read by a standard kernel. ++ ++ If unsure, you should _definitely_ say 'N'. ++ ++config JFFS2_ZLIB ++ bool "JFFS2 ZLIB compression support" if JFFS2_COMPRESSION_OPTIONS ++ select ZLIB_INFLATE ++ select ZLIB_DEFLATE ++ depends on JFFS2_FS ++ default y ++ help ++ Zlib is designed to be a free, general-purpose, legally unencumbered, ++ lossless data-compression library for use on virtually any computer ++ hardware and operating system. See for ++ further information. ++ ++ Say 'Y' if unsure. ++ ++config JFFS2_LZO ++ bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS ++ select LZO_COMPRESS ++ select LZO_DECOMPRESS ++ depends on JFFS2_FS ++ default n ++ help ++ minilzo-based compression. Generally works better than Zlib. ++ ++ This feature was added in July, 2007. Say 'N' if you need ++ compatibility with older bootloaders or kernels. ++ ++config JFFS2_RTIME ++ bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS ++ depends on JFFS2_FS ++ default y ++ help ++ Rtime does manage to recompress already-compressed data. Say 'Y' if unsure. ++ ++config JFFS2_RUBIN ++ bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS ++ depends on JFFS2_FS ++ default n ++ help ++ RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure. ++ ++choice ++ prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS ++ default JFFS2_CMODE_PRIORITY ++ depends on JFFS2_FS ++ help ++ You can set here the default compression mode of JFFS2 from ++ the available compression modes. Don't touch if unsure. ++ ++config JFFS2_CMODE_NONE ++ bool "no compression" ++ help ++ Uses no compression. ++ ++config JFFS2_CMODE_PRIORITY ++ bool "priority" ++ help ++ Tries the compressors in a predefined order and chooses the first ++ successful one. ++ ++config JFFS2_CMODE_SIZE ++ bool "size (EXPERIMENTAL)" ++ help ++ Tries all compressors and chooses the one which has the smallest ++ result. ++ ++config JFFS2_CMODE_FAVOURLZO ++ bool "Favour LZO" ++ help ++ Tries all compressors and chooses the one which has the smallest ++ result but gives some preference to LZO (which has faster ++ decompression) at the expense of size. ++ ++endchoice ++ ++# UBIFS File system configuration ++source "fs/ubifs/Kconfig" ++ ++config CRAMFS ++ tristate "Compressed ROM file system support (cramfs)" ++ depends on BLOCK ++ select ZLIB_INFLATE ++ help ++ Saying Y here includes support for CramFs (Compressed ROM File ++ System). CramFs is designed to be a simple, small, and compressed ++ file system for ROM based embedded systems. CramFs is read-only, ++ limited to 256MB file systems (with 16MB files), and doesn't support ++ 16/32 bits uid/gid, hard links and timestamps. ++ ++ See and ++ for further information. ++ ++ To compile this as a module, choose M here: the module will be called ++ cramfs. Note that the root file system (the one containing the ++ directory /) cannot be compiled as a module. ++ ++ If unsure, say N. ++ ++config VXFS_FS ++ tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" ++ depends on BLOCK ++ help ++ FreeVxFS is a file system driver that support the VERITAS VxFS(TM) ++ file system format. VERITAS VxFS(TM) is the standard file system ++ of SCO UnixWare (and possibly others) and optionally available ++ for Sunsoft Solaris, HP-UX and many other operating systems. ++ Currently only readonly access is supported. ++ ++ NOTE: the file system type as used by mount(1), mount(2) and ++ fstab(5) is 'vxfs' as it describes the file system format, not ++ the actual driver. ++ ++ To compile this as a module, choose M here: the module will be ++ called freevxfs. If unsure, say N. ++ ++config MINIX_FS ++ tristate "Minix file system support" ++ depends on BLOCK ++ help ++ Minix is a simple operating system used in many classes about OS's. ++ The minix file system (method to organize files on a hard disk ++ partition or a floppy disk) was the original file system for Linux, ++ but has been superseded by the second extended file system ext2fs. ++ You don't want to use the minix file system on your hard disk ++ because of certain built-in restrictions, but it is sometimes found ++ on older Linux floppy disks. This option will enlarge your kernel ++ by about 28 KB. If unsure, say N. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called minix. Note that the file system of your root ++ partition (the one containing the directory /) cannot be compiled as ++ a module. ++ ++config OMFS_FS ++ tristate "SonicBlue Optimized MPEG File System support" ++ depends on BLOCK ++ select CRC_ITU_T ++ help ++ This is the proprietary file system used by the Rio Karma music ++ player and ReplayTV DVR. Despite the name, this filesystem is not ++ more efficient than a standard FS for MPEG files, in fact likely ++ the opposite is true. Say Y if you have either of these devices ++ and wish to mount its disk. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called omfs. If unsure, say N. ++ ++config HPFS_FS ++ tristate "OS/2 HPFS file system support" ++ depends on BLOCK ++ help ++ OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS ++ is the file system used for organizing files on OS/2 hard disk ++ partitions. Say Y if you want to be able to read files from and ++ write files to an OS/2 HPFS partition on your hard drive. OS/2 ++ floppies however are in regular MSDOS format, so you don't need this ++ option in order to be able to read them. Read ++ . ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called hpfs. If unsure, say N. ++ ++ ++config QNX4FS_FS ++ tristate "QNX4 file system support (read only)" ++ depends on BLOCK ++ help ++ This is the file system used by the real-time operating systems ++ QNX 4 and QNX 6 (the latter is also called QNX RTP). ++ Further information is available at . ++ Say Y if you intend to mount QNX hard disks or floppies. ++ Unless you say Y to "QNX4FS read-write support" below, you will ++ only be able to read these file systems. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called qnx4. ++ ++ If you don't know whether you need it, then you don't need it: ++ answer N. ++ ++config QNX4FS_RW ++ bool "QNX4FS write support (DANGEROUS)" ++ depends on QNX4FS_FS && EXPERIMENTAL && BROKEN ++ help ++ Say Y if you want to test write support for QNX4 file systems. ++ ++ It's currently broken, so for now: ++ answer N. ++ ++config ROMFS_FS ++ tristate "ROM file system support" ++ depends on BLOCK ++ ---help--- ++ This is a very small read-only file system mainly intended for ++ initial ram disks of installation disks, but it could be used for ++ other read-only media as well. Read ++ for details. ++ ++ To compile this file system support as a module, choose M here: the ++ module will be called romfs. Note that the file system of your ++ root partition (the one containing the directory /) cannot be a ++ module. ++ ++ If you don't know whether you need it, then you don't need it: ++ answer N. ++ ++ ++config SYSV_FS ++ tristate "System V/Xenix/V7/Coherent file system support" ++ depends on BLOCK ++ help ++ SCO, Xenix and Coherent are commercial Unix systems for Intel ++ machines, and Version 7 was used on the DEC PDP-11. Saying Y ++ here would allow you to read from their floppies and hard disk ++ partitions. ++ ++ If you have floppies or hard disk partitions like that, it is likely ++ that they contain binaries from those other Unix systems; in order ++ to run these binaries, you will want to install linux-abi which is ++ a set of kernel modules that lets you run SCO, Xenix, Wyse, ++ UnixWare, Dell Unix and System V programs under Linux. It is ++ available via FTP (user: ftp) from ++ ). ++ NOTE: that will work only for binaries from Intel-based systems; ++ PDP ones will have to wait until somebody ports Linux to -11 ;-) ++ ++ If you only intend to mount files from some other Unix over the ++ network using NFS, you don't need the System V file system support ++ (but you need NFS file system support obviously). ++ ++ Note that this option is generally not needed for floppies, since a ++ good portable way to transport files and directories between unixes ++ (and even other operating systems) is given by the tar program ("man ++ tar" or preferably "info tar"). Note also that this option has ++ nothing whatsoever to do with the option "System V IPC". Read about ++ the System V file system in ++ . ++ Saying Y here will enlarge your kernel by about 27 KB. ++ ++ To compile this as a module, choose M here: the module will be called ++ sysv. ++ ++ If you haven't heard about all of this before, it's safe to say N. ++ ++ ++config UFS_FS ++ tristate "UFS file system support (read only)" ++ depends on BLOCK ++ help ++ BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD, ++ OpenBSD and NeXTstep) use a file system called UFS. Some System V ++ Unixes can create and mount hard disk partitions and diskettes using ++ this file system as well. Saying Y here will allow you to read from ++ these partitions; if you also want to write to them, say Y to the ++ experimental "UFS file system write support", below. Please read the ++ file for more information. ++ ++ The recently released UFS2 variant (used in FreeBSD 5.x) is ++ READ-ONLY supported. ++ ++ Note that this option is generally not needed for floppies, since a ++ good portable way to transport files and directories between unixes ++ (and even other operating systems) is given by the tar program ("man ++ tar" or preferably "info tar"). ++ ++ When accessing NeXTstep files, you may need to convert them from the ++ NeXT character set to the Latin1 character set; use the program ++ recode ("info recode") for this purpose. ++ ++ To compile the UFS file system support as a module, choose M here: the ++ module will be called ufs. ++ ++ If you haven't heard about all of this before, it's safe to say N. ++ ++config UFS_FS_WRITE ++ bool "UFS file system write support (DANGEROUS)" ++ depends on UFS_FS && EXPERIMENTAL ++ help ++ Say Y here if you want to try writing to UFS partitions. This is ++ experimental, so you should back up your UFS partitions beforehand. ++ ++config UFS_DEBUG ++ bool "UFS debugging" ++ depends on UFS_FS ++ help ++ If you are experiencing any problems with the UFS filesystem, say ++ Y here. This will result in _many_ additional debugging messages to be ++ written to the system log. ++ ++endmenu ++ ++menuconfig NETWORK_FILESYSTEMS ++ bool "Network File Systems" ++ default y ++ depends on NET ++ ---help--- ++ Say Y here to get to see options for network filesystems and ++ filesystem-related networking code, such as NFS daemon and ++ RPCSEC security modules. ++ ++ This option alone does not add any kernel code. ++ ++ If you say N, all options in this submenu will be skipped and ++ disabled; if unsure, say Y here. ++ ++if NETWORK_FILESYSTEMS ++ ++config NFS_FS ++ tristate "NFS client support" ++ depends on INET ++ select LOCKD ++ select SUNRPC ++ select NFS_ACL_SUPPORT if NFS_V3_ACL ++ help ++ Choose Y here if you want to access files residing on other ++ computers using Sun's Network File System protocol. To compile ++ this file system support as a module, choose M here: the module ++ will be called nfs. ++ ++ To mount file systems exported by NFS servers, you also need to ++ install the user space mount.nfs command which can be found in ++ the Linux nfs-utils package, available from http://linux-nfs.org/. ++ Information about using the mount command is available in the ++ mount(8) man page. More detail about the Linux NFS client ++ implementation is available via the nfs(5) man page. ++ ++ Below you can choose which versions of the NFS protocol are ++ available in the kernel to mount NFS servers. Support for NFS ++ version 2 (RFC 1094) is always available when NFS_FS is selected. ++ ++ To configure a system which mounts its root file system via NFS ++ at boot time, say Y here, select "Kernel level IP ++ autoconfiguration" in the NETWORK menu, and select "Root file ++ system on NFS" below. You cannot compile this file system as a ++ module in this case. ++ ++ If unsure, say N. ++ ++config NFS_V3 ++ bool "NFS client support for NFS version 3" ++ depends on NFS_FS ++ help ++ This option enables support for version 3 of the NFS protocol ++ (RFC 1813) in the kernel's NFS client. ++ ++ If unsure, say Y. ++ ++config NFS_V3_ACL ++ bool "NFS client support for the NFSv3 ACL protocol extension" ++ depends on NFS_V3 ++ help ++ Some NFS servers support an auxiliary NFSv3 ACL protocol that ++ Sun added to Solaris but never became an official part of the ++ NFS version 3 protocol. This protocol extension allows ++ applications on NFS clients to manipulate POSIX Access Control ++ Lists on files residing on NFS servers. NFS servers enforce ++ ACLs on local files whether this protocol is available or not. ++ ++ Choose Y here if your NFS server supports the Solaris NFSv3 ACL ++ protocol extension and you want your NFS client to allow ++ applications to access and modify ACLs on files on the server. ++ ++ Most NFS servers don't support the Solaris NFSv3 ACL protocol ++ extension. You can choose N here or specify the "noacl" mount ++ option to prevent your NFS client from trying to use the NFSv3 ++ ACL protocol. ++ ++ If unsure, say N. ++ ++config NFS_V4 ++ bool "NFS client support for NFS version 4 (EXPERIMENTAL)" ++ depends on NFS_FS && EXPERIMENTAL ++ select RPCSEC_GSS_KRB5 ++ help ++ This option enables support for version 4 of the NFS protocol ++ (RFC 3530) in the kernel's NFS client. ++ ++ To mount NFS servers using NFSv4, you also need to install user ++ space programs which can be found in the Linux nfs-utils package, ++ available from http://linux-nfs.org/. ++ ++ If unsure, say N. ++ ++config ROOT_NFS ++ bool "Root file system on NFS" ++ depends on NFS_FS=y && IP_PNP ++ help ++ If you want your system to mount its root file system via NFS, ++ choose Y here. This is common practice for managing systems ++ without local permanent storage. For details, read ++ . ++ ++ Most people say N here. ++ ++config NFSD ++ tristate "NFS server support" ++ depends on INET ++ select LOCKD ++ select SUNRPC ++ select EXPORTFS ++ select NFS_ACL_SUPPORT if NFSD_V2_ACL ++ help ++ Choose Y here if you want to allow other computers to access ++ files residing on this system using Sun's Network File System ++ protocol. To compile the NFS server support as a module, ++ choose M here: the module will be called nfsd. ++ ++ You may choose to use a user-space NFS server instead, in which ++ case you can choose N here. ++ ++ To export local file systems using NFS, you also need to install ++ user space programs which can be found in the Linux nfs-utils ++ package, available from http://linux-nfs.org/. More detail about ++ the Linux NFS server implementation is available via the ++ exports(5) man page. ++ ++ Below you can choose which versions of the NFS protocol are ++ available to clients mounting the NFS server on this system. ++ Support for NFS version 2 (RFC 1094) is always available when ++ CONFIG_NFSD is selected. ++ ++ If unsure, say N. ++ ++config NFSD_V2_ACL ++ bool ++ depends on NFSD ++ ++config NFSD_V3 ++ bool "NFS server support for NFS version 3" ++ depends on NFSD ++ help ++ This option enables support in your system's NFS server for ++ version 3 of the NFS protocol (RFC 1813). ++ ++ If unsure, say Y. ++ ++config NFSD_V3_ACL ++ bool "NFS server support for the NFSv3 ACL protocol extension" ++ depends on NFSD_V3 ++ select NFSD_V2_ACL ++ help ++ Solaris NFS servers support an auxiliary NFSv3 ACL protocol that ++ never became an official part of the NFS version 3 protocol. ++ This protocol extension allows applications on NFS clients to ++ manipulate POSIX Access Control Lists on files residing on NFS ++ servers. NFS servers enforce POSIX ACLs on local files whether ++ this protocol is available or not. ++ ++ This option enables support in your system's NFS server for the ++ NFSv3 ACL protocol extension allowing NFS clients to manipulate ++ POSIX ACLs on files exported by your system's NFS server. NFS ++ clients which support the Solaris NFSv3 ACL protocol can then ++ access and modify ACLs on your NFS server. ++ ++ To store ACLs on your NFS server, you also need to enable ACL- ++ related CONFIG options for your local file systems of choice. ++ ++ If unsure, say N. ++ ++config NFSD_V4 ++ bool "NFS server support for NFS version 4 (EXPERIMENTAL)" ++ depends on NFSD && PROC_FS && EXPERIMENTAL ++ select NFSD_V3 ++ select FS_POSIX_ACL ++ select RPCSEC_GSS_KRB5 ++ help ++ This option enables support in your system's NFS server for ++ version 4 of the NFS protocol (RFC 3530). ++ ++ To export files using NFSv4, you need to install additional user ++ space programs which can be found in the Linux nfs-utils package, ++ available from http://linux-nfs.org/. ++ ++ If unsure, say N. ++ ++config LOCKD ++ tristate ++ ++config LOCKD_V4 ++ bool ++ depends on NFSD_V3 || NFS_V3 ++ default y ++ ++config EXPORTFS ++ tristate ++ ++config NFS_ACL_SUPPORT ++ tristate ++ select FS_POSIX_ACL ++ ++config NFS_COMMON ++ bool ++ depends on NFSD || NFS_FS ++ default y ++ ++config SUNRPC ++ tristate ++ ++config SUNRPC_GSS ++ tristate ++ ++config SUNRPC_XPRT_RDMA ++ tristate ++ depends on SUNRPC && INFINIBAND && EXPERIMENTAL ++ default SUNRPC && INFINIBAND ++ help ++ This option enables an RPC client transport capability that ++ allows the NFS client to mount servers via an RDMA-enabled ++ transport. ++ ++ To compile RPC client RDMA transport support as a module, ++ choose M here: the module will be called xprtrdma. ++ ++ If unsure, say N. ++ ++config RPCSEC_GSS_KRB5 ++ tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)" ++ depends on SUNRPC && EXPERIMENTAL ++ select SUNRPC_GSS ++ select CRYPTO ++ select CRYPTO_MD5 ++ select CRYPTO_DES ++ select CRYPTO_CBC ++ help ++ Choose Y here to enable Secure RPC using the Kerberos version 5 ++ GSS-API mechanism (RFC 1964). ++ ++ Secure RPC calls with Kerberos require an auxiliary user-space ++ daemon which may be found in the Linux nfs-utils package ++ available from http://linux-nfs.org/. In addition, user-space ++ Kerberos support should be installed. ++ ++ If unsure, say N. ++ ++config RPCSEC_GSS_SPKM3 ++ tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)" ++ depends on SUNRPC && EXPERIMENTAL ++ select SUNRPC_GSS ++ select CRYPTO ++ select CRYPTO_MD5 ++ select CRYPTO_DES ++ select CRYPTO_CAST5 ++ select CRYPTO_CBC ++ help ++ Choose Y here to enable Secure RPC using the SPKM3 public key ++ GSS-API mechansim (RFC 2025). ++ ++ Secure RPC calls with SPKM3 require an auxiliary userspace ++ daemon which may be found in the Linux nfs-utils package ++ available from http://linux-nfs.org/. ++ ++ If unsure, say N. ++ ++config SMB_FS ++ tristate "SMB file system support (OBSOLETE, please use CIFS)" ++ depends on INET ++ select NLS ++ help ++ SMB (Server Message Block) is the protocol Windows for Workgroups ++ (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share ++ files and printers over local networks. Saying Y here allows you to ++ mount their file systems (often called "shares" in this context) and ++ access them just like any other Unix directory. Currently, this ++ works only if the Windows machines use TCP/IP as the underlying ++ transport protocol, and not NetBEUI. For details, read ++ and the SMB-HOWTO, ++ available from . ++ ++ Note: if you just want your box to act as an SMB *server* and make ++ files and printing services available to Windows clients (which need ++ to have a TCP/IP stack), you don't need to say Y here; you can use ++ the program SAMBA (available from ) ++ for that. ++ ++ General information about how to connect Linux, Windows machines and ++ Macs is on the WWW at . ++ ++ To compile the SMB support as a module, choose M here: ++ the module will be called smbfs. Most people say N, however. ++ ++config SMB_NLS_DEFAULT ++ bool "Use a default NLS" ++ depends on SMB_FS ++ help ++ Enabling this will make smbfs use nls translations by default. You ++ need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls ++ settings and you need to give the default nls for the SMB server as ++ CONFIG_SMB_NLS_REMOTE. ++ ++ The nls settings can be changed at mount time, if your smbmount ++ supports that, using the codepage and iocharset parameters. ++ ++ smbmount from samba 2.2.0 or later supports this. ++ ++config SMB_NLS_REMOTE ++ string "Default Remote NLS Option" ++ depends on SMB_NLS_DEFAULT ++ default "cp437" ++ help ++ This setting allows you to specify a default value for which ++ codepage the server uses. If this field is left blank no ++ translations will be done by default. The local codepage/charset ++ default to CONFIG_NLS_DEFAULT. ++ ++ The nls settings can be changed at mount time, if your smbmount ++ supports that, using the codepage and iocharset parameters. ++ ++ smbmount from samba 2.2.0 or later supports this. ++ ++config CIFS ++ tristate "CIFS support (advanced network filesystem, SMBFS successor)" ++ depends on INET ++ select NLS ++ help ++ This is the client VFS module for the Common Internet File System ++ (CIFS) protocol which is the successor to the Server Message Block ++ (SMB) protocol, the native file sharing mechanism for most early ++ PC operating systems. The CIFS protocol is fully supported by ++ file servers such as Windows 2000 (including Windows 2003, NT 4 ++ and Windows XP) as well by Samba (which provides excellent CIFS ++ server support for Linux and many other operating systems). Limited ++ support for OS/2 and Windows ME and similar servers is provided as ++ well. ++ ++ The cifs module provides an advanced network file system ++ client for mounting to CIFS compliant servers. It includes ++ support for DFS (hierarchical name space), secure per-user ++ session establishment via Kerberos or NTLM or NTLMv2, ++ safe distributed caching (oplock), optional packet ++ signing, Unicode and other internationalization improvements. ++ If you need to mount to Samba or Windows from this machine, say Y. ++ ++config CIFS_STATS ++ bool "CIFS statistics" ++ depends on CIFS ++ help ++ Enabling this option will cause statistics for each server share ++ mounted by the cifs client to be displayed in /proc/fs/cifs/Stats ++ ++config CIFS_STATS2 ++ bool "Extended statistics" ++ depends on CIFS_STATS ++ help ++ Enabling this option will allow more detailed statistics on SMB ++ request timing to be displayed in /proc/fs/cifs/DebugData and also ++ allow optional logging of slow responses to dmesg (depending on the ++ value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details). ++ These additional statistics may have a minor effect on performance ++ and memory utilization. ++ ++ Unless you are a developer or are doing network performance analysis ++ or tuning, say N. ++ ++config CIFS_WEAK_PW_HASH ++ bool "Support legacy servers which use weaker LANMAN security" ++ depends on CIFS ++ help ++ Modern CIFS servers including Samba and most Windows versions ++ (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos) ++ security mechanisms. These hash the password more securely ++ than the mechanisms used in the older LANMAN version of the ++ SMB protocol but LANMAN based authentication is needed to ++ establish sessions with some old SMB servers. ++ ++ Enabling this option allows the cifs module to mount to older ++ LANMAN based servers such as OS/2 and Windows 95, but such ++ mounts may be less secure than mounts using NTLM or more recent ++ security mechanisms if you are on a public network. Unless you ++ have a need to access old SMB servers (and are on a private ++ network) you probably want to say N. Even if this support ++ is enabled in the kernel build, LANMAN authentication will not be ++ used automatically. At runtime LANMAN mounts are disabled but ++ can be set to required (or optional) either in ++ /proc/fs/cifs (see fs/cifs/README for more detail) or via an ++ option on the mount command. This support is disabled by ++ default in order to reduce the possibility of a downgrade ++ attack. ++ ++ If unsure, say N. ++ ++config CIFS_XATTR ++ bool "CIFS extended attributes" ++ depends on CIFS ++ help ++ Extended attributes are name:value pairs associated with inodes by ++ the kernel or by users (see the attr(5) manual page, or visit ++ for details). CIFS maps the name of ++ extended attributes beginning with the user namespace prefix ++ to SMB/CIFS EAs. EAs are stored on Windows servers without the ++ user namespace prefix, but their names are seen by Linux cifs clients ++ prefaced by the user namespace prefix. The system namespace ++ (used by some filesystems to store ACLs) is not supported at ++ this time. ++ ++ If unsure, say N. ++ ++config CIFS_POSIX ++ bool "CIFS POSIX Extensions" ++ depends on CIFS_XATTR ++ help ++ Enabling this option will cause the cifs client to attempt to ++ negotiate a newer dialect with servers, such as Samba 3.0.5 ++ or later, that optionally can handle more POSIX like (rather ++ than Windows like) file behavior. It also enables ++ support for POSIX ACLs (getfacl and setfacl) to servers ++ (such as Samba 3.10 and later) which can negotiate ++ CIFS POSIX ACL support. If unsure, say N. ++ ++config CIFS_DEBUG2 ++ bool "Enable additional CIFS debugging routines" ++ depends on CIFS ++ help ++ Enabling this option adds a few more debugging routines ++ to the cifs code which slightly increases the size of ++ the cifs module and can cause additional logging of debug ++ messages in some error paths, slowing performance. This ++ option can be turned off unless you are debugging ++ cifs problems. If unsure, say N. ++ ++config CIFS_EXPERIMENTAL ++ bool "CIFS Experimental Features (EXPERIMENTAL)" ++ depends on CIFS && EXPERIMENTAL ++ help ++ Enables cifs features under testing. These features are ++ experimental and currently include DFS support and directory ++ change notification ie fcntl(F_DNOTIFY), as well as the upcall ++ mechanism which will be used for Kerberos session negotiation ++ and uid remapping. Some of these features also may depend on ++ setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental ++ (which is disabled by default). See the file fs/cifs/README ++ for more details. If unsure, say N. ++ ++config CIFS_UPCALL ++ bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)" ++ depends on CIFS_EXPERIMENTAL ++ depends on KEYS ++ help ++ Enables an upcall mechanism for CIFS which accesses ++ userspace helper utilities to provide SPNEGO packaged (RFC 4178) ++ Kerberos tickets which are needed to mount to certain secure servers ++ (for which more secure Kerberos authentication is required). If ++ unsure, say N. ++ ++config CIFS_DFS_UPCALL ++ bool "DFS feature support (EXPERIMENTAL)" ++ depends on CIFS_EXPERIMENTAL ++ depends on KEYS ++ help ++ Enables an upcall mechanism for CIFS which contacts userspace ++ helper utilities to provide server name resolution (host names to ++ IP addresses) which is needed for implicit mounts of DFS junction ++ points. If unsure, say N. ++ ++config NCP_FS ++ tristate "NCP file system support (to mount NetWare volumes)" ++ depends on IPX!=n || INET ++ help ++ NCP (NetWare Core Protocol) is a protocol that runs over IPX and is ++ used by Novell NetWare clients to talk to file servers. It is to ++ IPX what NFS is to TCP/IP, if that helps. Saying Y here allows you ++ to mount NetWare file server volumes and to access them just like ++ any other Unix directory. For details, please read the file ++ in the kernel source and ++ the IPX-HOWTO from . ++ ++ You do not have to say Y here if you want your Linux box to act as a ++ file *server* for Novell NetWare clients. ++ ++ General information about how to connect Linux, Windows machines and ++ Macs is on the WWW at . ++ ++ To compile this as a module, choose M here: the module will be called ++ ncpfs. Say N unless you are connected to a Novell network. ++ ++source "fs/ncpfs/Kconfig" ++ ++config CODA_FS ++ tristate "Coda file system support (advanced network fs)" ++ depends on INET ++ help ++ Coda is an advanced network file system, similar to NFS in that it ++ enables you to mount file systems of a remote server and access them ++ with regular Unix commands as if they were sitting on your hard ++ disk. Coda has several advantages over NFS: support for ++ disconnected operation (e.g. for laptops), read/write server ++ replication, security model for authentication and encryption, ++ persistent client caches and write back caching. ++ ++ If you say Y here, your Linux box will be able to act as a Coda ++ *client*. You will need user level code as well, both for the ++ client and server. Servers are currently user level, i.e. they need ++ no kernel support. Please read ++ and check out the Coda ++ home page . ++ ++ To compile the coda client support as a module, choose M here: the ++ module will be called coda. ++ ++config AFS_FS ++ tristate "Andrew File System support (AFS) (EXPERIMENTAL)" ++ depends on INET && EXPERIMENTAL ++ select AF_RXRPC ++ help ++ If you say Y here, you will get an experimental Andrew File System ++ driver. It currently only supports unsecured read-only AFS access. ++ ++ See for more information. ++ ++ If unsure, say N. ++ ++config AFS_DEBUG ++ bool "AFS dynamic debugging" ++ depends on AFS_FS ++ help ++ Say Y here to make runtime controllable debugging messages appear. ++ ++ See for more information. ++ ++ If unsure, say N. ++ ++config 9P_FS ++ tristate "Plan 9 Resource Sharing Support (9P2000) (Experimental)" ++ depends on INET && NET_9P && EXPERIMENTAL ++ help ++ If you say Y here, you will get experimental support for ++ Plan 9 resource sharing via the 9P2000 protocol. ++ ++ See for more information. ++ ++ If unsure, say N. ++ ++endif # NETWORK_FILESYSTEMS ++ ++if BLOCK ++menu "Partition Types" ++ ++source "fs/partitions/Kconfig" ++ ++endmenu ++endif ++ ++source "fs/nls/Kconfig" ++source "fs/dlm/Kconfig" ++ ++endmenu +diff -uNr a/fs/Makefile b/fs/Makefile +--- a/fs/Makefile 2008-07-28 19:40:31.000000000 -0700 ++++ b/fs/Makefile 2008-08-13 16:18:09.000000000 -0700 +@@ -74,6 +74,7 @@ + obj-$(CONFIG_JBD2) += jbd2/ + obj-$(CONFIG_EXT2_FS) += ext2/ + obj-$(CONFIG_CRAMFS) += cramfs/ ++obj-$(CONFIG_SQUASHFS) += squashfs/ + obj-y += ramfs/ + obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ + obj-$(CONFIG_CODA_FS) += coda/ +diff -uNr a/fs/squashfs/block.c b/fs/squashfs/block.c +--- a/fs/squashfs/block.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/block.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,314 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * block.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++static struct buffer_head *get_block_length(struct super_block *s, ++ int *cur_index, int *offset, int *c_byte) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ unsigned short temp; ++ struct buffer_head *bh; ++ ++ if (!(bh = sb_bread(s, *cur_index))) ++ goto out; ++ ++ if (msblk->devblksize - *offset == 1) { ++ if (msblk->swap) ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ else ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ brelse(bh); ++ if (!(bh = sb_bread(s, ++(*cur_index)))) ++ goto out; ++ if (msblk->swap) ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ bh->b_data); ++ else ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ bh->b_data); ++ *c_byte = temp; ++ *offset = 1; ++ } else { ++ if (msblk->swap) { ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ (bh->b_data + *offset + 1)); ++ } else { ++ ((unsigned char *) &temp)[0] = *((unsigned char *) ++ (bh->b_data + *offset)); ++ ((unsigned char *) &temp)[1] = *((unsigned char *) ++ (bh->b_data + *offset + 1)); ++ } ++ *c_byte = temp; ++ *offset += 2; ++ } ++ ++ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { ++ if (*offset == msblk->devblksize) { ++ brelse(bh); ++ if (!(bh = sb_bread(s, ++(*cur_index)))) ++ goto out; ++ *offset = 0; ++ } ++ if (*((unsigned char *) (bh->b_data + *offset)) != ++ SQUASHFS_MARKER_BYTE) { ++ ERROR("Metadata block marker corrupt @ %x\n", ++ *cur_index); ++ brelse(bh); ++ goto out; ++ } ++ (*offset)++; ++ } ++ return bh; ++ ++out: ++ return NULL; ++} ++ ++ ++unsigned int squashfs_read_data(struct super_block *s, char *buffer, ++ long long index, unsigned int length, ++ long long *next_index, int srclength) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ struct buffer_head **bh; ++ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); ++ unsigned int cur_index = index >> msblk->devblksize_log2; ++ int bytes, avail_bytes, b = 0, k = 0; ++ unsigned int compressed; ++ unsigned int c_byte = length; ++ ++ bh = kmalloc(((sblk->block_size >> msblk->devblksize_log2) + 1) * ++ sizeof(struct buffer_head *), GFP_KERNEL); ++ if (bh == NULL) ++ goto read_failure; ++ ++ if (c_byte) { ++ bytes = -offset; ++ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); ++ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); ++ ++ TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, ++ compressed ? "" : "un", (unsigned int) c_byte, srclength); ++ ++ if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used) ++ goto read_failure; ++ ++ for (b = 0; bytes < (int) c_byte; b++, cur_index++) { ++ bh[b] = sb_getblk(s, cur_index); ++ if (bh[b] == NULL) ++ goto block_release; ++ bytes += msblk->devblksize; ++ } ++ ll_rw_block(READ, b, bh); ++ } else { ++ if (index < 0 || (index + 2) > sblk->bytes_used) ++ goto read_failure; ++ ++ bh[0] = get_block_length(s, &cur_index, &offset, &c_byte); ++ if (bh[0] == NULL) ++ goto read_failure; ++ b = 1; ++ ++ bytes = msblk->devblksize - offset; ++ compressed = SQUASHFS_COMPRESSED(c_byte); ++ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); ++ ++ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed ++ ? "" : "un", (unsigned int) c_byte); ++ ++ if (c_byte > srclength || (index + c_byte) > sblk->bytes_used) ++ goto block_release; ++ ++ for (; bytes < c_byte; b++) { ++ bh[b] = sb_getblk(s, ++cur_index); ++ if (bh[b] == NULL) ++ goto block_release; ++ bytes += msblk->devblksize; ++ } ++ ll_rw_block(READ, b - 1, bh + 1); ++ } ++ ++ if (compressed) { ++ int zlib_err = 0; ++ ++ /* ++ * uncompress block ++ */ ++ ++ mutex_lock(&msblk->read_data_mutex); ++ ++ msblk->stream.next_out = buffer; ++ msblk->stream.avail_out = srclength; ++ ++ for (bytes = 0; k < b; k++) { ++ avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); ++ ++ wait_on_buffer(bh[k]); ++ if (!buffer_uptodate(bh[k])) ++ goto release_mutex; ++ ++ msblk->stream.next_in = bh[k]->b_data + offset; ++ msblk->stream.avail_in = avail_bytes; ++ ++ if (k == 0) { ++ zlib_err = zlib_inflateInit(&msblk->stream); ++ if (zlib_err != Z_OK) { ++ ERROR("zlib_inflateInit returned unexpected result 0x%x," ++ " srclength %d\n", zlib_err, srclength); ++ goto release_mutex; ++ } ++ ++ if (avail_bytes == 0) { ++ offset = 0; ++ brelse(bh[k]); ++ continue; ++ } ++ } ++ ++ zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH); ++ if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) { ++ ERROR("zlib_inflate returned unexpected result 0x%x," ++ " srclength %d, avail_in %d, avail_out %d\n", zlib_err, ++ srclength, msblk->stream.avail_in, msblk->stream.avail_out); ++ goto release_mutex; ++ } ++ ++ bytes += avail_bytes; ++ offset = 0; ++ brelse(bh[k]); ++ } ++ ++ if (zlib_err != Z_STREAM_END) ++ goto release_mutex; ++ ++ zlib_err = zlib_inflateEnd(&msblk->stream); ++ if (zlib_err != Z_OK) { ++ ERROR("zlib_inflateEnd returned unexpected result 0x%x," ++ " srclength %d\n", zlib_err, srclength); ++ goto release_mutex; ++ } ++ bytes = msblk->stream.total_out; ++ mutex_unlock(&msblk->read_data_mutex); ++ } else { ++ int i; ++ ++ for(i = 0; i < b; i++) { ++ wait_on_buffer(bh[i]); ++ if (!buffer_uptodate(bh[i])) ++ goto block_release; ++ } ++ ++ for (bytes = 0; k < b; k++) { ++ avail_bytes = min(c_byte - bytes, msblk->devblksize - offset); ++ ++ memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes); ++ bytes += avail_bytes; ++ offset = 0; ++ brelse(bh[k]); ++ } ++ } ++ ++ if (next_index) ++ *next_index = index + c_byte + (length ? 0 : ++ (SQUASHFS_CHECK_DATA(msblk->sblk.flags) ? 3 : 2)); ++ ++ kfree(bh); ++ return bytes; ++ ++release_mutex: ++ mutex_unlock(&msblk->read_data_mutex); ++ ++block_release: ++ for (; k < b; k++) ++ brelse(bh[k]); ++ ++read_failure: ++ ERROR("sb_bread failed reading block 0x%x\n", cur_index); ++ kfree(bh); ++ return 0; ++} ++ ++ ++int squashfs_get_cached_block(struct super_block *s, void *buffer, ++ long long block, unsigned int offset, ++ int length, long long *next_block, ++ unsigned int *next_offset) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ int bytes, return_length = length; ++ struct squashfs_cache_entry *entry; ++ ++ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); ++ ++ while (1) { ++ entry = squashfs_cache_get(s, msblk->block_cache, block, 0); ++ bytes = entry->length - offset; ++ ++ if (entry->error || bytes < 1) { ++ return_length = 0; ++ goto finish; ++ } else if (bytes >= length) { ++ if (buffer) ++ memcpy(buffer, entry->data + offset, length); ++ if (entry->length - offset == length) { ++ *next_block = entry->next_index; ++ *next_offset = 0; ++ } else { ++ *next_block = block; ++ *next_offset = offset + length; ++ } ++ goto finish; ++ } else { ++ if (buffer) { ++ memcpy(buffer, entry->data + offset, bytes); ++ buffer = (char *) buffer + bytes; ++ } ++ block = entry->next_index; ++ squashfs_cache_put(msblk->block_cache, entry); ++ length -= bytes; ++ offset = 0; ++ } ++ } ++ ++finish: ++ squashfs_cache_put(msblk->block_cache, entry); ++ return return_length; ++} +diff -uNr a/fs/squashfs/cache.c b/fs/squashfs/cache.c +--- a/fs/squashfs/cache.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/cache.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,189 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * cache.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++struct squashfs_cache_entry *squashfs_cache_get(struct super_block *s, ++ struct squashfs_cache *cache, long long block, int length) ++{ ++ int i, n; ++ struct squashfs_cache_entry *entry; ++ ++ spin_lock(&cache->lock); ++ ++ while (1) { ++ for (i = 0; i < cache->entries && cache->entry[i].block != block; i++); ++ ++ if (i == cache->entries) { ++ if (cache->unused_blks == 0) { ++ cache->waiting ++; ++ spin_unlock(&cache->lock); ++ wait_event(cache->wait_queue, cache->unused_blks); ++ spin_lock(&cache->lock); ++ cache->waiting --; ++ continue; ++ } ++ ++ i = cache->next_blk; ++ for (n = 0; n < cache->entries; n++) { ++ if (cache->entry[i].locked == 0) ++ break; ++ i = (i + 1) % cache->entries; ++ } ++ ++ cache->next_blk = (i + 1) % cache->entries; ++ entry = &cache->entry[i]; ++ ++ cache->unused_blks --; ++ entry->block = block; ++ entry->locked = 1; ++ entry->pending = 1; ++ entry->waiting = 0; ++ entry->error = 0; ++ spin_unlock(&cache->lock); ++ ++ entry->length = squashfs_read_data(s, entry->data, ++ block, length, &entry->next_index, cache->block_size); ++ ++ spin_lock(&cache->lock); ++ ++ if (entry->length == 0) ++ entry->error = 1; ++ ++ entry->pending = 0; ++ spin_unlock(&cache->lock); ++ if (entry->waiting) ++ wake_up_all(&entry->wait_queue); ++ goto out; ++ } ++ ++ entry = &cache->entry[i]; ++ if (entry->locked == 0) ++ cache->unused_blks --; ++ entry->locked++; ++ ++ if (entry->pending) { ++ entry->waiting ++; ++ spin_unlock(&cache->lock); ++ wait_event(entry->wait_queue, !entry->pending); ++ goto out; ++ } ++ ++ spin_unlock(&cache->lock); ++ goto out; ++ } ++ ++out: ++ TRACE("Got %s %d, start block %lld, locked %d, error %d\n", i, ++ cache->name, entry->block, entry->locked, entry->error); ++ if (entry->error) ++ ERROR("Unable to read %s cache entry [%llx]\n", cache->name, block); ++ return entry; ++} ++ ++ ++void squashfs_cache_put(struct squashfs_cache *cache, ++ struct squashfs_cache_entry *entry) ++{ ++ spin_lock(&cache->lock); ++ entry->locked --; ++ if (entry->locked == 0) { ++ cache->unused_blks ++; ++ spin_unlock(&cache->lock); ++ if (cache->waiting) ++ wake_up(&cache->wait_queue); ++ } else ++ spin_unlock(&cache->lock); ++} ++ ++ ++void squashfs_cache_delete(struct squashfs_cache *cache) ++{ ++ int i; ++ ++ if (cache == NULL) ++ return; ++ ++ for (i = 0; i < cache->entries; i++) ++ if (cache->entry[i].data) { ++ if (cache->use_vmalloc) ++ vfree(cache->entry[i].data); ++ else ++ kfree(cache->entry[i].data); ++ } ++ ++ kfree(cache); ++} ++ ++ ++struct squashfs_cache *squashfs_cache_init(char *name, int entries, ++ int block_size, int use_vmalloc) ++{ ++ int i; ++ struct squashfs_cache *cache = kzalloc(sizeof(struct squashfs_cache) + ++ entries * sizeof(struct squashfs_cache_entry), GFP_KERNEL); ++ if (cache == NULL) { ++ ERROR("Failed to allocate %s cache\n", name); ++ goto failed; ++ } ++ ++ cache->next_blk = 0; ++ cache->unused_blks = entries; ++ cache->entries = entries; ++ cache->block_size = block_size; ++ cache->use_vmalloc = use_vmalloc; ++ cache->name = name; ++ cache->waiting = 0; ++ spin_lock_init(&cache->lock); ++ init_waitqueue_head(&cache->wait_queue); ++ ++ for (i = 0; i < entries; i++) { ++ init_waitqueue_head(&cache->entry[i].wait_queue); ++ cache->entry[i].block = SQUASHFS_INVALID_BLK; ++ cache->entry[i].data = use_vmalloc ? vmalloc(block_size) : ++ kmalloc(block_size, GFP_KERNEL); ++ if (cache->entry[i].data == NULL) { ++ ERROR("Failed to allocate %s cache entry\n", name); ++ goto cleanup; ++ } ++ } ++ ++ return cache; ++ ++cleanup: ++ squashfs_cache_delete(cache); ++failed: ++ return NULL; ++} +diff -uNr a/fs/squashfs/dir.c b/fs/squashfs/dir.c +--- a/fs/squashfs/dir.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/dir.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,216 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * dir.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++static const unsigned char squashfs_filetype_table[] = { ++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK ++}; ++ ++static int get_dir_index_using_offset(struct super_block *s, ++ long long *next_block, unsigned int *next_offset, ++ long long index_start, unsigned int index_offset, int i_count, ++ long long f_pos) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ int i, length = 0; ++ struct squashfs_dir_index index; ++ ++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", ++ i_count, (unsigned int) f_pos); ++ ++ f_pos -= 3; ++ if (f_pos == 0) ++ goto finish; ++ ++ for (i = 0; i < i_count; i++) { ++ if (msblk->swap) { ++ struct squashfs_dir_index sindex; ++ squashfs_get_cached_block(s, &sindex, index_start, index_offset, ++ sizeof(sindex), &index_start, &index_offset); ++ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); ++ } else ++ squashfs_get_cached_block(s, &index, index_start, index_offset, ++ sizeof(index), &index_start, &index_offset); ++ ++ if (index.index > f_pos) ++ break; ++ ++ squashfs_get_cached_block(s, NULL, index_start, index_offset, ++ index.size + 1, &index_start, &index_offset); ++ ++ length = index.index; ++ *next_block = index.start_block + sblk->directory_table_start; ++ } ++ ++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; ++ ++finish: ++ return length + 3; ++} ++ ++ ++static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) ++{ ++ struct inode *i = file->f_dentry->d_inode; ++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ long long next_block = SQUASHFS_I(i)->start_block + ++ sblk->directory_table_start; ++ int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; ++ struct squashfs_dir_header dirh; ++ struct squashfs_dir_entry *dire; ++ ++ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); ++ ++ dire = kmalloc(sizeof(struct squashfs_dir_entry) + ++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL); ++ if (dire == NULL) { ++ ERROR("Failed to allocate squashfs_dir_entry\n"); ++ goto finish; ++ } ++ ++ while(file->f_pos < 3) { ++ char *name; ++ int size, i_ino; ++ ++ if(file->f_pos == 0) { ++ name = "."; ++ size = 1; ++ i_ino = i->i_ino; ++ } else { ++ name = ".."; ++ size = 2; ++ i_ino = SQUASHFS_I(i)->u.s2.parent_inode; ++ } ++ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", ++ (unsigned int) dirent, name, size, (int) ++ file->f_pos, i_ino, squashfs_filetype_table[1]); ++ ++ if (filldir(dirent, name, size, file->f_pos, i_ino, ++ squashfs_filetype_table[1]) < 0) { ++ TRACE("Filldir returned less than 0\n"); ++ goto finish; ++ } ++ file->f_pos += size; ++ } ++ ++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_start, ++ SQUASHFS_I(i)->u.s2.directory_index_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_count, file->f_pos); ++ ++ while (length < i_size_read(i)) { ++ /* read directory header */ ++ if (msblk->swap) { ++ struct squashfs_dir_header sdirh; ++ ++ if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, ++ next_offset, sizeof(sdirh), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdirh); ++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, ++ next_offset, sizeof(dirh), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(dirh); ++ } ++ ++ dir_count = dirh.count + 1; ++ while (dir_count--) { ++ if (msblk->swap) { ++ struct squashfs_dir_entry sdire; ++ if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, ++ next_offset, sizeof(sdire), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdire); ++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, dire, next_block, ++ next_offset, sizeof(*dire), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(*dire); ++ } ++ ++ if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, ++ next_offset, dire->size + 1, &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += dire->size + 1; ++ ++ if (file->f_pos >= length) ++ continue; ++ ++ dire->name[dire->size + 1] = '\0'; ++ ++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", ++ (unsigned int) dirent, dire->name, dire->size + 1, ++ (int) file->f_pos, dirh.start_block, dire->offset, ++ dirh.inode_number + dire->inode_number, ++ squashfs_filetype_table[dire->type]); ++ ++ if (filldir(dirent, dire->name, dire->size + 1, file->f_pos, ++ dirh.inode_number + dire->inode_number, ++ squashfs_filetype_table[dire->type]) < 0) { ++ TRACE("Filldir returned less than 0\n"); ++ goto finish; ++ } ++ file->f_pos = length; ++ } ++ } ++ ++finish: ++ kfree(dire); ++ return 0; ++ ++failed_read: ++ ERROR("Unable to read directory block [%llx:%x]\n", next_block, ++ next_offset); ++ kfree(dire); ++ return 0; ++} ++ ++ ++const struct file_operations squashfs_dir_ops = { ++ .read = generic_read_dir, ++ .readdir = squashfs_readdir ++}; +diff -uNr a/fs/squashfs/export.c b/fs/squashfs/export.c +--- a/fs/squashfs/export.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/export.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,171 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * export.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)]; ++ int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1); ++ squashfs_inode_t inode; ++ ++ TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino); ++ ++ if (msblk->swap) { ++ squashfs_inode_t sinode; ++ ++ if (!squashfs_get_cached_block(s, &sinode, start, offset, ++ sizeof(sinode), &start, &offset)) ++ goto out; ++ SQUASHFS_SWAP_INODE_T((&inode), &sinode); ++ } else if (!squashfs_get_cached_block(s, &inode, start, offset, ++ sizeof(inode), &start, &offset)) ++ goto out; ++ ++ TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode); ++ ++ return inode; ++ ++out: ++ return SQUASHFS_INVALID_BLK; ++} ++ ++ ++static struct dentry *squashfs_export_iget(struct super_block *s, ++ unsigned int inode_number) ++{ ++ squashfs_inode_t inode; ++ struct inode *i; ++ struct dentry *dentry; ++ ++ TRACE("Entered squashfs_export_iget\n"); ++ ++ inode = squashfs_inode_lookup(s, inode_number); ++ if(inode == SQUASHFS_INVALID_BLK) { ++ dentry = ERR_PTR(-ENOENT); ++ goto failure; ++ } ++ ++ i = squashfs_iget(s, inode, inode_number); ++ if(i == NULL) { ++ dentry = ERR_PTR(-EACCES); ++ goto failure; ++ } ++ ++ dentry = d_alloc_anon(i); ++ if (dentry == NULL) { ++ iput(i); ++ dentry = ERR_PTR(-ENOMEM); ++ } ++ ++failure: ++ return dentry; ++} ++ ++ ++static struct dentry *squashfs_fh_to_dentry(struct super_block *s, ++ struct fid *fid, int fh_len, int fh_type) ++{ ++ if((fh_type != FILEID_INO32_GEN && fh_type != FILEID_INO32_GEN_PARENT) || ++ fh_len < 2) ++ return NULL; ++ ++ return squashfs_export_iget(s, fid->i32.ino); ++} ++ ++ ++static struct dentry *squashfs_fh_to_parent(struct super_block *s, ++ struct fid *fid, int fh_len, int fh_type) ++{ ++ if(fh_type != FILEID_INO32_GEN_PARENT || fh_len < 4) ++ return NULL; ++ ++ return squashfs_export_iget(s, fid->i32.parent_ino); ++} ++ ++ ++static struct dentry *squashfs_get_parent(struct dentry *child) ++{ ++ struct inode *i = child->d_inode; ++ ++ TRACE("Entered squashfs_get_parent\n"); ++ ++ return squashfs_export_iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode); ++} ++ ++ ++int read_inode_lookup_table(struct super_block *s) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes); ++ ++ TRACE("In read_inode_lookup_table, length %d\n", length); ++ ++ /* Allocate inode lookup table */ ++ msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL); ++ if (msblk->inode_lookup_table == NULL) { ++ ERROR("Failed to allocate inode lookup table\n"); ++ return 0; ++ } ++ ++ if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table, ++ sblk->lookup_table_start, length | ++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { ++ ERROR("unable to read inode lookup table\n"); ++ return 0; ++ } ++ ++ if (msblk->swap) { ++ int i; ++ long long block; ++ ++ for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) { ++ SQUASHFS_SWAP_LOOKUP_BLOCKS((&block), ++ &msblk->inode_lookup_table[i], 1); ++ msblk->inode_lookup_table[i] = block; ++ } ++ } ++ ++ return 1; ++} ++ ++ ++const struct export_operations squashfs_export_ops = { ++ .fh_to_dentry = squashfs_fh_to_dentry, ++ .fh_to_parent = squashfs_fh_to_parent, ++ .get_parent = squashfs_get_parent ++}; +diff -uNr a/fs/squashfs/file.c b/fs/squashfs/file.c +--- a/fs/squashfs/file.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/file.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,430 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * file.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++static struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) ++{ ++ struct meta_index *meta = NULL; ++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; ++ int i; ++ ++ mutex_lock(&msblk->meta_index_mutex); ++ ++ TRACE("locate_meta_index: index %d, offset %d\n", index, offset); ++ ++ if (msblk->meta_index == NULL) ++ goto not_allocated; ++ ++ for (i = 0; i < SQUASHFS_META_NUMBER; i ++) { ++ if (msblk->meta_index[i].inode_number == inode->i_ino && ++ msblk->meta_index[i].offset >= offset && ++ msblk->meta_index[i].offset <= index && ++ msblk->meta_index[i].locked == 0) { ++ TRACE("locate_meta_index: entry %d, offset %d\n", i, ++ msblk->meta_index[i].offset); ++ meta = &msblk->meta_index[i]; ++ offset = meta->offset; ++ } ++ } ++ ++ if (meta) ++ meta->locked = 1; ++ ++not_allocated: ++ mutex_unlock(&msblk->meta_index_mutex); ++ ++ return meta; ++} ++ ++ ++static struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) ++{ ++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; ++ struct meta_index *meta = NULL; ++ int i; ++ ++ mutex_lock(&msblk->meta_index_mutex); ++ ++ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); ++ ++ if (msblk->meta_index == NULL) { ++ msblk->meta_index = kmalloc(sizeof(struct meta_index) * ++ SQUASHFS_META_NUMBER, GFP_KERNEL); ++ if (msblk->meta_index == NULL) { ++ ERROR("Failed to allocate meta_index\n"); ++ goto failed; ++ } ++ for (i = 0; i < SQUASHFS_META_NUMBER; i++) { ++ msblk->meta_index[i].inode_number = 0; ++ msblk->meta_index[i].locked = 0; ++ } ++ msblk->next_meta_index = 0; ++ } ++ ++ for (i = SQUASHFS_META_NUMBER; i && ++ msblk->meta_index[msblk->next_meta_index].locked; i --) ++ msblk->next_meta_index = (msblk->next_meta_index + 1) % ++ SQUASHFS_META_NUMBER; ++ ++ if (i == 0) { ++ TRACE("empty_meta_index: failed!\n"); ++ goto failed; ++ } ++ ++ TRACE("empty_meta_index: returned meta entry %d, %p\n", ++ msblk->next_meta_index, ++ &msblk->meta_index[msblk->next_meta_index]); ++ ++ meta = &msblk->meta_index[msblk->next_meta_index]; ++ msblk->next_meta_index = (msblk->next_meta_index + 1) % ++ SQUASHFS_META_NUMBER; ++ ++ meta->inode_number = inode->i_ino; ++ meta->offset = offset; ++ meta->skip = skip; ++ meta->entries = 0; ++ meta->locked = 1; ++ ++failed: ++ mutex_unlock(&msblk->meta_index_mutex); ++ return meta; ++} ++ ++ ++static void release_meta_index(struct inode *inode, struct meta_index *meta) ++{ ++ meta->locked = 0; ++ smp_mb(); ++} ++ ++ ++static int read_block_index(struct super_block *s, int blocks, char *block_list, ++ long long *start_block, int *offset) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ unsigned int *block_listp; ++ int block = 0; ++ ++ if (msblk->swap) { ++ char sblock_list[blocks << 2]; ++ ++ if (!squashfs_get_cached_block(s, sblock_list, *start_block, ++ *offset, blocks << 2, start_block, offset)) { ++ ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); ++ goto failure; ++ } ++ SQUASHFS_SWAP_INTS(((unsigned int *)block_list), ++ ((unsigned int *)sblock_list), blocks); ++ } else { ++ if (!squashfs_get_cached_block(s, block_list, *start_block, ++ *offset, blocks << 2, start_block, offset)) { ++ ERROR("Fail reading block list [%llx:%x]\n", *start_block, *offset); ++ goto failure; ++ } ++ } ++ ++ for (block_listp = (unsigned int *) block_list; blocks; ++ block_listp++, blocks --) ++ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); ++ ++ return block; ++ ++failure: ++ return -1; ++} ++ ++ ++#define SIZE 256 ++ ++static inline int calculate_skip(int blocks) { ++ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); ++ return skip >= 7 ? 7 : skip + 1; ++} ++ ++ ++static int get_meta_index(struct inode *inode, int index, ++ long long *index_block, int *index_offset, ++ long long *data_block, char *block_list) ++{ ++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); ++ int offset = 0; ++ struct meta_index *meta; ++ struct meta_entry *meta_entry; ++ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; ++ int cur_offset = SQUASHFS_I(inode)->offset; ++ long long cur_data_block = SQUASHFS_I(inode)->start_block; ++ int i; ++ ++ index /= SQUASHFS_META_INDEXES * skip; ++ ++ while (offset < index) { ++ meta = locate_meta_index(inode, index, offset + 1); ++ ++ if (meta == NULL) { ++ meta = empty_meta_index(inode, offset + 1, skip); ++ if (meta == NULL) ++ goto all_done; ++ } else { ++ if(meta->entries == 0) ++ goto failed; ++ /* XXX */ ++ offset = index < meta->offset + meta->entries ? index : ++ meta->offset + meta->entries - 1; ++ /* XXX */ ++ meta_entry = &meta->meta_entry[offset - meta->offset]; ++ cur_index_block = meta_entry->index_block + sblk->inode_table_start; ++ cur_offset = meta_entry->offset; ++ cur_data_block = meta_entry->data_block; ++ TRACE("get_meta_index: offset %d, meta->offset %d, " ++ "meta->entries %d\n", offset, meta->offset, meta->entries); ++ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" ++ " data_block 0x%llx\n", cur_index_block, ++ cur_offset, cur_data_block); ++ } ++ ++ for (i = meta->offset + meta->entries; i <= index && ++ i < meta->offset + SQUASHFS_META_ENTRIES; i++) { ++ int blocks = skip * SQUASHFS_META_INDEXES; ++ ++ while (blocks) { ++ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : blocks; ++ int res = read_block_index(inode->i_sb, block, block_list, ++ &cur_index_block, &cur_offset); ++ ++ if (res == -1) ++ goto failed; ++ ++ cur_data_block += res; ++ blocks -= block; ++ } ++ ++ meta_entry = &meta->meta_entry[i - meta->offset]; ++ meta_entry->index_block = cur_index_block - sblk->inode_table_start; ++ meta_entry->offset = cur_offset; ++ meta_entry->data_block = cur_data_block; ++ meta->entries ++; ++ offset ++; ++ } ++ ++ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", ++ meta->offset, meta->entries); ++ ++ release_meta_index(inode, meta); ++ } ++ ++all_done: ++ *index_block = cur_index_block; ++ *index_offset = cur_offset; ++ *data_block = cur_data_block; ++ ++ return offset * SQUASHFS_META_INDEXES * skip; ++ ++failed: ++ release_meta_index(inode, meta); ++ return -1; ++} ++ ++ ++long long read_blocklist(struct inode *inode, int index, ++ int readahead_blks, char *block_list, ++ unsigned short **block_p, unsigned int *bsize) ++{ ++ long long block_ptr; ++ int offset; ++ long long block; ++ int res = get_meta_index(inode, index, &block_ptr, &offset, &block, ++ block_list); ++ ++ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" ++ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, block); ++ ++ if(res == -1) ++ goto failure; ++ ++ index -= res; ++ ++ while (index) { ++ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; ++ int res = read_block_index(inode->i_sb, blocks, block_list, ++ &block_ptr, &offset); ++ if (res == -1) ++ goto failure; ++ block += res; ++ index -= blocks; ++ } ++ ++ if (read_block_index(inode->i_sb, 1, block_list, &block_ptr, &offset) == -1) ++ goto failure; ++ *bsize = *((unsigned int *) block_list); ++ ++ return block; ++ ++failure: ++ return 0; ++} ++ ++ ++static int squashfs_readpage(struct file *file, struct page *page) ++{ ++ struct inode *inode = page->mapping->host; ++ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ unsigned char *block_list = NULL; ++ long long block; ++ unsigned int bsize, i; ++ int bytes; ++ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); ++ void *pageaddr; ++ struct squashfs_cache_entry *fragment = NULL; ++ char *data_ptr = msblk->read_page; ++ ++ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; ++ int start_index = page->index & ~mask; ++ int end_index = start_index | mask; ++ int file_end = i_size_read(inode) >> sblk->block_log; ++ int sparse = 0; ++ ++ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", ++ page->index, SQUASHFS_I(inode)->start_block); ++ ++ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> ++ PAGE_CACHE_SHIFT)) ++ goto out; ++ ++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK ++ || index < file_end) { ++ block_list = kmalloc(SIZE, GFP_KERNEL); ++ if (block_list == NULL) { ++ ERROR("Failed to allocate block_list\n"); ++ goto error_out; ++ } ++ ++ block = (msblk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize); ++ if (block == 0) ++ goto error_out; ++ ++ if (bsize == 0) { /* hole */ ++ bytes = index == file_end ? ++ (i_size_read(inode) & (sblk->block_size - 1)) : sblk->block_size; ++ sparse = 1; ++ } else { ++ mutex_lock(&msblk->read_page_mutex); ++ ++ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, ++ bsize, NULL, sblk->block_size); ++ ++ if (bytes == 0) { ++ ERROR("Unable to read page, block %llx, size %x\n", block, bsize); ++ mutex_unlock(&msblk->read_page_mutex); ++ goto error_out; ++ } ++ } ++ } else { ++ fragment = get_cached_fragment(inode->i_sb, ++ SQUASHFS_I(inode)-> u.s1.fragment_start_block, ++ SQUASHFS_I(inode)->u.s1.fragment_size); ++ ++ if (fragment->error) { ++ ERROR("Unable to read page, block %llx, size %x\n", ++ SQUASHFS_I(inode)->u.s1.fragment_start_block, ++ (int) SQUASHFS_I(inode)->u.s1.fragment_size); ++ release_cached_fragment(msblk, fragment); ++ goto error_out; ++ } ++ bytes = i_size_read(inode) & (sblk->block_size - 1); ++ data_ptr = fragment->data + SQUASHFS_I(inode)->u.s1.fragment_offset; ++ } ++ ++ for (i = start_index; i <= end_index && bytes > 0; i++, ++ bytes -= PAGE_CACHE_SIZE, data_ptr += PAGE_CACHE_SIZE) { ++ struct page *push_page; ++ int avail = sparse ? 0 : min_t(unsigned int, bytes, PAGE_CACHE_SIZE); ++ ++ TRACE("bytes %d, i %d, available_bytes %d\n", bytes, i, avail); ++ ++ push_page = (i == page->index) ? page : ++ grab_cache_page_nowait(page->mapping, i); ++ ++ if (!push_page) ++ continue; ++ ++ if (PageUptodate(push_page)) ++ goto skip_page; ++ ++ pageaddr = kmap_atomic(push_page, KM_USER0); ++ memcpy(pageaddr, data_ptr, avail); ++ memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail); ++ kunmap_atomic(pageaddr, KM_USER0); ++ flush_dcache_page(push_page); ++ SetPageUptodate(push_page); ++skip_page: ++ unlock_page(push_page); ++ if(i != page->index) ++ page_cache_release(push_page); ++ } ++ ++ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK ++ || index < file_end) { ++ if (!sparse) ++ mutex_unlock(&msblk->read_page_mutex); ++ kfree(block_list); ++ } else ++ release_cached_fragment(msblk, fragment); ++ ++ return 0; ++ ++error_out: ++ SetPageError(page); ++out: ++ pageaddr = kmap_atomic(page, KM_USER0); ++ memset(pageaddr, 0, PAGE_CACHE_SIZE); ++ kunmap_atomic(pageaddr, KM_USER0); ++ flush_dcache_page(page); ++ if (!PageError(page)) ++ SetPageUptodate(page); ++ unlock_page(page); ++ ++ kfree(block_list); ++ return 0; ++} ++ ++ ++const struct address_space_operations squashfs_aops = { ++ .readpage = squashfs_readpage ++}; +diff -uNr a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c +--- a/fs/squashfs/fragment.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/fragment.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,122 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * fragment.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++int get_fragment_location(struct super_block *s, unsigned int fragment, ++ long long *fragment_start_block, ++ unsigned int *fragment_size) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ long long start_block = ++ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; ++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); ++ struct squashfs_fragment_entry fragment_entry; ++ ++ if (msblk->swap) { ++ struct squashfs_fragment_entry sfragment_entry; ++ ++ if (!squashfs_get_cached_block(s, &sfragment_entry, start_block, offset, ++ sizeof(sfragment_entry), &start_block, &offset)) ++ goto out; ++ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); ++ } else ++ if (!squashfs_get_cached_block(s, &fragment_entry, start_block, offset, ++ sizeof(fragment_entry), &start_block, &offset)) ++ goto out; ++ ++ *fragment_start_block = fragment_entry.start_block; ++ *fragment_size = fragment_entry.size; ++ ++ return 1; ++ ++out: ++ return 0; ++} ++ ++ ++void release_cached_fragment(struct squashfs_sb_info *msblk, ++ struct squashfs_cache_entry *fragment) ++{ ++ squashfs_cache_put(msblk->fragment_cache, fragment); ++} ++ ++ ++struct squashfs_cache_entry *get_cached_fragment(struct super_block *s, ++ long long start_block, int length) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ ++ return squashfs_cache_get(s, msblk->fragment_cache, start_block, length); ++} ++ ++ ++int read_fragment_index_table(struct super_block *s) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments); ++ ++ if(length == 0) ++ return 1; ++ ++ /* Allocate fragment index table */ ++ msblk->fragment_index = kmalloc(length, GFP_KERNEL); ++ if (msblk->fragment_index == NULL) { ++ ERROR("Failed to allocate fragment index table\n"); ++ return 0; ++ } ++ ++ if (!squashfs_read_data(s, (char *) msblk->fragment_index, ++ sblk->fragment_table_start, length | ++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { ++ ERROR("unable to read fragment index table\n"); ++ return 0; ++ } ++ ++ if (msblk->swap) { ++ int i; ++ long long fragment; ++ ++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) { ++ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), ++ &msblk->fragment_index[i], 1); ++ msblk->fragment_index[i] = fragment; ++ } ++ } ++ ++ return 1; ++} +diff -uNr a/fs/squashfs/id.c b/fs/squashfs/id.c +--- a/fs/squashfs/id.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/id.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,97 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * id.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++int get_id(struct super_block *s, unsigned int index, unsigned int *id) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ long long start_block = msblk->id_table[SQUASHFS_ID_BLOCK(index)]; ++ int offset = SQUASHFS_ID_BLOCK_OFFSET(index); ++ ++ if (msblk->swap) { ++ unsigned int sid; ++ ++ if (!squashfs_get_cached_block(s, &sid, start_block, offset, ++ sizeof(unsigned int), &start_block, &offset)) ++ goto out; ++ SQUASHFS_SWAP_INTS((&sid), id, 1); ++ } else ++ if (!squashfs_get_cached_block(s, id, start_block, offset, ++ sizeof(unsigned int), &start_block, &offset)) ++ goto out; ++ ++ return 1; ++ ++out: ++ return 0; ++} ++ ++ ++int read_id_index_table(struct super_block *s) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ unsigned int length = SQUASHFS_ID_BLOCK_BYTES(sblk->no_ids); ++ ++ TRACE("In read_id_index_table, length %d\n", length); ++ ++ /* Allocate id index table */ ++ msblk->id_table = kmalloc(length, GFP_KERNEL); ++ if (msblk->id_table == NULL) { ++ ERROR("Failed to allocate id index table\n"); ++ return 0; ++ } ++ ++ if (!squashfs_read_data(s, (char *) msblk->id_table, ++ sblk->id_table_start, length | ++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) { ++ ERROR("unable to read id index table\n"); ++ return 0; ++ } ++ ++ if (msblk->swap) { ++ int i; ++ long long block; ++ ++ for (i = 0; i < SQUASHFS_ID_BLOCKS(sblk->no_ids); i++) { ++ SQUASHFS_SWAP_ID_BLOCKS((&block), &msblk->id_table[i], 1); ++ msblk->id_table[i] = block; ++ } ++ } ++ ++ return 1; ++} +diff -uNr a/fs/squashfs/inode.c b/fs/squashfs/inode.c +--- a/fs/squashfs/inode.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/inode.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,340 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * inode.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++static int squashfs_new_inode(struct super_block *s, struct inode *i, ++ struct squashfs_base_inode_header *inodeb) ++{ ++ if(get_id(s, inodeb->uid, &i->i_uid) == 0) ++ goto out; ++ if(get_id(s, inodeb->guid, &i->i_gid) == 0) ++ goto out; ++ ++ i->i_ino = inodeb->inode_number; ++ i->i_mtime.tv_sec = inodeb->mtime; ++ i->i_atime.tv_sec = inodeb->mtime; ++ i->i_ctime.tv_sec = inodeb->mtime; ++ i->i_mode = inodeb->mode; ++ i->i_size = 0; ++ ++ return 1; ++ ++out: ++ return 0; ++} ++ ++ ++struct inode *squashfs_iget(struct super_block *s, ++ squashfs_inode_t inode, unsigned int inode_number) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct inode *i = iget_locked(s, inode_number); ++ ++ TRACE("Entered squashfs_iget\n"); ++ ++ if(i && (i->i_state & I_NEW)) { ++ (msblk->read_inode)(i, inode); ++ unlock_new_inode(i); ++ } ++ ++ return i; ++} ++ ++ ++int squashfs_read_inode(struct inode *i, squashfs_inode_t inode) ++{ ++ struct super_block *s = i->i_sb; ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ long long block = SQUASHFS_INODE_BLK(inode) + sblk->inode_table_start; ++ unsigned int offset = SQUASHFS_INODE_OFFSET(inode); ++ long long next_block; ++ unsigned int next_offset; ++ union squashfs_inode_header id, sid; ++ struct squashfs_base_inode_header *inodeb = &id.base, *sinodeb = &sid.base; ++ ++ TRACE("Entered squashfs_read_inode\n"); ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodeb, block, offset, ++ sizeof(*sinodeb), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, sizeof(*sinodeb)); ++ } else ++ if (!squashfs_get_cached_block(s, inodeb, block, offset, ++ sizeof(*inodeb), &next_block, &next_offset)) ++ goto failed_read; ++ ++ if(squashfs_new_inode(s, i, inodeb) == 0) ++ goto failed_read; ++ ++ switch(inodeb->inode_type) { ++ case SQUASHFS_FILE_TYPE: { ++ unsigned int frag_size; ++ long long frag_blk; ++ struct squashfs_reg_inode_header *inodep = &id.reg; ++ struct squashfs_reg_inode_header *sinodep = &sid.reg; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodep, block, offset, ++ sizeof(*sinodep), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, inodep, block, offset, ++ sizeof(*inodep), &next_block, &next_offset)) ++ goto failed_read; ++ ++ frag_blk = SQUASHFS_INVALID_BLK; ++ ++ if (inodep->fragment != SQUASHFS_INVALID_FRAG) ++ if(!get_fragment_location(s, inodep->fragment, &frag_blk, ++ &frag_size)) ++ goto failed_read; ++ ++ i->i_nlink = 1; ++ i->i_size = inodep->file_size; ++ i->i_fop = &generic_ro_fops; ++ i->i_mode |= S_IFREG; ++ i->i_blocks = ((i->i_size - 1) >> 9) + 1; ++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; ++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; ++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; ++ SQUASHFS_I(i)->start_block = inodep->start_block; ++ SQUASHFS_I(i)->u.s1.block_list_start = next_block; ++ SQUASHFS_I(i)->offset = next_offset; ++ i->i_data.a_ops = &squashfs_aops; ++ ++ TRACE("File inode %x:%x, start_block %llx, " ++ "block_list_start %llx, offset %x\n", ++ SQUASHFS_INODE_BLK(inode), offset, ++ inodep->start_block, next_block, ++ next_offset); ++ break; ++ } ++ case SQUASHFS_LREG_TYPE: { ++ unsigned int frag_size; ++ long long frag_blk; ++ struct squashfs_lreg_inode_header *inodep = &id.lreg; ++ struct squashfs_lreg_inode_header *sinodep = &sid.lreg; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodep, block, offset, ++ sizeof(*sinodep), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, inodep, block, offset, ++ sizeof(*inodep), &next_block, &next_offset)) ++ goto failed_read; ++ ++ frag_blk = SQUASHFS_INVALID_BLK; ++ ++ if (inodep->fragment != SQUASHFS_INVALID_FRAG) ++ if (!get_fragment_location(s, inodep->fragment, &frag_blk, ++ &frag_size)) ++ goto failed_read; ++ ++ i->i_nlink = inodep->nlink; ++ i->i_size = inodep->file_size; ++ i->i_fop = &generic_ro_fops; ++ i->i_mode |= S_IFREG; ++ i->i_blocks = ((inodep->file_size - inodep->sparse - 1) >> 9) + 1; ++ ++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; ++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; ++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; ++ SQUASHFS_I(i)->start_block = inodep->start_block; ++ SQUASHFS_I(i)->u.s1.block_list_start = next_block; ++ SQUASHFS_I(i)->offset = next_offset; ++ i->i_data.a_ops = &squashfs_aops; ++ ++ TRACE("File inode %x:%x, start_block %llx, " ++ "block_list_start %llx, offset %x\n", ++ SQUASHFS_INODE_BLK(inode), offset, ++ inodep->start_block, next_block, ++ next_offset); ++ break; ++ } ++ case SQUASHFS_DIR_TYPE: { ++ struct squashfs_dir_inode_header *inodep = &id.dir; ++ struct squashfs_dir_inode_header *sinodep = &sid.dir; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodep, block, offset, ++ sizeof(*sinodep), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, inodep, block, offset, ++ sizeof(*inodep), &next_block, &next_offset)) ++ goto failed_read; ++ ++ i->i_nlink = inodep->nlink; ++ i->i_size = inodep->file_size; ++ i->i_op = &squashfs_dir_inode_ops; ++ i->i_fop = &squashfs_dir_ops; ++ i->i_mode |= S_IFDIR; ++ SQUASHFS_I(i)->start_block = inodep->start_block; ++ SQUASHFS_I(i)->offset = inodep->offset; ++ SQUASHFS_I(i)->u.s2.directory_index_count = 0; ++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; ++ ++ TRACE("Directory inode %x:%x, start_block %x, offset " ++ "%x\n", SQUASHFS_INODE_BLK(inode), ++ offset, inodep->start_block, ++ inodep->offset); ++ break; ++ } ++ case SQUASHFS_LDIR_TYPE: { ++ struct squashfs_ldir_inode_header *inodep = &id.ldir; ++ struct squashfs_ldir_inode_header *sinodep = &sid.ldir; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodep, block, offset, ++ sizeof(*sinodep), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, inodep, block, offset, ++ sizeof(*inodep), &next_block, &next_offset)) ++ goto failed_read; ++ ++ i->i_nlink = inodep->nlink; ++ i->i_size = inodep->file_size; ++ i->i_op = &squashfs_dir_inode_ops; ++ i->i_fop = &squashfs_dir_ops; ++ i->i_mode |= S_IFDIR; ++ SQUASHFS_I(i)->start_block = inodep->start_block; ++ SQUASHFS_I(i)->offset = inodep->offset; ++ SQUASHFS_I(i)->u.s2.directory_index_start = next_block; ++ SQUASHFS_I(i)->u.s2.directory_index_offset = next_offset; ++ SQUASHFS_I(i)->u.s2.directory_index_count = inodep->i_count; ++ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; ++ ++ TRACE("Long 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: { ++ struct squashfs_symlink_inode_header *inodep = &id.symlink; ++ struct squashfs_symlink_inode_header *sinodep = &sid.symlink; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodep, block, offset, ++ sizeof(*sinodep), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, inodep, block, offset, ++ sizeof(*inodep), &next_block, &next_offset)) ++ goto failed_read; ++ ++ i->i_nlink = inodep->nlink; ++ 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 %llx, offset %x\n", ++ SQUASHFS_INODE_BLK(inode), offset, ++ next_block, next_offset); ++ break; ++ } ++ case SQUASHFS_BLKDEV_TYPE: ++ case SQUASHFS_CHRDEV_TYPE: { ++ struct squashfs_dev_inode_header *inodep = &id.dev; ++ struct squashfs_dev_inode_header *sinodep = &sid.dev; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodep, block, offset, ++ sizeof(*sinodep), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, inodep, block, offset, ++ sizeof(*inodep), &next_block, &next_offset)) ++ goto failed_read; ++ ++ i->i_nlink = inodep->nlink; ++ 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_FIFO_TYPE: ++ case SQUASHFS_SOCKET_TYPE: { ++ struct squashfs_ipc_inode_header *inodep = &id.ipc; ++ struct squashfs_ipc_inode_header *sinodep = &sid.ipc; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, sinodep, block, offset, ++ sizeof(*sinodep), &next_block, &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, inodep, block, offset, ++ sizeof(*inodep), &next_block, &next_offset)) ++ goto failed_read; ++ ++ i->i_nlink = inodep->nlink; ++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) ++ ? S_IFIFO : S_IFSOCK; ++ 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; ++ } ++ ++ return 1; ++ ++failed_read: ++ ERROR("Unable to read inode [%llx:%x]\n", block, offset); ++ ++failed_read1: ++ make_bad_inode(i); ++ return 0; ++} +diff -uNr a/fs/squashfs/Makefile b/fs/squashfs/Makefile +--- a/fs/squashfs/Makefile 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/Makefile 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,8 @@ ++# ++# Makefile for the linux squashfs routines. ++# ++ ++obj-$(CONFIG_SQUASHFS) += squashfs.o ++squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o ++squashfs-y += namei.o super.o symlink.o ++#squashfs-y += squashfs2_0.o +diff -uNr a/fs/squashfs/namei.c b/fs/squashfs/namei.c +--- a/fs/squashfs/namei.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/namei.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,200 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * namei.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++static int get_dir_index_using_name(struct super_block *s, ++ long long *next_block, unsigned int *next_offset, ++ long long index_start, unsigned int index_offset, int i_count, ++ const char *name, int size) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ int i, length = 0; ++ struct squashfs_dir_index *index; ++ char *str; ++ ++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); ++ ++ str = kmalloc(sizeof(struct squashfs_dir_index) + ++ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL); ++ if (str == NULL) { ++ ERROR("Failed to allocate squashfs_dir_index\n"); ++ goto failure; ++ } ++ ++ index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1); ++ strncpy(str, name, size); ++ str[size] = '\0'; ++ ++ for (i = 0; i < i_count; i++) { ++ if (msblk->swap) { ++ struct squashfs_dir_index sindex; ++ squashfs_get_cached_block(s, &sindex, index_start, index_offset, ++ sizeof(sindex), &index_start, &index_offset); ++ SQUASHFS_SWAP_DIR_INDEX(index, &sindex); ++ } else ++ squashfs_get_cached_block(s, index, index_start, index_offset, ++ sizeof(struct squashfs_dir_index), &index_start, &index_offset); ++ ++ squashfs_get_cached_block(s, index->name, index_start, index_offset, ++ index->size + 1, &index_start, &index_offset); ++ ++ index->name[index->size + 1] = '\0'; ++ ++ if (strcmp(index->name, str) > 0) ++ break; ++ ++ length = index->index; ++ *next_block = index->start_block + sblk->directory_table_start; ++ } ++ ++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; ++ kfree(str); ++ ++failure: ++ return length + 3; ++} ++ ++ ++static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, ++ struct nameidata *nd) ++{ ++ const unsigned char *name = dentry->d_name.name; ++ int len = dentry->d_name.len; ++ struct inode *inode = NULL; ++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ long long next_block = SQUASHFS_I(i)->start_block + ++ sblk->directory_table_start; ++ int next_offset = SQUASHFS_I(i)->offset, length = 0, dir_count; ++ struct squashfs_dir_header dirh; ++ struct squashfs_dir_entry *dire; ++ ++ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); ++ ++ dire = kmalloc(sizeof(struct squashfs_dir_entry) + ++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL); ++ if (dire == NULL) { ++ ERROR("Failed to allocate squashfs_dir_entry\n"); ++ goto exit_lookup; ++ } ++ ++ if (len > SQUASHFS_NAME_LEN) ++ goto exit_lookup; ++ ++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_start, ++ SQUASHFS_I(i)->u.s2.directory_index_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_count, name, len); ++ ++ while (length < i_size_read(i)) { ++ /* read directory header */ ++ if (msblk->swap) { ++ struct squashfs_dir_header sdirh; ++ if (!squashfs_get_cached_block(i->i_sb, &sdirh, next_block, ++ next_offset, sizeof(sdirh), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdirh); ++ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, &dirh, next_block, ++ next_offset, sizeof(dirh), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(dirh); ++ } ++ ++ dir_count = dirh.count + 1; ++ while (dir_count--) { ++ if (msblk->swap) { ++ struct squashfs_dir_entry sdire; ++ if (!squashfs_get_cached_block(i->i_sb, &sdire, next_block, ++ next_offset, sizeof(sdire), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdire); ++ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, dire, next_block, ++ next_offset, sizeof(*dire), &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(*dire); ++ } ++ ++ if (!squashfs_get_cached_block(i->i_sb, dire->name, next_block, ++ next_offset, dire->size + 1, &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += dire->size + 1; ++ ++ if (name[0] < dire->name[0]) ++ goto exit_lookup; ++ ++ if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) { ++ squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block, ++ dire->offset); ++ ++ TRACE("calling squashfs_iget for directory entry %s, inode" ++ " %x:%x, %d\n", name, dirh.start_block, dire->offset, ++ dirh.inode_number + dire->inode_number); ++ ++ inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number); ++ ++ goto exit_lookup; ++ } ++ } ++ } ++ ++exit_lookup: ++ kfree(dire); ++ if (inode) ++ return d_splice_alias(inode, dentry); ++ d_add(dentry, inode); ++ return ERR_PTR(0); ++ ++failed_read: ++ ERROR("Unable to read directory block [%llx:%x]\n", next_block, ++ next_offset); ++ goto exit_lookup; ++} ++ ++ ++const struct inode_operations squashfs_dir_inode_ops = { ++ .lookup = squashfs_lookup ++}; +diff -uNr a/fs/squashfs/squashfs2_0.c b/fs/squashfs/squashfs2_0.c +--- a/fs/squashfs/squashfs2_0.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/squashfs2_0.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,740 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * squashfs2_0.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); ++static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, ++ struct nameidata *); ++ ++static struct file_operations squashfs_dir_ops_2 = { ++ .read = generic_read_dir, ++ .readdir = squashfs_readdir_2 ++}; ++ ++static struct inode_operations squashfs_dir_inode_ops_2 = { ++ .lookup = squashfs_lookup_2 ++}; ++ ++static unsigned char squashfs_filetype_table[] = { ++ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK ++}; ++ ++static int read_fragment_index_table_2(struct super_block *s) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ ++ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 ++ (sblk->fragments), GFP_KERNEL))) { ++ ERROR("Failed to allocate uid/gid table\n"); ++ return 0; ++ } ++ ++ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && ++ !squashfs_read_data(s, (char *) ++ msblk->fragment_index_2, ++ sblk->fragment_table_start, ++ SQUASHFS_FRAGMENT_INDEX_BYTES_2 ++ (sblk->fragments) | ++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) { ++ ERROR("unable to read fragment index table\n"); ++ return 0; ++ } ++ ++ if (msblk->swap) { ++ int i; ++ unsigned int fragment; ++ ++ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); ++ i++) { ++ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), ++ &msblk->fragment_index_2[i], 1); ++ msblk->fragment_index_2[i] = fragment; ++ } ++ } ++ ++ return 1; ++} ++ ++ ++static int get_fragment_location_2(struct super_block *s, unsigned int fragment, ++ long long *fragment_start_block, ++ unsigned int *fragment_size) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ long long start_block = ++ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; ++ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); ++ struct squashfs_fragment_entry_2 fragment_entry; ++ ++ if (msblk->swap) { ++ struct squashfs_fragment_entry_2 sfragment_entry; ++ ++ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, ++ start_block, offset, ++ sizeof(sfragment_entry), &start_block, ++ &offset)) ++ goto out; ++ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); ++ } else ++ if (!squashfs_get_cached_block(s, (char *) &fragment_entry, ++ start_block, offset, ++ sizeof(fragment_entry), &start_block, ++ &offset)) ++ goto out; ++ ++ *fragment_start_block = fragment_entry.start_block; ++ *fragment_size = fragment_entry.size; ++ ++ return 1; ++ ++out: ++ return 0; ++} ++ ++ ++static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i, ++ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) ++{ ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ ++ i->i_ino = ino; ++ 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_uid = msblk->uid[inodeb->uid]; ++ i->i_mode = inodeb->mode; ++ i->i_nlink = 1; ++ i->i_size = 0; ++ if (inodeb->guid == SQUASHFS_GUIDS) ++ i->i_gid = i->i_uid; ++ else ++ i->i_gid = msblk->guid[inodeb->guid]; ++} ++ ++ ++static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode) ++{ ++ struct super_block *s = i->i_sb; ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct 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); ++ long long next_block; ++ unsigned int next_offset; ++ union squashfs_inode_header_2 id, sid; ++ struct squashfs_base_inode_header_2 *inodeb = &id.base, ++ *sinodeb = &sid.base; ++ ++ TRACE("Entered squashfs_read_inode_2\n"); ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, (char *) sinodeb, block, ++ offset, sizeof(*sinodeb), &next_block, ++ &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, ++ sizeof(*sinodeb)); ++ } else ++ if (!squashfs_get_cached_block(s, (char *) inodeb, block, ++ offset, sizeof(*inodeb), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ squashfs_new_inode(msblk, i, inodeb, ino); ++ ++ switch(inodeb->inode_type) { ++ case SQUASHFS_FILE_TYPE: { ++ struct squashfs_reg_inode_header_2 *inodep = &id.reg; ++ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; ++ long long frag_blk; ++ unsigned int frag_size = 0; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, (char *) ++ sinodep, block, offset, ++ sizeof(*sinodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, (char *) ++ inodep, block, offset, ++ sizeof(*inodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ frag_blk = SQUASHFS_INVALID_BLK; ++ if (inodep->fragment != SQUASHFS_INVALID_FRAG && ++ !get_fragment_location_2(s, ++ inodep->fragment, &frag_blk, &frag_size)) ++ goto failed_read; ++ ++ 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; ++ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; ++ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; ++ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; ++ SQUASHFS_I(i)->start_block = inodep->start_block; ++ SQUASHFS_I(i)->u.s1.block_list_start = next_block; ++ SQUASHFS_I(i)->offset = next_offset; ++ i->i_data.a_ops = &squashfs_aops; ++ ++ TRACE("File inode %x:%x, start_block %x, " ++ "block_list_start %llx, offset %x\n", ++ SQUASHFS_INODE_BLK(inode), offset, ++ inodep->start_block, next_block, ++ next_offset); ++ break; ++ } ++ case SQUASHFS_DIR_TYPE: { ++ struct squashfs_dir_inode_header_2 *inodep = &id.dir; ++ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, (char *) ++ sinodep, block, offset, ++ sizeof(*sinodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, (char *) ++ inodep, block, offset, ++ sizeof(*inodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ i->i_size = inodep->file_size; ++ i->i_op = &squashfs_dir_inode_ops_2; ++ i->i_fop = &squashfs_dir_ops_2; ++ 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; ++ SQUASHFS_I(i)->u.s2.parent_inode = 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_LDIR_TYPE: { ++ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; ++ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, (char *) ++ sinodep, block, offset, ++ sizeof(*sinodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, ++ sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, (char *) ++ inodep, block, offset, ++ sizeof(*inodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ i->i_size = inodep->file_size; ++ i->i_op = &squashfs_dir_inode_ops_2; ++ i->i_fop = &squashfs_dir_ops_2; ++ 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_start = next_block; ++ SQUASHFS_I(i)->u.s2.directory_index_offset = ++ next_offset; ++ SQUASHFS_I(i)->u.s2.directory_index_count = ++ inodep->i_count; ++ SQUASHFS_I(i)->u.s2.parent_inode = 0; ++ ++ TRACE("Long 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: { ++ struct squashfs_symlink_inode_header_2 *inodep = ++ &id.symlink; ++ struct squashfs_symlink_inode_header_2 *sinodep = ++ &sid.symlink; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, (char *) ++ sinodep, block, offset, ++ sizeof(*sinodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, ++ sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, (char *) ++ inodep, block, offset, ++ sizeof(*inodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ 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 %llx, " ++ "offset %x\n", ++ SQUASHFS_INODE_BLK(inode), offset, ++ next_block, next_offset); ++ break; ++ } ++ case SQUASHFS_BLKDEV_TYPE: ++ case SQUASHFS_CHRDEV_TYPE: { ++ struct squashfs_dev_inode_header_2 *inodep = &id.dev; ++ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; ++ ++ if (msblk->swap) { ++ if (!squashfs_get_cached_block(s, (char *) ++ sinodep, block, offset, ++ sizeof(*sinodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); ++ } else ++ if (!squashfs_get_cached_block(s, (char *) ++ inodep, block, offset, ++ sizeof(*inodep), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ 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_FIFO_TYPE: ++ case SQUASHFS_SOCKET_TYPE: { ++ ++ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) ++ ? S_IFIFO : S_IFSOCK; ++ 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; ++ } ++ ++ return 1; ++ ++failed_read: ++ ERROR("Unable to read inode [%x:%x]\n", block, offset); ++ ++failed_read1: ++ return 0; ++} ++ ++ ++static int get_dir_index_using_offset(struct super_block *s, long long ++ *next_block, unsigned int *next_offset, ++ long long index_start, ++ unsigned int index_offset, int i_count, ++ long long f_pos) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ int i, length = 0; ++ struct squashfs_dir_index_2 index; ++ ++ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", ++ i_count, (unsigned int) f_pos); ++ ++ if (f_pos == 0) ++ goto finish; ++ ++ for (i = 0; i < i_count; i++) { ++ if (msblk->swap) { ++ struct squashfs_dir_index_2 sindex; ++ squashfs_get_cached_block(s, (char *) &sindex, ++ index_start, index_offset, ++ sizeof(sindex), &index_start, ++ &index_offset); ++ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); ++ } else ++ squashfs_get_cached_block(s, (char *) &index, ++ index_start, index_offset, ++ sizeof(index), &index_start, ++ &index_offset); ++ ++ if (index.index > f_pos) ++ break; ++ ++ squashfs_get_cached_block(s, NULL, index_start, index_offset, ++ index.size + 1, &index_start, ++ &index_offset); ++ ++ length = index.index; ++ *next_block = index.start_block + sblk->directory_table_start; ++ } ++ ++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; ++ ++finish: ++ return length; ++} ++ ++ ++static int get_dir_index_using_name(struct super_block *s, long long ++ *next_block, unsigned int *next_offset, ++ long long index_start, ++ unsigned int index_offset, int i_count, ++ const char *name, int size) ++{ ++ struct squashfs_sb_info *msblk = s->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ int i, length = 0; ++ struct squashfs_dir_index_2 *index; ++ char *str; ++ ++ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); ++ ++ if (!(str = kmalloc(sizeof(struct squashfs_dir_index) + ++ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) { ++ ERROR("Failed to allocate squashfs_dir_index\n"); ++ goto failure; ++ } ++ ++ index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1); ++ strncpy(str, name, size); ++ str[size] = '\0'; ++ ++ for (i = 0; i < i_count; i++) { ++ if (msblk->swap) { ++ struct squashfs_dir_index_2 sindex; ++ squashfs_get_cached_block(s, (char *) &sindex, ++ index_start, index_offset, ++ sizeof(sindex), &index_start, ++ &index_offset); ++ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); ++ } else ++ squashfs_get_cached_block(s, (char *) index, ++ index_start, index_offset, ++ sizeof(struct squashfs_dir_index_2), ++ &index_start, &index_offset); ++ ++ squashfs_get_cached_block(s, index->name, index_start, ++ index_offset, index->size + 1, ++ &index_start, &index_offset); ++ ++ index->name[index->size + 1] = '\0'; ++ ++ if (strcmp(index->name, str) > 0) ++ break; ++ ++ length = index->index; ++ *next_block = index->start_block + sblk->directory_table_start; ++ } ++ ++ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; ++ kfree(str); ++failure: ++ return length; ++} ++ ++ ++static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) ++{ ++ struct inode *i = file->f_dentry->d_inode; ++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ long long next_block = SQUASHFS_I(i)->start_block + ++ sblk->directory_table_start; ++ int next_offset = SQUASHFS_I(i)->offset, length = 0, ++ dir_count; ++ struct squashfs_dir_header_2 dirh; ++ struct squashfs_dir_entry_2 *dire; ++ ++ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); ++ ++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + ++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { ++ ERROR("Failed to allocate squashfs_dir_entry\n"); ++ goto finish; ++ } ++ ++ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_start, ++ SQUASHFS_I(i)->u.s2.directory_index_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_count, ++ file->f_pos); ++ ++ while (length < i_size_read(i)) { ++ /* read directory header */ ++ if (msblk->swap) { ++ struct squashfs_dir_header_2 sdirh; ++ ++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, ++ next_block, next_offset, sizeof(sdirh), ++ &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdirh); ++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, ++ next_block, next_offset, sizeof(dirh), ++ &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(dirh); ++ } ++ ++ dir_count = dirh.count + 1; ++ while (dir_count--) { ++ if (msblk->swap) { ++ struct squashfs_dir_entry_2 sdire; ++ if (!squashfs_get_cached_block(i->i_sb, (char *) ++ &sdire, next_block, next_offset, ++ sizeof(sdire), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdire); ++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, (char *) ++ dire, next_block, next_offset, ++ sizeof(*dire), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(*dire); ++ } ++ ++ if (!squashfs_get_cached_block(i->i_sb, dire->name, ++ next_block, next_offset, ++ dire->size + 1, &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ length += dire->size + 1; ++ ++ if (file->f_pos >= length) ++ continue; ++ ++ dire->name[dire->size + 1] = '\0'; ++ ++ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", ++ (unsigned int) dirent, dire->name, ++ dire->size + 1, (int) file->f_pos, ++ dirh.start_block, dire->offset, ++ squashfs_filetype_table[dire->type]); ++ ++ if (filldir(dirent, dire->name, dire->size + 1, ++ file->f_pos, SQUASHFS_MK_VFS_INODE( ++ dirh.start_block, dire->offset), ++ squashfs_filetype_table[dire->type]) ++ < 0) { ++ TRACE("Filldir returned less than 0\n"); ++ goto finish; ++ } ++ file->f_pos = length; ++ } ++ } ++ ++finish: ++ kfree(dire); ++ return 0; ++ ++failed_read: ++ ERROR("Unable to read directory block [%llx:%x]\n", next_block, ++ next_offset); ++ kfree(dire); ++ return 0; ++} ++ ++ ++static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, ++ struct nameidata *nd) ++{ ++ const unsigned char *name = dentry->d_name.name; ++ int len = dentry->d_name.len; ++ struct inode *inode = NULL; ++ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ long long next_block = SQUASHFS_I(i)->start_block + ++ sblk->directory_table_start; ++ int next_offset = SQUASHFS_I(i)->offset, length = 0, ++ dir_count; ++ struct squashfs_dir_header_2 dirh; ++ struct squashfs_dir_entry_2 *dire; ++ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; ++ ++ TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset); ++ ++ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) + ++ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) { ++ ERROR("Failed to allocate squashfs_dir_entry\n"); ++ goto exit_loop; ++ } ++ ++ if (len > SQUASHFS_NAME_LEN) ++ goto exit_loop; ++ ++ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_start, ++ SQUASHFS_I(i)->u.s2.directory_index_offset, ++ SQUASHFS_I(i)->u.s2.directory_index_count, name, ++ len); ++ ++ while (length < i_size_read(i)) { ++ /* read directory header */ ++ if (msblk->swap) { ++ struct squashfs_dir_header_2 sdirh; ++ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, ++ next_block, next_offset, sizeof(sdirh), ++ &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdirh); ++ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, ++ next_block, next_offset, sizeof(dirh), ++ &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(dirh); ++ } ++ ++ dir_count = dirh.count + 1; ++ while (dir_count--) { ++ if (msblk->swap) { ++ struct squashfs_dir_entry_2 sdire; ++ if (!squashfs_get_cached_block(i->i_sb, (char *) ++ &sdire, next_block,next_offset, ++ sizeof(sdire), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(sdire); ++ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); ++ } else { ++ if (!squashfs_get_cached_block(i->i_sb, (char *) ++ dire, next_block,next_offset, ++ sizeof(*dire), &next_block, ++ &next_offset)) ++ goto failed_read; ++ ++ length += sizeof(*dire); ++ } ++ ++ if (!squashfs_get_cached_block(i->i_sb, dire->name, ++ next_block, next_offset, dire->size + 1, ++ &next_block, &next_offset)) ++ goto failed_read; ++ ++ length += dire->size + 1; ++ ++ if (sorted && name[0] < dire->name[0]) ++ goto exit_loop; ++ ++ if ((len == dire->size + 1) && !strncmp(name, ++ dire->name, len)) { ++ squashfs_inode_t ino = ++ SQUASHFS_MKINODE(dirh.start_block, ++ dire->offset); ++ unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block, ++ dire->offset); ++ ++ TRACE("calling squashfs_iget for directory " ++ "entry %s, inode %x:%x, %lld\n", name, ++ dirh.start_block, dire->offset, ino); ++ ++ inode = squashfs_iget(i->i_sb, ino, inode_number); ++ ++ goto exit_loop; ++ } ++ } ++ } ++ ++exit_loop: ++ kfree(dire); ++ d_add(dentry, inode); ++ return ERR_PTR(0); ++ ++failed_read: ++ ERROR("Unable to read directory block [%llx:%x]\n", next_block, ++ next_offset); ++ goto exit_loop; ++} ++ ++ ++int squashfs_2_0_supported(struct squashfs_sb_info *msblk) ++{ ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ ++ msblk->read_inode = squashfs_read_inode_2; ++ msblk->read_fragment_index_table = read_fragment_index_table_2; ++ ++ sblk->bytes_used = sblk->bytes_used_2; ++ sblk->uid_start = sblk->uid_start_2; ++ sblk->guid_start = sblk->guid_start_2; ++ sblk->inode_table_start = sblk->inode_table_start_2; ++ sblk->directory_table_start = sblk->directory_table_start_2; ++ sblk->fragment_table_start = sblk->fragment_table_start_2; ++ ++ return 1; ++} +diff -uNr a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h +--- a/fs/squashfs/squashfs.h 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/squashfs.h 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,122 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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 CONFIG_SQUASHFS_1_0_COMPATIBILITY ++#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY ++#endif ++ ++#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) ++ ++static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) ++{ ++ return list_entry(inode, struct squashfs_inode_info, vfs_inode); ++} ++ ++/* block.c */ ++extern unsigned int squashfs_read_data(struct super_block *, char *, ++ long long, unsigned int, long long *, int); ++extern int squashfs_get_cached_block(struct super_block *, void *, ++ long long, unsigned int, int, long long *, unsigned int *); ++ ++/* cache.c */ ++extern struct squashfs_cache_entry *squashfs_cache_get(struct super_block *, ++ struct squashfs_cache *, long long, int); ++extern void squashfs_cache_put(struct squashfs_cache *, ++ struct squashfs_cache_entry *); ++extern void squashfs_cache_delete(struct squashfs_cache *); ++extern struct squashfs_cache *squashfs_cache_init(char *, int, int, int); ++ ++/* export.c */ ++extern int read_inode_lookup_table(struct super_block *); ++ ++/* file.c */ ++extern long long read_blocklist(struct inode *, int, int, char *, ++ unsigned short **, unsigned int *); ++ ++/* fragment.c */ ++extern int get_fragment_location(struct super_block *, unsigned int, ++ long long *, unsigned int *); ++extern void release_cached_fragment(struct squashfs_sb_info *, ++ struct squashfs_cache_entry *); ++extern struct squashfs_cache_entry *get_cached_fragment(struct super_block *, ++ long long, int); ++extern int read_fragment_index_table(struct super_block *); ++ ++/* id.c */ ++extern int get_id(struct super_block *, unsigned int, unsigned int *); ++extern int read_id_index_table(struct super_block *); ++ ++/* inode.c */ ++extern struct inode *squashfs_iget(struct super_block *, squashfs_inode_t, ++ unsigned int); ++extern int squashfs_read_inode(struct inode *, squashfs_inode_t); ++ ++/* ++ * Inodes and files operations ++ */ ++ ++/* dir.c */ ++extern const struct file_operations squashfs_dir_ops; ++ ++/* export.c */ ++extern const struct export_operations squashfs_export_ops; ++ ++/* file.c */ ++extern const struct address_space_operations squashfs_aops; ++ ++/* namei.c */ ++extern const struct inode_operations squashfs_dir_inode_ops; ++ ++/* symlink.c */ ++extern const struct address_space_operations squashfs_symlink_aops; ++ ++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY ++extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); ++#else ++static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) ++{ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY ++extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); ++#else ++static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) ++{ ++ return 0; ++} ++#endif +diff -uNr a/fs/squashfs/super.c b/fs/squashfs/super.c +--- a/fs/squashfs/super.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/super.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,381 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * super.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++static struct file_system_type squashfs_fs_type; ++static struct super_operations squashfs_super_ops; ++ ++static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) ++{ ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ ++ msblk->read_inode = squashfs_read_inode; ++ msblk->read_blocklist = read_blocklist; ++ msblk->read_fragment_index_table = read_fragment_index_table; ++ ++ if (sblk->s_major == 1) { ++ if (!squashfs_1_0_supported(msblk)) { ++ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " ++ "are unsupported\n"); ++ SERROR("Please recompile with Squashfs 1.0 support enabled\n"); ++ return 0; ++ } ++ } else if (sblk->s_major == 2) { ++ if (!squashfs_2_0_supported(msblk)) { ++ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " ++ "are unsupported\n"); ++ SERROR("Please recompile with Squashfs 2.0 support enabled\n"); ++ return 0; ++ } ++ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > ++ SQUASHFS_MINOR) { ++ SERROR("Major/Minor mismatch, trying to mount newer %d.%d " ++ "filesystem\n", sblk->s_major, sblk->s_minor); ++ SERROR("Please update your kernel\n"); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++ ++static int squashfs_fill_super(struct super_block *s, void *data, int silent) ++{ ++ struct squashfs_sb_info *msblk; ++ struct squashfs_super_block *sblk; ++ char b[BDEVNAME_SIZE]; ++ struct inode *root; ++ ++ TRACE("Entered squashfs_fill_superblock\n"); ++ ++ s->s_fs_info = kzalloc(sizeof(struct squashfs_sb_info), GFP_KERNEL); ++ if (s->s_fs_info == NULL) { ++ ERROR("Failed to allocate superblock\n"); ++ goto failure; ++ } ++ msblk = s->s_fs_info; ++ ++ msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()); ++ if (msblk->stream.workspace == NULL) { ++ ERROR("Failed to allocate zlib workspace\n"); ++ goto failure; ++ } ++ sblk = &msblk->sblk; ++ ++ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); ++ msblk->devblksize_log2 = ffz(~msblk->devblksize); ++ ++ mutex_init(&msblk->read_data_mutex); ++ mutex_init(&msblk->read_page_mutex); ++ mutex_init(&msblk->meta_index_mutex); ++ ++ /* sblk->bytes_used is checked in squashfs_read_data to ensure reads are not ++ * beyond filesystem end. As we're using squashfs_read_data to read sblk here, ++ * first set sblk->bytes_used to a useful value */ ++ sblk->bytes_used = sizeof(struct squashfs_super_block); ++ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, ++ sizeof(struct squashfs_super_block) | ++ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) { ++ SERROR("unable to read superblock\n"); ++ goto failed_mount; ++ } ++ ++ /* Check it is a SQUASHFS superblock */ ++ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { ++ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { ++ struct squashfs_super_block ssblk; ++ ++ WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", ++ bdevname(s->s_bdev, b)); ++ ++ //SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); ++ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); ++ msblk->swap = 1; ++ } else { ++ SERROR("Can't find a SQUASHFS superblock on %s\n", ++ bdevname(s->s_bdev, b)); ++ goto failed_mount; ++ } ++ } ++ ++ /* Check the MAJOR & MINOR versions */ ++ if(!supported_squashfs_filesystem(msblk, silent)) ++ goto failed_mount; ++ ++ /* Check the filesystem does not extend beyond the end of the ++ block device */ ++ if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode)) ++ goto failed_mount; ++ ++ /* Check the root inode for sanity */ ++ if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE) ++ goto failed_mount; ++ ++ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); ++ TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sblk->flags) ++ ? "un" : ""); ++ TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) ++ ? "un" : ""); ++ TRACE("Check data is %spresent in the filesystem\n", ++ SQUASHFS_CHECK_DATA(sblk->flags) ? "" : "not "); ++ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); ++ TRACE("Block size %d\n", sblk->block_size); ++ TRACE("Number of inodes %d\n", sblk->inodes); ++ if (sblk->s_major > 1) ++ TRACE("Number of fragments %d\n", sblk->fragments); ++ TRACE("Number of ids %d\n", sblk->no_ids); ++ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); ++ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); ++ if (sblk->s_major > 1) ++ TRACE("sblk->fragment_table_start %llx\n", sblk->fragment_table_start); ++ TRACE("sblk->id_table_start %llx\n", sblk->id_table_start); ++ ++ s->s_maxbytes = MAX_LFS_FILESIZE; ++ s->s_flags |= MS_RDONLY; ++ s->s_op = &squashfs_super_ops; ++ ++ msblk->block_cache = squashfs_cache_init("metadata", SQUASHFS_CACHED_BLKS, ++ SQUASHFS_METADATA_SIZE, 0); ++ if (msblk->block_cache == NULL) ++ goto failed_mount; ++ ++ /* Allocate read_page block */ ++ msblk->read_page = vmalloc(sblk->block_size); ++ if (msblk->read_page == NULL) { ++ ERROR("Failed to allocate read_page block\n"); ++ goto failed_mount; ++ } ++ ++ /* Allocate and read id index table */ ++ if (read_id_index_table(s) == 0) ++ goto failed_mount; ++ ++ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) ++ goto allocate_root; ++ ++ msblk->fragment_cache = squashfs_cache_init("fragment", ++ SQUASHFS_CACHED_FRAGMENTS, sblk->block_size, 1); ++ if (msblk->fragment_cache == NULL) ++ goto failed_mount; ++ ++ /* Allocate and read fragment index table */ ++ if (msblk->read_fragment_index_table(s) == 0) ++ goto failed_mount; ++ ++ if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK) ++ goto allocate_root; ++ ++ /* Allocate and read inode lookup table */ ++ if (read_inode_lookup_table(s) == 0) ++ goto failed_mount; ++ ++ s->s_export_op = &squashfs_export_ops; ++ ++allocate_root: ++ root = new_inode(s); ++ if ((msblk->read_inode)(root, sblk->root_inode) == 0) ++ goto failed_mount; ++ insert_inode_hash(root); ++ ++ s->s_root = d_alloc_root(root); ++ if (s->s_root == NULL) { ++ ERROR("Root inode create failed\n"); ++ iput(root); ++ goto failed_mount; ++ } ++ ++ TRACE("Leaving squashfs_fill_super\n"); ++ return 0; ++ ++failed_mount: ++ kfree(msblk->inode_lookup_table); ++ kfree(msblk->fragment_index); ++ squashfs_cache_delete(msblk->fragment_cache); ++ kfree(msblk->id_table); ++ vfree(msblk->read_page); ++ squashfs_cache_delete(msblk->block_cache); ++ kfree(msblk->fragment_index_2); ++ vfree(msblk->stream.workspace); ++ kfree(s->s_fs_info); ++ s->s_fs_info = NULL; ++ return -EINVAL; ++ ++failure: ++ return -ENOMEM; ++} ++ ++ ++static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) ++{ ++ struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; ++ struct squashfs_super_block *sblk = &msblk->sblk; ++ ++ TRACE("Entered squashfs_statfs\n"); ++ ++ buf->f_type = SQUASHFS_MAGIC; ++ buf->f_bsize = sblk->block_size; ++ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; ++ buf->f_bfree = buf->f_bavail = 0; ++ buf->f_files = sblk->inodes; ++ buf->f_ffree = 0; ++ buf->f_namelen = SQUASHFS_NAME_LEN; ++ ++ return 0; ++} ++ ++ ++static int squashfs_remount(struct super_block *s, int *flags, char *data) ++{ ++ *flags |= MS_RDONLY; ++ return 0; ++} ++ ++ ++static void squashfs_put_super(struct super_block *s) ++{ ++ if (s->s_fs_info) { ++ struct squashfs_sb_info *sbi = s->s_fs_info; ++ squashfs_cache_delete(sbi->block_cache); ++ squashfs_cache_delete(sbi->fragment_cache); ++ vfree(sbi->read_page); ++ kfree(sbi->id_table); ++ kfree(sbi->fragment_index); ++ kfree(sbi->fragment_index_2); ++ kfree(sbi->meta_index); ++ vfree(sbi->stream.workspace); ++ kfree(s->s_fs_info); ++ s->s_fs_info = NULL; ++ } ++} ++ ++ ++static int squashfs_get_sb(struct file_system_type *fs_type, int flags, ++ const char *dev_name, void *data, struct vfsmount *mnt) ++{ ++ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, ++ mnt); ++} ++ ++ ++static struct kmem_cache * squashfs_inode_cachep; ++ ++ ++static void init_once(void *foo) ++{ ++ struct squashfs_inode_info *ei = foo; ++ ++ inode_init_once(&ei->vfs_inode); ++} ++ ++ ++static int __init init_inodecache(void) ++{ ++ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", ++ sizeof(struct squashfs_inode_info), 0, ++ SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, init_once); ++ if (squashfs_inode_cachep == NULL) ++ return -ENOMEM; ++ return 0; ++} ++ ++ ++static void destroy_inodecache(void) ++{ ++ kmem_cache_destroy(squashfs_inode_cachep); ++} ++ ++ ++static int __init init_squashfs_fs(void) ++{ ++ int err = init_inodecache(); ++ if (err) ++ goto out; ++ ++ printk(KERN_INFO "squashfs: version 4.0-CVS (2008/07/27) " ++ "Phillip Lougher\n"); ++ ++ err = register_filesystem(&squashfs_fs_type); ++ if (err) ++ destroy_inodecache(); ++ ++out: ++ return err; ++} ++ ++ ++static void __exit exit_squashfs_fs(void) ++{ ++ unregister_filesystem(&squashfs_fs_type); ++ destroy_inodecache(); ++} ++ ++ ++static struct inode *squashfs_alloc_inode(struct super_block *sb) ++{ ++ struct squashfs_inode_info *ei; ++ ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); ++ return ei ? &ei->vfs_inode : NULL; ++} ++ ++ ++static void squashfs_destroy_inode(struct inode *inode) ++{ ++ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); ++} ++ ++ ++static struct file_system_type squashfs_fs_type = { ++ .owner = THIS_MODULE, ++ .name = "squashfs", ++ .get_sb = squashfs_get_sb, ++ .kill_sb = kill_block_super, ++ .fs_flags = FS_REQUIRES_DEV ++}; ++ ++static struct super_operations squashfs_super_ops = { ++ .alloc_inode = squashfs_alloc_inode, ++ .destroy_inode = squashfs_destroy_inode, ++ .statfs = squashfs_statfs, ++ .put_super = squashfs_put_super, ++ .remount_fs = squashfs_remount ++}; ++ ++module_init(init_squashfs_fs); ++module_exit(exit_squashfs_fs); ++MODULE_DESCRIPTION("squashfs 4.0-CVS, a compressed read-only filesystem"); ++MODULE_AUTHOR("Phillip Lougher "); ++MODULE_LICENSE("GPL"); +diff -uNr a/fs/squashfs/symlink.c b/fs/squashfs/symlink.c +--- a/fs/squashfs/symlink.c 1969-12-31 16:00:00.000000000 -0800 ++++ b/fs/squashfs/symlink.c 2008-08-13 16:14:50.000000000 -0700 +@@ -0,0 +1,85 @@ ++/* ++ * Squashfs - a compressed read only filesystem for Linux ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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. ++ * ++ * symlink.c ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "squashfs.h" ++ ++static int squashfs_symlink_readpage(struct file *file, struct page *page) ++{ ++ struct inode *inode = page->mapping->host; ++ int index = page->index << PAGE_CACHE_SHIFT; ++ long long block = SQUASHFS_I(inode)->start_block; ++ int offset = SQUASHFS_I(inode)->offset; ++ void *pageaddr = kmap(page); ++ int length, bytes, avail_bytes; ++ ++ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " ++ "%llx, offset %x\n", page->index, ++ SQUASHFS_I(inode)->start_block, ++ SQUASHFS_I(inode)->offset); ++ ++ for (length = 0; length < index; length += bytes) { ++ bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, ++ offset, PAGE_CACHE_SIZE, &block, &offset); ++ if (bytes == 0) { ++ ERROR("Unable to read symbolic link [%llx:%x]\n", ++ block, offset); ++ goto skip_read; ++ } ++ } ++ ++ if (length != index) { ++ ERROR("(squashfs_symlink_readpage) length != index\n"); ++ bytes = 0; ++ goto skip_read; ++ } ++ ++ avail_bytes = min_t(int, i_size_read(inode) - length, PAGE_CACHE_SIZE); ++ ++ bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, ++ avail_bytes, &block, &offset); ++ if (bytes == 0) ++ ERROR("Unable to read symbolic link [%llx:%x]\n", block, ++ offset); ++ ++skip_read: ++ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); ++ kunmap(page); ++ flush_dcache_page(page); ++ SetPageUptodate(page); ++ unlock_page(page); ++ ++ return 0; ++} ++ ++ ++const struct address_space_operations squashfs_symlink_aops = { ++ .readpage = squashfs_symlink_readpage ++}; +diff -uNr a/include/linux/squashfs_fs.h b/include/linux/squashfs_fs.h +--- a/include/linux/squashfs_fs.h 1969-12-31 16:00:00.000000000 -0800 ++++ b/include/linux/squashfs_fs.h 2008-08-13 16:16:05.000000000 -0700 +@@ -0,0 +1,949 @@ ++#ifndef SQUASHFS_FS ++#define SQUASHFS_FS ++/* ++ * Squashfs ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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 ++ */ ++ ++#if 0 ++#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY ++#define CONFIG_SQUASHFS_2_0_COMPATIBILITY ++#endif ++#endif ++ ++#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE ++#define SQUASHFS_MAJOR 4 ++#define SQUASHFS_MINOR 0 ++#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 131072 ++#define SQUASHFS_FILE_LOG 17 ++ ++#define SQUASHFS_FILE_MAX_SIZE 1048576 ++ ++/* Max number of uids and gids */ ++#define SQUASHFS_IDS 65536 ++ ++/* Max length of filename (not 255) */ ++#define SQUASHFS_NAME_LEN 256 ++ ++#define SQUASHFS_INVALID ((long long) 0xffffffffffff) ++#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) ++#define SQUASHFS_INVALID_BLK ((long long) -1) ++#define SQUASHFS_USED_BLK ((long long) -2) ++ ++/* 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_EXPORT 7 ++ ++#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_EXPORTABLE(flags) SQUASHFS_BIT(flags, \ ++ SQUASHFS_EXPORT) ++ ++#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ ++ SQUASHFS_CHECK) ++ ++#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ ++ duplicate_checking, exportable) (noi | (nod << 1) | (check_data << 2) \ ++ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ ++ (duplicate_checking << 6) | (exportable << 7)) ++ ++/* 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 ++#define SQUASHFS_LREG_TYPE 9 ++ ++/* 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) ++ ++#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_t)(((squashfs_inode_t) (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)) ++/* XXX */ ++ ++/* Translate between VFS mode and squashfs mode */ ++#define SQUASHFS_MODE(a) ((a) & 0xfff) ++ ++/* fragment and fragment table defines */ ++#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct 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(long long)) ++ ++/* inode lookup table defines */ ++#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t)) ++ ++#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \ ++ SQUASHFS_METADATA_SIZE - 1) / \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\ ++ sizeof(long long)) ++ ++/* uid lookup table defines */ ++#define SQUASHFS_ID_BYTES(A) ((A) * sizeof(unsigned int)) ++ ++#define SQUASHFS_ID_BLOCK(A) (SQUASHFS_ID_BYTES(A) / \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_ID_BLOCK_OFFSET(A) (SQUASHFS_ID_BYTES(A) % \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_ID_BLOCKS(A) ((SQUASHFS_ID_BYTES(A) + \ ++ SQUASHFS_METADATA_SIZE - 1) / \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_ID_BLOCK_BYTES(A) (SQUASHFS_ID_BLOCKS(A) *\ ++ sizeof(long long)) ++ ++/* cached data constants for filesystem */ ++#define SQUASHFS_CACHED_BLKS 8 ++ ++#define SQUASHFS_MAX_FILE_SIZE_LOG 64 ++ ++#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ ++ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) ++ ++#define SQUASHFS_MARKER_BYTE 0xff ++ ++/* meta index cache */ ++#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) ++#define SQUASHFS_META_ENTRIES 31 ++#define SQUASHFS_META_NUMBER 8 ++#define SQUASHFS_SLOTS 4 ++ ++struct meta_entry { ++ long long data_block; ++ unsigned int index_block; ++ unsigned short offset; ++ unsigned short pad; ++}; ++ ++struct meta_index { ++ unsigned int inode_number; ++ unsigned int offset; ++ unsigned short entries; ++ unsigned short skip; ++ unsigned short locked; ++ unsigned short pad; ++ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; ++}; ++ ++ ++/* ++ * definitions for structures on disk ++ */ ++ ++typedef long long squashfs_block_t; ++typedef long long squashfs_inode_t; ++ ++#define COMPRESSION_ZLIB 1 ++ ++struct squashfs_super_block { ++ unsigned int s_magic; ++ unsigned int inodes; ++ unsigned int mkfs_time /* time of filesystem creation */; ++ unsigned int block_size; ++ unsigned int fragments; ++ unsigned short compression; ++ unsigned short block_log; ++ unsigned short flags; ++ unsigned short no_ids; ++ unsigned short s_major; ++ unsigned short s_minor; ++ squashfs_inode_t root_inode; ++ long long bytes_used; ++ long long id_table_start; ++ long long xattr_table_start; ++ long long inode_table_start; ++ long long directory_table_start; ++ long long fragment_table_start; ++ long long lookup_table_start; ++}; ++ ++struct squashfs_dir_index { ++ unsigned int index; ++ unsigned int start_block; ++ unsigned int size; ++ unsigned char name[0]; ++}; ++ ++#define SQUASHFS_BASE_INODE_HEADER \ ++ unsigned short inode_type; \ ++ unsigned short mode; \ ++ unsigned short uid; \ ++ unsigned short guid; \ ++ unsigned int mtime; \ ++ unsigned int inode_number; ++ ++struct squashfs_base_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++}; ++ ++struct squashfs_ipc_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++ unsigned int nlink; ++}; ++ ++struct squashfs_dev_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++ unsigned int nlink; ++ unsigned int rdev; ++}; ++ ++struct squashfs_symlink_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++ unsigned int nlink; ++ unsigned int symlink_size; ++ char symlink[0]; ++}; ++ ++struct squashfs_reg_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++ unsigned int start_block; ++ unsigned int fragment; ++ unsigned int offset; ++ unsigned int file_size; ++ unsigned short block_list[0]; ++}; ++ ++struct squashfs_lreg_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++ squashfs_block_t start_block; ++ long long file_size; ++ long long sparse; ++ unsigned int nlink; ++ unsigned int fragment; ++ unsigned int offset; ++ unsigned int xattr; ++ unsigned short block_list[0]; ++}; ++ ++struct squashfs_dir_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++ unsigned int start_block; ++ unsigned int nlink; ++ unsigned short file_size; ++ unsigned short offset; ++ unsigned int parent_inode; ++}; ++ ++struct squashfs_ldir_inode_header { ++ SQUASHFS_BASE_INODE_HEADER; ++ unsigned int nlink; ++ unsigned int file_size; ++ unsigned int start_block; ++ unsigned int parent_inode; ++ unsigned short i_count; ++ unsigned short offset; ++ struct squashfs_dir_index index[0]; ++}; ++ ++union squashfs_inode_header { ++ struct squashfs_base_inode_header base; ++ struct squashfs_dev_inode_header dev; ++ struct squashfs_symlink_inode_header symlink; ++ struct squashfs_reg_inode_header reg; ++ struct squashfs_lreg_inode_header lreg; ++ struct squashfs_dir_inode_header dir; ++ struct squashfs_ldir_inode_header ldir; ++ struct squashfs_ipc_inode_header ipc; ++}; ++ ++struct squashfs_dir_entry { ++ unsigned short offset; ++ short inode_number; ++ unsigned short type; ++ unsigned short size; ++ char name[0]; ++}; ++ ++struct squashfs_dir_header { ++ unsigned int count; ++ unsigned int start_block; ++ unsigned int inode_number; ++}; ++ ++struct squashfs_fragment_entry { ++ long long start_block; ++ unsigned int size; ++ unsigned int unused; ++}; ++ ++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_START \ ++ int bits;\ ++ int b_pos;\ ++ unsigned long long val;\ ++ unsigned char *s;\ ++ unsigned char *d; ++ ++#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ ++ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ ++ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ ++ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ ++ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ ++ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ ++ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ ++ SQUASHFS_SWAP((s)->directory_table_start_2, 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_2, d, 472, 32);\ ++ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ ++ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ ++ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ ++ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ ++ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ ++ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ ++ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\ ++} ++ ++#define SQUASHFS_SWAP_BASE_INODE_CORE(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);\ ++ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ ++ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); ++ ++#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ ++} ++ ++#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ ++ sizeof(struct squashfs_ipc_inode_header))\ ++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ ++} ++ ++#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ ++ sizeof(struct squashfs_dev_inode_header)); \ ++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ ++ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ ++} ++ ++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ ++ sizeof(struct squashfs_symlink_inode_header));\ ++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ ++ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ ++} ++ ++#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ ++ sizeof(struct squashfs_reg_inode_header));\ ++ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ ++ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ ++ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ ++ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ ++} ++ ++#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ ++ sizeof(struct squashfs_lreg_inode_header));\ ++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ ++ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ ++ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ ++ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ ++ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ ++} ++ ++#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ ++ sizeof(struct squashfs_dir_inode_header));\ ++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ ++ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ ++ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ ++ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ ++ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ ++} ++ ++#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ ++ sizeof(struct squashfs_ldir_inode_header));\ ++ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ ++ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ ++ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ ++ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ ++ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ ++ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ ++} ++ ++#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ ++ SQUASHFS_SWAP((s)->index, d, 0, 32);\ ++ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ ++ SQUASHFS_SWAP((s)->size, d, 64, 8);\ ++} ++ ++#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ ++ SQUASHFS_SWAP((s)->count, d, 0, 8);\ ++ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ ++ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ ++} ++ ++#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ ++ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ ++ SQUASHFS_SWAP((s)->type, d, 13, 3);\ ++ SQUASHFS_SWAP((s)->size, d, 16, 8);\ ++ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ ++} ++ ++#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ ++ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ ++ SQUASHFS_SWAP((s)->size, d, 64, 32);\ ++} ++ ++#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1) ++ ++#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ ++ int entry;\ ++ int bit_position;\ ++ SQUASHFS_SWAP_START\ ++ 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_SWAP_START\ ++ 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_LONG_LONGS(s, d, n) {\ ++ int entry;\ ++ int bit_position;\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, n * 8);\ ++ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ ++ 64)\ ++ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ ++} ++ ++#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ ++ int entry;\ ++ int bit_position;\ ++ SQUASHFS_SWAP_START\ ++ 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_LONG_LONGS(s, d, n) ++#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) ++#define SQUASHFS_SWAP_ID_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) ++ ++#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY ++ ++struct squashfs_base_inode_header_1 { ++ 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)); ++ ++struct squashfs_ipc_inode_header_1 { ++ 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)); ++ ++struct squashfs_dev_inode_header_1 { ++ 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)); ++ ++struct squashfs_symlink_inode_header_1 { ++ 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)); ++ ++struct squashfs_reg_inode_header_1 { ++ 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; ++ unsigned int start_block; ++ unsigned int file_size:32; ++ unsigned short block_list[0]; ++} __attribute__ ((packed)); ++ ++struct squashfs_dir_inode_header_1 { ++ 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)); ++ ++union squashfs_inode_header_1 { ++ struct squashfs_base_inode_header_1 base; ++ struct squashfs_dev_inode_header_1 dev; ++ struct squashfs_symlink_inode_header_1 symlink; ++ struct squashfs_reg_inode_header_1 reg; ++ struct squashfs_dir_inode_header_1 dir; ++ struct squashfs_ipc_inode_header_1 ipc; ++}; ++ ++#define SQUASHFS_SWAP_BASE_INODE_CORE_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_BASE_INODE_HEADER_1(s, d, n) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ ++} ++ ++#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ ++ sizeof(struct 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_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ ++ sizeof(struct squashfs_dev_inode_header_1));\ ++ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ ++} ++ ++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ ++ sizeof(struct squashfs_symlink_inode_header_1));\ ++ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ ++} ++ ++#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ ++ sizeof(struct 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, 32);\ ++} ++ ++#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ ++ sizeof(struct 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 CONFIG_SQUASHFS_2_0_COMPATIBILITY ++ ++struct squashfs_dir_index_2 { ++ unsigned int index:27; ++ unsigned int start_block:29; ++ unsigned char size; ++ unsigned char name[0]; ++} __attribute__ ((packed)); ++ ++struct squashfs_base_inode_header_2 { ++ 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)); ++ ++struct squashfs_ipc_inode_header_2 { ++ 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)); ++ ++struct squashfs_dev_inode_header_2 { ++ 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)); ++ ++struct squashfs_symlink_inode_header_2 { ++ 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)); ++ ++struct squashfs_reg_inode_header_2 { ++ 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; ++ unsigned int start_block; ++ unsigned int fragment; ++ unsigned int offset; ++ unsigned int file_size:32; ++ unsigned short block_list[0]; ++} __attribute__ ((packed)); ++ ++struct squashfs_dir_inode_header_2 { ++ 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)); ++ ++struct squashfs_ldir_inode_header_2 { ++ 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; ++ struct squashfs_dir_index_2 index[0]; ++} __attribute__ ((packed)); ++ ++union squashfs_inode_header_2 { ++ struct squashfs_base_inode_header_2 base; ++ struct squashfs_dev_inode_header_2 dev; ++ struct squashfs_symlink_inode_header_2 symlink; ++ struct squashfs_reg_inode_header_2 reg; ++ struct squashfs_dir_inode_header_2 dir; ++ struct squashfs_ldir_inode_header_2 ldir; ++ struct squashfs_ipc_inode_header_2 ipc; ++}; ++ ++struct squashfs_dir_header_2 { ++ unsigned int count:8; ++ unsigned int start_block:24; ++} __attribute__ ((packed)); ++ ++struct squashfs_dir_entry_2 { ++ unsigned int offset:13; ++ unsigned int type:3; ++ unsigned int size:8; ++ char name[0]; ++} __attribute__ ((packed)); ++ ++struct squashfs_fragment_entry_2 { ++ unsigned int start_block; ++ unsigned int size; ++} __attribute__ ((packed)); ++ ++#define SQUASHFS_SWAP_BASE_INODE_CORE_2(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_BASE_INODE_HEADER_2(s, d, n) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ ++} ++ ++#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ ++ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) ++ ++#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ ++ sizeof(struct squashfs_dev_inode_header_2)); \ ++ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ ++} ++ ++#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ ++ sizeof(struct squashfs_symlink_inode_header_2));\ ++ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ ++} ++ ++#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ ++ sizeof(struct squashfs_reg_inode_header_2));\ ++ 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, 32);\ ++} ++ ++#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ ++ sizeof(struct squashfs_dir_inode_header_2));\ ++ 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_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ ++ sizeof(struct squashfs_ldir_inode_header_2));\ ++ 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_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ ++ 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_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ ++ SQUASHFS_SWAP((s)->count, d, 0, 8);\ ++ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ ++} ++ ++#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ ++ 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_2(s, d) {\ ++ SQUASHFS_SWAP_START\ ++ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ ++ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ ++ SQUASHFS_SWAP((s)->size, d, 32, 32);\ ++} ++ ++#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) ++ ++/* fragment and fragment table defines */ ++#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) ++ ++#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ ++ SQUASHFS_METADATA_SIZE - 1) / \ ++ SQUASHFS_METADATA_SIZE) ++ ++#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ ++ sizeof(int)) ++ ++#endif ++ ++#ifdef __KERNEL__ ++ ++/* ++ * macros used to swap each structure entry, taking into account ++ * bitfields and different bitfield placing conventions on differing ++ * architectures ++ */ ++ ++#include ++ ++#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) {\ ++ b_pos = pos % 8;\ ++ val = 0;\ ++ s = (unsigned char *)p + (pos / 8);\ ++ 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 -uNr a/include/linux/squashfs_fs_i.h b/include/linux/squashfs_fs_i.h +--- a/include/linux/squashfs_fs_i.h 1969-12-31 16:00:00.000000000 -0800 ++++ b/include/linux/squashfs_fs_i.h 2008-08-13 16:16:05.000000000 -0700 +@@ -0,0 +1,45 @@ ++#ifndef SQUASHFS_FS_I ++#define SQUASHFS_FS_I ++/* ++ * Squashfs ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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 ++ */ ++ ++struct squashfs_inode_info { ++ long long start_block; ++ unsigned int offset; ++ union { ++ struct { ++ long long fragment_start_block; ++ unsigned int fragment_size; ++ unsigned int fragment_offset; ++ long long block_list_start; ++ } s1; ++ struct { ++ long long directory_index_start; ++ unsigned int directory_index_offset; ++ unsigned int directory_index_count; ++ unsigned int parent_inode; ++ } s2; ++ } u; ++ struct inode vfs_inode; ++}; ++#endif +diff -uNr a/include/linux/squashfs_fs_sb.h b/include/linux/squashfs_fs_sb.h +--- a/include/linux/squashfs_fs_sb.h 1969-12-31 16:00:00.000000000 -0800 ++++ b/include/linux/squashfs_fs_sb.h 2008-08-13 16:16:05.000000000 -0700 +@@ -0,0 +1,78 @@ ++#ifndef SQUASHFS_FS_SB ++#define SQUASHFS_FS_SB ++/* ++ * Squashfs ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 ++ * Phillip Lougher ++ * ++ * 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 ++ ++struct squashfs_cache_entry { ++ long long block; ++ int length; ++ int locked; ++ long long next_index; ++ char pending; ++ char error; ++ int waiting; ++ wait_queue_head_t wait_queue; ++ char *data; ++}; ++ ++struct squashfs_cache { ++ char *name; ++ int entries; ++ int block_size; ++ int next_blk; ++ int waiting; ++ int unused_blks; ++ int use_vmalloc; ++ spinlock_t lock; ++ wait_queue_head_t wait_queue; ++ struct squashfs_cache_entry entry[0]; ++}; ++ ++struct squashfs_sb_info { ++ struct squashfs_super_block sblk; ++ int devblksize; ++ int devblksize_log2; ++ int swap; ++ struct squashfs_cache *block_cache; ++ struct squashfs_cache *fragment_cache; ++ int next_meta_index; ++ unsigned int *id_table; ++ long long *fragment_index; ++ unsigned int *fragment_index_2; ++ char *read_page; ++ struct mutex read_data_mutex; ++ struct mutex read_page_mutex; ++ struct mutex meta_index_mutex; ++ struct meta_index *meta_index; ++ z_stream stream; ++ long long *inode_lookup_table; ++ int (*read_inode)(struct inode *i, squashfs_inode_t \ ++ inode); ++ long long (*read_blocklist)(struct inode *inode, int \ ++ index, int readahead_blks, char *block_list, \ ++ unsigned short **block_p, unsigned int *bsize); ++ int (*read_fragment_index_table)(struct super_block *s); ++}; ++#endif -- cgit v1.2.3