summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/Config.in1
-rw-r--r--fs/Makefile44
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/affs/file.c4
-rw-r--r--fs/autofs/dir.c11
-rw-r--r--fs/autofs/root.c9
-rw-r--r--fs/bad_inode.c3
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/block_dev.c361
-rw-r--r--fs/buffer.c11
-rw-r--r--fs/coda/dir.c3
-rw-r--r--fs/coda/file.c2
-rw-r--r--fs/coda/psdev.c2
-rw-r--r--fs/cramfs/.cvsignore2
-rw-r--r--fs/cramfs/Makefile14
-rw-r--r--fs/cramfs/cramfs.h41
-rw-r--r--fs/cramfs/inflate/Makefile34
-rw-r--r--fs/cramfs/inflate/adler32.c48
-rw-r--r--fs/cramfs/inflate/infblock.c360
-rw-r--r--fs/cramfs/inflate/infblock.h39
-rw-r--r--fs/cramfs/inflate/infcodes.c247
-rw-r--r--fs/cramfs/inflate/infcodes.h27
-rw-r--r--fs/cramfs/inflate/inffast.c161
-rw-r--r--fs/cramfs/inflate/inffast.h17
-rw-r--r--fs/cramfs/inflate/inffixed.h151
-rw-r--r--fs/cramfs/inflate/inflate.c330
-rw-r--r--fs/cramfs/inflate/inftrees.c392
-rw-r--r--fs/cramfs/inflate/inftrees.h58
-rw-r--r--fs/cramfs/inflate/infutil.c87
-rw-r--r--fs/cramfs/inflate/infutil.h98
-rw-r--r--fs/cramfs/inflate/uncompr.c55
-rw-r--r--fs/cramfs/inflate/zconf.h90
-rw-r--r--fs/cramfs/inflate/zlib.h893
-rw-r--r--fs/cramfs/inflate/zutil.h70
-rw-r--r--fs/cramfs/inode.c484
-rw-r--r--fs/cramfs/uncompress.c60
-rw-r--r--fs/dcache.c2
-rw-r--r--fs/devices.c204
-rw-r--r--fs/devpts/inode.c6
-rw-r--r--fs/devpts/root.c11
-rw-r--r--fs/efs/dir.c2
-rw-r--r--fs/efs/file.c2
-rw-r--r--fs/efs/inode.c10
-rw-r--r--fs/exec.c43
-rw-r--r--fs/ext2/acl.c43
-rw-r--r--fs/ext2/balloc.c10
-rw-r--r--fs/ext2/dir.c4
-rw-r--r--fs/ext2/file.c15
-rw-r--r--fs/ext2/super.c49
-rw-r--r--fs/fat/dir.c181
-rw-r--r--fs/fat/inode.c9
-rw-r--r--fs/fifo.c21
-rw-r--r--fs/filesystems.c13
-rw-r--r--fs/hfs/dir_cap.c2
-rw-r--r--fs/hfs/dir_dbl.c2
-rw-r--r--fs/hfs/dir_nat.c2
-rw-r--r--fs/hfs/file.c2
-rw-r--r--fs/hfs/file_cap.c2
-rw-r--r--fs/hfs/file_hdr.c2
-rw-r--r--fs/hpfs/inode.c4
-rw-r--r--fs/inode.c8
-rw-r--r--fs/isofs/inode.c134
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/minix/inode.c13
-rw-r--r--fs/namei.c78
-rw-r--r--fs/nfs/file.c2
-rw-r--r--fs/ntfs/fs.c15
-rw-r--r--fs/open.c3
-rw-r--r--fs/openpromfs/.cvsignore2
-rw-r--r--fs/openpromfs/Makefile14
-rw-r--r--fs/openpromfs/inode.c (renamed from fs/proc/openpromfs.c)108
-rw-r--r--fs/partitions/Config.in104
-rw-r--r--fs/proc/Makefile10
-rw-r--r--fs/proc/base.c8
-rw-r--r--fs/proc/kcore.c2
-rw-r--r--fs/proc/omirr.c2
-rw-r--r--fs/proc/openprom-dev.c46
-rw-r--r--fs/proc/root.c3
-rw-r--r--fs/qnx4/BUGS11
-rw-r--r--fs/qnx4/README4
-rw-r--r--fs/qnx4/TODO9
-rw-r--r--fs/qnx4/bitmap.c25
-rw-r--r--fs/qnx4/dir.c106
-rw-r--r--fs/qnx4/file.c122
-rw-r--r--fs/qnx4/inode.c157
-rw-r--r--fs/qnx4/namei.c34
-rw-r--r--fs/qnx4/symlinks.c90
-rw-r--r--fs/read_write.c23
-rw-r--r--fs/romfs/inode.c12
-rw-r--r--fs/smbfs/file.c2
-rw-r--r--fs/stat.c121
-rw-r--r--fs/super.c186
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/udf/balloc.c4
-rw-r--r--fs/udf/dir.c2
-rw-r--r--fs/udf/file.c25
-rw-r--r--fs/udf/inode.c11
-rw-r--r--fs/udf/lowlevel.c104
-rw-r--r--fs/udf/namei.c19
-rw-r--r--fs/udf/super.c4
-rw-r--r--fs/udf/udfdecl.h4
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/ufs/file.c2
-rw-r--r--fs/ufs/namei.c5
-rw-r--r--fs/ufs/super.c6
-rw-r--r--fs/vfat/namei.c320
108 files changed, 5216 insertions, 1608 deletions
diff --git a/fs/Config.in b/fs/Config.in
index 150e1c95b..5919ef6f3 100644
--- a/fs/Config.in
+++ b/fs/Config.in
@@ -29,6 +29,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'EFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS
fi
+tristate 'Compressed ROM filessytem support' CONFIG_CRAMFS
tristate 'ISO 9660 CDROM filesystem support' CONFIG_ISO9660_FS
if [ "$CONFIG_ISO9660_FS" != "n" ]; then
bool ' Microsoft Joliet CDROM extensions' CONFIG_JOLIET
diff --git a/fs/Makefile b/fs/Makefile
index 6b22588cb..eadd9e16c 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -7,18 +7,18 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile.
-L_TARGET := filesystems.a
-L_OBJS = $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
+FILESYSTEMS = $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
O_TARGET := fs.o
O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \
super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
- dcache.o inode.o attr.o bad_inode.o file.o iobuf.o $(BINFMTS)
+ dcache.o inode.o attr.o bad_inode.o file.o iobuf.o \
+ $(BINFMTS) $(FILESYSTEMS)
MOD_LIST_NAME := FS_MODULES
ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
- nfsd nls devpts adfs partitions qnx4 udf bfs
+ nfsd nls devpts adfs partitions qnx4 udf bfs cramfs openpromfs
SUB_DIRS := partitions
@@ -28,6 +28,22 @@ else
O_OBJS += noquot.o
endif
+ifeq ($(CONFIG_EXT2_FS),y)
+SUB_DIRS += ext2
+else
+ ifeq ($(CONFIG_EXT2_FS),m)
+ MOD_SUB_DIRS += ext2
+ endif
+endif
+
+ifeq ($(CONFIG_CRAMFS),y)
+SUB_DIRS += cramfs
+else
+ ifeq ($(CONFIG_CRAMFS),m)
+ MOD_SUB_DIRS += cramfs
+ endif
+endif
+
ifeq ($(CONFIG_CODA_FS),y)
SUB_DIRS += coda
else
@@ -44,14 +60,6 @@ else
endif
endif
-ifeq ($(CONFIG_EXT2_FS),y)
-SUB_DIRS += ext2
-else
- ifeq ($(CONFIG_EXT2_FS),m)
- MOD_SUB_DIRS += ext2
- endif
-endif
-
ifeq ($(CONFIG_FAT_FS),y)
SUB_DIRS += fat
else
@@ -78,10 +86,6 @@ endif
ifdef CONFIG_PROC_FS
SUB_DIRS += proc
-ifeq ($(CONFIG_SUN_OPENPROMFS),m)
-MOD_IN_SUB_DIRS += proc
-MOD_TO_LIST += openpromfs.o
-endif
endif
ifeq ($(CONFIG_BFS_FS),y)
@@ -265,6 +269,14 @@ else
endif
endif
+ifeq ($(CONFIG_SUN_OPENPROMFS),y)
+SUB_DIRS += openpromfs
+else
+ ifeq ($(CONFIG_SUN_OPENPROMFS),m)
+ MOD_SUB_DIRS += openpromfs
+ endif
+endif
+
ifeq ($(CONFIG_BINFMT_AOUT),y)
BINFMTS += binfmt_aout.o
else
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index f3eb4e872..a65f5c168 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -31,8 +31,6 @@ static struct file_operations adfs_dir_operations = {
NULL, /* no special release code */
file_fsync, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
/*
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index 2881e81f1..a4580426a 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -44,8 +44,6 @@ static struct file_operations adfs_file_operations = {
NULL, /* release */
file_fsync, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
struct inode_operations adfs_file_inode_operations = {
diff --git a/fs/affs/file.c b/fs/affs/file.c
index e32b9c344..7a751e40b 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -56,8 +56,6 @@ static struct file_operations affs_file_operations = {
NULL, /* release */
file_fsync, /* brute force, but works */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL /* lock */
};
@@ -95,8 +93,6 @@ static struct file_operations affs_file_operations_ofs = {
NULL, /* release */
file_fsync, /* brute force, but works */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL /* lock */
};
diff --git a/fs/autofs/dir.c b/fs/autofs/dir.c
index 018b6787b..ae53396af 100644
--- a/fs/autofs/dir.c
+++ b/fs/autofs/dir.c
@@ -47,17 +47,6 @@ static struct file_operations autofs_dir_operations = {
NULL, /* read */
NULL, /* write */
autofs_dir_readdir, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* flush */
- NULL, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
};
struct inode_operations autofs_dir_inode_operations = {
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index 4f0569ca7..46fc4503e 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -30,15 +30,6 @@ static struct file_operations autofs_root_operations = {
autofs_root_readdir, /* readdir */
NULL, /* poll */
autofs_root_ioctl, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* flush */
- NULL, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
};
struct inode_operations autofs_root_inode_operations = {
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 4369e2a86..bff2689a0 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -42,8 +42,7 @@ static struct file_operations bad_file_ops =
EIO_ERROR, /* release */
EIO_ERROR, /* fsync */
EIO_ERROR, /* fasync */
- EIO_ERROR, /* check_media_change */
- EIO_ERROR /* revalidate */
+ EIO_ERROR, /* lock */
};
struct inode_operations bad_inode_ops =
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 6f5c240d2..b6159be85 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -89,8 +89,6 @@ static struct file_operations bfs_dir_operations = {
release: NULL,
fsync: file_fsync,
fasync: NULL,
- check_media_change: NULL,
- revalidate: NULL,
};
extern void dump_imap(const char *, struct super_block *);
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 856ed33cd..9e7503626 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -34,8 +34,6 @@ static struct file_operations bfs_file_operations = {
release: NULL,
fsync: NULL,
fasync: NULL,
- check_media_change: NULL,
- revalidate: NULL,
};
static int bfs_get_block(struct inode * inode, long block,
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 8331e9514..c32b8c0f2 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -4,9 +4,12 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
+#include <linux/config.h>
#include <linux/mm.h>
#include <linux/locks.h>
#include <linux/fcntl.h>
+#include <linux/malloc.h>
+#include <linux/kmod.h>
#include <asm/uaccess.h>
@@ -299,3 +302,361 @@ int block_fsync(struct file *filp, struct dentry *dentry)
{
return fsync_dev(dentry->d_inode->i_rdev);
}
+
+/*
+ * bdev cache handling - shamelessly stolen from inode.c
+ * We use smaller hashtable, though.
+ */
+
+#define HASH_BITS 6
+#define HASH_SIZE (1UL << HASH_BITS)
+#define HASH_MASK (HASH_SIZE-1)
+static struct list_head bdev_hashtable[HASH_SIZE];
+static spinlock_t bdev_lock = SPIN_LOCK_UNLOCKED;
+static kmem_cache_t * bdev_cachep;
+
+#define alloc_bdev() \
+ ((struct block_device *) kmem_cache_alloc(bdev_cachep, SLAB_KERNEL))
+#define destroy_bdev(bdev) kmem_cache_free(bdev_cachep, (bdev))
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+ struct block_device * bdev = (struct block_device *) foo;
+
+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+ SLAB_CTOR_CONSTRUCTOR)
+ {
+ memset(bdev, 0, sizeof(*bdev));
+ sema_init(&bdev->bd_sem, 1);
+ }
+}
+
+void bdev_init(void)
+{
+ int i;
+ struct list_head *head = bdev_hashtable;
+
+ i = HASH_SIZE;
+ do {
+ INIT_LIST_HEAD(head);
+ head++;
+ i--;
+ } while (i);
+
+ bdev_cachep = kmem_cache_create("bdev_cache",
+ sizeof(struct block_device),
+ 0, SLAB_HWCACHE_ALIGN, init_once,
+ NULL);
+ if (!bdev_cachep)
+ panic("cannot create bdev slab cache");
+}
+
+/*
+ * Most likely _very_ bad one - but then it's hardly critical for small
+ * /dev and can be fixed when somebody will need really large one.
+ */
+static inline unsigned long hash(dev_t dev)
+{
+ unsigned long tmp = dev;
+ tmp = tmp + (tmp >> HASH_BITS) + (tmp >> HASH_BITS*2);
+ return tmp & HASH_MASK;
+}
+
+static struct block_device *bdfind(dev_t dev, struct list_head *head)
+{
+ struct list_head *p;
+ struct block_device *bdev;
+ for (p=head->next; p!=head; p=p->next) {
+ bdev = list_entry(p, struct block_device, bd_hash);
+ if (bdev->bd_dev != dev)
+ continue;
+ atomic_inc(&bdev->bd_count);
+ return bdev;
+ }
+ return NULL;
+}
+
+struct block_device *bdget(dev_t dev)
+{
+ struct list_head * head = bdev_hashtable + hash(dev);
+ struct block_device *bdev, *new_bdev;
+ spin_lock(&bdev_lock);
+ bdev = bdfind(dev, head);
+ spin_unlock(&bdev_lock);
+ if (bdev)
+ return bdev;
+ new_bdev = alloc_bdev();
+ if (!new_bdev)
+ return NULL;
+ atomic_set(&new_bdev->bd_count,1);
+ new_bdev->bd_dev = dev;
+ new_bdev->bd_op = NULL;
+ spin_lock(&bdev_lock);
+ bdev = bdfind(dev, head);
+ if (!bdev) {
+ list_add(&new_bdev->bd_hash, head);
+ spin_unlock(&bdev_lock);
+ return new_bdev;
+ }
+ spin_unlock(&bdev_lock);
+ destroy_bdev(new_bdev);
+ return bdev;
+}
+
+void bdput(struct block_device *bdev)
+{
+ if (atomic_dec_and_test(&bdev->bd_count)) {
+ spin_lock(&bdev_lock);
+ if (atomic_read(&bdev->bd_openers))
+ BUG();
+ list_del(&bdev->bd_hash);
+ spin_unlock(&bdev_lock);
+ destroy_bdev(bdev);
+ }
+}
+
+static struct {
+ const char *name;
+ struct block_device_operations *bdops;
+} blkdevs[MAX_BLKDEV] = {
+ { NULL, NULL },
+};
+
+int get_blkdev_list(char * p)
+{
+ int i;
+ int len;
+
+ len = sprintf(p, "\nBlock devices:\n");
+ for (i = 0; i < MAX_BLKDEV ; i++) {
+ if (blkdevs[i].bdops) {
+ len += sprintf(p+len, "%3d %s\n", i, blkdevs[i].name);
+ }
+ }
+ return len;
+}
+
+/*
+ Return the function table of a device.
+ Load the driver if needed.
+*/
+static const struct block_device_operations * get_blkfops(unsigned int major)
+{
+ const struct block_device_operations *ret = NULL;
+
+ /* major 0 is used for non-device mounts */
+ if (major && major < MAX_BLKDEV) {
+#ifdef CONFIG_KMOD
+ if (!blkdevs[major].bdops) {
+ char name[20];
+ sprintf(name, "block-major-%d", major);
+ request_module(name);
+ }
+#endif
+ ret = blkdevs[major].bdops;
+ }
+ return ret;
+}
+
+int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
+{
+ if (major == 0) {
+ for (major = MAX_BLKDEV-1; major > 0; major--) {
+ if (blkdevs[major].bdops == NULL) {
+ blkdevs[major].name = name;
+ blkdevs[major].bdops = bdops;
+ return major;
+ }
+ }
+ return -EBUSY;
+ }
+ if (major >= MAX_BLKDEV)
+ return -EINVAL;
+ if (blkdevs[major].bdops && blkdevs[major].bdops != bdops)
+ return -EBUSY;
+ blkdevs[major].name = name;
+ blkdevs[major].bdops = bdops;
+ return 0;
+}
+
+int unregister_blkdev(unsigned int major, const char * name)
+{
+ if (major >= MAX_BLKDEV)
+ return -EINVAL;
+ if (!blkdevs[major].bdops)
+ return -EINVAL;
+ if (strcmp(blkdevs[major].name, name))
+ return -EINVAL;
+ blkdevs[major].name = NULL;
+ blkdevs[major].bdops = NULL;
+ return 0;
+}
+
+/*
+ * This routine checks whether a removable media has been changed,
+ * and invalidates all buffer-cache-entries in that case. This
+ * is a relatively slow routine, so we have to try to minimize using
+ * it. Thus it is called only upon a 'mount' or 'open'. This
+ * is the best way of combining speed and utility, I think.
+ * People changing diskettes in the middle of an operation deserve
+ * to lose :-)
+ */
+int check_disk_change(kdev_t dev)
+{
+ int i;
+ const struct block_device_operations * bdops;
+ struct super_block * sb;
+
+ i = MAJOR(dev);
+ if (i >= MAX_BLKDEV || (bdops = blkdevs[i].bdops) == NULL)
+ return 0;
+ if (bdops->check_media_change == NULL)
+ return 0;
+ if (!bdops->check_media_change(dev))
+ return 0;
+
+ printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
+ bdevname(dev));
+
+ sb = get_super(dev);
+ if (sb && invalidate_inodes(sb))
+ printk("VFS: busy inodes on changed media.\n");
+
+ invalidate_buffers(dev);
+
+ if (bdops->revalidate)
+ bdops->revalidate(dev);
+ return 1;
+}
+
+int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
+{
+ kdev_t rdev = to_kdev_t(bdev->bd_dev);
+ struct inode inode_fake;
+ int res;
+ mm_segment_t old_fs = get_fs();
+
+ if (!bdev->bd_op->ioctl)
+ return -EINVAL;
+ inode_fake.i_rdev=rdev;
+ init_waitqueue_head(&inode_fake.i_wait);
+ set_fs(KERNEL_DS);
+ res = bdev->bd_op->ioctl(&inode_fake, NULL, cmd, arg);
+ set_fs(old_fs);
+ return res;
+}
+
+int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
+{
+ int ret = -ENODEV;
+ kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
+ down(&bdev->bd_sem);
+ if (!bdev->bd_op)
+ bdev->bd_op = get_blkfops(MAJOR(rdev));
+ if (bdev->bd_op) {
+ /*
+ * This crockload is due to bad choice of ->open() type.
+ * It will go away.
+ */
+ struct file fake_file = {};
+ struct dentry fake_dentry = {};
+ struct inode *fake_inode = get_empty_inode();
+ ret = -ENOMEM;
+ if (fake_inode) {
+ fake_file.f_mode = mode;
+ fake_file.f_flags = flags;
+ fake_file.f_dentry = &fake_dentry;
+ fake_dentry.d_inode = fake_inode;
+ fake_inode->i_rdev = rdev;
+ ret = 0;
+ if (bdev->bd_op->open)
+ ret = bdev->bd_op->open(fake_inode, &fake_file);
+ if (!ret)
+ atomic_inc(&bdev->bd_openers);
+ iput(fake_inode);
+ }
+ }
+ up(&bdev->bd_sem);
+ return ret;
+}
+
+int blkdev_open(struct inode * inode, struct file * filp)
+{
+ int ret = -ENODEV;
+ struct block_device *bdev = inode->i_bdev;
+ down(&bdev->bd_sem);
+ if (!bdev->bd_op)
+ bdev->bd_op = get_blkfops(MAJOR(inode->i_rdev));
+ if (bdev->bd_op) {
+ ret = 0;
+ if (bdev->bd_op->open)
+ ret = bdev->bd_op->open(inode,filp);
+ if (!ret)
+ atomic_inc(&bdev->bd_openers);
+ }
+ up(&bdev->bd_sem);
+ return ret;
+}
+
+int blkdev_put(struct block_device *bdev, int kind)
+{
+ int ret = 0;
+ kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */
+ down(&bdev->bd_sem);
+ /* syncing will go here */
+ if (atomic_dec_and_test(&bdev->bd_openers)) {
+ /* invalidating buffers will go here */
+ }
+ if (bdev->bd_op->release) {
+ struct inode * fake_inode = get_empty_inode();
+ ret = -ENOMEM;
+ if (fake_inode) {
+ fake_inode->i_rdev = rdev;
+ ret = bdev->bd_op->release(fake_inode, NULL);
+ iput(fake_inode);
+ }
+ }
+ if (!atomic_read(&bdev->bd_openers))
+ bdev->bd_op = NULL; /* we can't rely on driver being */
+ /* kind to stay around. */
+ up(&bdev->bd_sem);
+ return ret;
+}
+
+static int blkdev_close(struct inode * inode, struct file * filp)
+{
+ return blkdev_put(inode->i_bdev, BDEV_FILE);
+}
+
+static int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ if (inode->i_bdev->bd_op->ioctl)
+ return inode->i_bdev->bd_op->ioctl(inode, file, cmd, arg);
+ return -EINVAL;
+}
+
+struct file_operations def_blk_fops = {
+ open: blkdev_open,
+ release: blkdev_close,
+ read: block_read,
+ write: block_write,
+ fsync: block_fsync,
+ ioctl: blkdev_ioctl,
+};
+
+struct inode_operations blkdev_inode_operations = {
+ &def_blk_fops, /* default file operations */
+};
+
+char * bdevname(kdev_t dev)
+{
+ static char buffer[32];
+ const char * name = blkdevs[MAJOR(dev)].name;
+
+ if (!name)
+ name = "unknown-block";
+
+ sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
+ return buffer;
+}
diff --git a/fs/buffer.c b/fs/buffer.c
index 6bf84ca27..b2bc7670f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -727,8 +727,7 @@ static void end_buffer_io_async(struct buffer_head * bh, int uptodate)
atomic_dec(&bh->b_count);
tmp = bh->b_this_page;
while (tmp != bh) {
- if (atomic_read(&tmp->b_count) &&
- (tmp->b_end_io == end_buffer_io_async))
+ if (tmp->b_end_io == end_buffer_io_async && buffer_locked(tmp))
goto still_busy;
tmp = tmp->b_this_page;
}
@@ -1089,7 +1088,7 @@ static struct buffer_head * get_unused_buffer_head(int async)
return NULL;
}
-void set_bh_page (struct buffer_head *bh, struct page *page, unsigned int offset)
+void set_bh_page (struct buffer_head *bh, struct page *page, unsigned long offset)
{
bh->b_page = page;
if (offset >= PAGE_SIZE)
@@ -1630,7 +1629,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
int offset;
unsigned long blocknr;
struct kiobuf * iobuf = NULL;
- unsigned long page;
struct page * map;
struct buffer_head *tmp, *bh[KIO_MAX_SECTORS];
@@ -1662,11 +1660,6 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[],
for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
map = iobuf->maplist[pageind];
- if (map && PageHighMem(map)) {
- err = -EIO;
- goto error;
- }
- page = page_address(map);
while (length > 0) {
blocknr = b[bufind++];
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 794a8d263..2a1a122c8 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -97,9 +97,6 @@ struct file_operations coda_dir_operations = {
NULL,
coda_release, /* release */
coda_fsync, /* fsync */
- NULL,
- NULL,
- NULL
};
diff --git a/fs/coda/file.c b/fs/coda/file.c
index d053258e8..726bd18fd 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -68,8 +68,6 @@ struct file_operations coda_file_operations = {
coda_release, /* release */
coda_fsync, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL /* lock */
};
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 330b634a3..65aeee08e 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -327,8 +327,6 @@ static struct file_operations coda_psdev_fops = {
coda_psdev_release, /* release */
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL /* lock */
};
diff --git a/fs/cramfs/.cvsignore b/fs/cramfs/.cvsignore
new file mode 100644
index 000000000..857dd22e9
--- /dev/null
+++ b/fs/cramfs/.cvsignore
@@ -0,0 +1,2 @@
+.depend
+.*.flags
diff --git a/fs/cramfs/Makefile b/fs/cramfs/Makefile
new file mode 100644
index 000000000..9f71d0814
--- /dev/null
+++ b/fs/cramfs/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux cramfs routines.
+#
+
+O_TARGET := cramfs.o
+
+O_OBJS := inode.o uncompress.o inflate/zlib.o
+
+M_OBJS := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
+
+inflate/zlib.o:
+ make -C inflate
diff --git a/fs/cramfs/cramfs.h b/fs/cramfs/cramfs.h
new file mode 100644
index 000000000..e98cd7309
--- /dev/null
+++ b/fs/cramfs/cramfs.h
@@ -0,0 +1,41 @@
+#ifndef __CRAMFS_H
+#define __CRAMFS_H
+
+#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */
+#define CRAMFS_SIGNATURE "Compressed ROMFS"
+
+/*
+ * Reasonably terse representation of the inode
+ * data.. When the mode of the inode indicates
+ * a special device node, the "offset" bits will
+ * encode i_rdev. In other cases, "offset" points
+ * to the ROM image for the actual file data
+ * (whether that data be directory or compressed
+ * file data depends on the inode type again)
+ */
+struct cramfs_inode {
+ u32 mode:16, uid:16;
+ u32 size:24, gid:8;
+ u32 namelen:6, offset:26;
+};
+
+/*
+ * Superblock information at the beginning of the FS.
+ */
+struct cramfs_super {
+ u32 magic; /* 0x28cd3d45 - random number */
+ u32 size; /* > offset, < 2**26 */
+ u32 flags; /* 0 */
+ u32 future; /* 0 */
+ u8 signature[16]; /* "Compressed ROMFS" */
+ u8 fsid[16]; /* random number */
+ u8 name[16]; /* user-defined name */
+ struct cramfs_inode root; /* Root inode data */
+};
+
+/* Uncompression interfaces to the underlying zlib */
+int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);
+int cramfs_uncompress_init(void);
+int cramfs_uncompress_exit(void);
+
+#endif
diff --git a/fs/cramfs/inflate/Makefile b/fs/cramfs/inflate/Makefile
new file mode 100644
index 000000000..92feb8325
--- /dev/null
+++ b/fs/cramfs/inflate/Makefile
@@ -0,0 +1,34 @@
+#
+# inflate/Makefile
+#
+#
+# NOTE NOTE NOTE!
+#
+# This code is basically a bastardized version of the zlib
+# library uncompression. It avoids dynamic allocations at
+# all cost, and is cut down in other ways too, to make it
+# simpler and more specialized. If you want to get the real
+# thing, don't look here.
+#
+# The simplifications mean that this version of the library
+# (unlike the real lib) is completely single-threaded, and
+# you cannot do multiple uncompressions at a time. You can
+# ONLY use it to uncompress a single block, with both the
+# source and the destination completely in memory. In SMP
+# environments, the uncompression has to be protected by
+# some lock to guarantee single-threaded access to the static
+# data structures used for inflation.
+#
+# You have been warned.
+#
+# (The upsides of the simplification is that you can't get in
+# any nasty situations wrt memory management, and that the
+# uncompression can be done without blocking on allocation).
+#
+
+O_TARGET := zlib.o
+
+O_OBJS := adler32.o infblock.o infcodes.o inffast.o inflate.o \
+ inftrees.o infutil.o uncompr.o
+
+include $(TOPDIR)/Rules.make
diff --git a/fs/cramfs/inflate/adler32.c b/fs/cramfs/inflate/adler32.c
new file mode 100644
index 000000000..16cf9a703
--- /dev/null
+++ b/fs/cramfs/inflate/adler32.c
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff --git a/fs/cramfs/inflate/infblock.c b/fs/cramfs/inflate/infblock.c
new file mode 100644
index 000000000..b6cc1fc86
--- /dev/null
+++ b/fs/cramfs/inflate/infblock.c
@@ -0,0 +1,360 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+ if (c != Z_NULL)
+ *c = s->check;
+ if (s->mode == CODES)
+ inflate_codes_free(s->sub.decode.codes, z);
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+ inflate_blocks_statef *s;
+ static struct inflate_blocks_state working_blocks_state;
+ static inflate_huft working_hufts[MANY];
+ static unsigned char working_window[1 << MAX_WBITS];
+
+ s = &working_blocks_state;
+ s->hufts = working_hufts;
+ s->window = working_window;
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ inflate_blocks_reset(s, z, Z_NULL);
+ return s;
+}
+
+
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BAD;
+ z->msg = (char*)"invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ memcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BAD;
+ z->msg = (char*)"too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ {
+ static unsigned int working_blens [258 + 0x1f + 0x1f];
+ s->sub.trees.blens = working_blens;
+ }
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, s->hufts, z);
+ if (t != Z_OK)
+ {
+ r = t;
+ if (r == Z_DATA_ERROR)
+ s->mode = BAD;
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->bits;
+ c = h->base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ s->mode = BAD;
+ z->msg = (char*)"invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td,
+ s->hufts, z);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ s->mode = BAD;
+ r = t;
+ LEAVE
+ }
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.codes = c;
+ }
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ LOAD
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONE;
+ case DONE:
+ r = Z_STREAM_END;
+ LEAVE
+ case BAD:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+int inflate_blocks_free(s, z)
+inflate_blocks_statef *s;
+z_streamp z;
+{
+ inflate_blocks_reset(s, z, Z_NULL);
+ return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt n;
+{
+ memcpy(s->window, d, n);
+ s->read = s->write = s->window + n;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH.
+ * IN assertion: s != Z_NULL
+ */
+int inflate_blocks_sync_point(s)
+inflate_blocks_statef *s;
+{
+ return s->mode == LENS;
+}
diff --git a/fs/cramfs/inflate/infblock.h b/fs/cramfs/inflate/infblock.h
new file mode 100644
index 000000000..bd25c8075
--- /dev/null
+++ b/fs/cramfs/inflate/infblock.h
@@ -0,0 +1,39 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+ z_streamp z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+extern int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int)); /* initial return code */
+
+extern void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ uLongf *)); /* check value on output */
+
+extern int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_streamp));
+
+extern void inflate_set_dictionary OF((
+ inflate_blocks_statef *s,
+ const Bytef *d, /* dictionary */
+ uInt n)); /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+ inflate_blocks_statef *s));
diff --git a/fs/cramfs/inflate/infcodes.c b/fs/cramfs/inflate/infcodes.c
new file mode 100644
index 000000000..ea7f6aba8
--- /dev/null
+++ b/fs/cramfs/inflate/infcodes.c
@@ -0,0 +1,247 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ inflate_codes_mode mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+ inflate_codes_statef *c;
+ static inflate_codes_statef memory_allocation;
+
+ c = &memory_allocation;
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ }
+ return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t + t->base;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = (char*)"invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+ f = (uInt)(q - s->window) < c->sub.copy.dist ?
+ s->end - (c->sub.copy.dist - (q - s->window)) :
+ q - c->sub.copy.dist;
+#else
+ f = q - c->sub.copy.dist;
+ if ((uInt)(q - s->window) < c->sub.copy.dist)
+ f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ if (k > 7) /* return unused byte, if any */
+ {
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+}
diff --git a/fs/cramfs/inflate/infcodes.h b/fs/cramfs/inflate/infcodes.h
new file mode 100644
index 000000000..6c750d896
--- /dev/null
+++ b/fs/cramfs/inflate/infcodes.h
@@ -0,0 +1,27 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_streamp ));
+
+extern int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+extern void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_streamp ));
+
diff --git a/fs/cramfs/inflate/inffast.c b/fs/cramfs/inflate/inffast.c
new file mode 100644
index 000000000..5da2cd0a9
--- /dev/null
+++ b/fs/cramfs/inflate/inffast.c
@@ -0,0 +1,161 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+
+/* Called with number of bytes left to write in window at least 258
+ (the maximum string length) and number of input bytes available
+ at least ten. The ten bytes are six bytes for the longest length/
+ distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ uInt ml; /* mask for literal/length tree */
+ uInt md; /* mask for distance tree */
+ uInt c; /* bytes to copy */
+ uInt d; /* distance back to copy from */
+ Bytef *r; /* copy source pointer */
+
+ /* load input, output, bit values */
+ LOAD
+
+ /* initialize masks */
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ /* do until not enough input or output space for fast loop */
+ do { /* assume called with m >= 258 && n >= 10 */
+ /* get literal/length code */
+ GRABBITS(20) /* max bits for literal/length code */
+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ *q++ = (Byte)t->base;
+ m--;
+ continue;
+ }
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits for length */
+ e &= 15;
+ c = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+
+ /* decode distance base of block to copy */
+ GRABBITS(15); /* max bits for distance code */
+ e = (t = td + ((uInt)b & md))->exop;
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits to add to distance base */
+ e &= 15;
+ GRABBITS(e) /* get extra bits (up to 13) */
+ d = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+
+ /* do the copy */
+ m -= c;
+ if ((uInt)(q - s->window) >= d) /* offset before dest */
+ { /* just copy */
+ r = q - d;
+ *q++ = *r++; c--; /* minimum count is three, */
+ *q++ = *r++; c--; /* so unroll loop a little */
+ }
+ else /* else offset after destination */
+ {
+ e = d - (uInt)(q - s->window); /* bytes from offset to end */
+ r = s->end - e; /* pointer to offset */
+ if (c > e) /* if source crosses, */
+ {
+ c -= e; /* copy to end of window */
+ do {
+ *q++ = *r++;
+ } while (--e);
+ r = s->window; /* copy rest from start of window */
+ }
+ }
+ do { /* copy all or what's left */
+ *q++ = *r++;
+ } while (--c);
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += t->base;
+ e = (t += ((uInt)b & inflate_mask[e]))->exop;
+ }
+ else
+ {
+ z->msg = (char*)"invalid distance code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ break;
+ }
+ if ((e & 64) == 0)
+ {
+ t += t->base;
+ if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ *q++ = (Byte)t->base;
+ m--;
+ break;
+ }
+ }
+ else if (e & 32)
+ {
+ UNGRAB
+ UPDATE
+ return Z_STREAM_END;
+ }
+ else
+ {
+ z->msg = (char*)"invalid literal/length code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ } while (m >= 258 && n >= 10);
+
+ /* not enough input or output--restore pointers and return */
+ UNGRAB
+ UPDATE
+ return Z_OK;
+}
diff --git a/fs/cramfs/inflate/inffast.h b/fs/cramfs/inflate/inffast.h
new file mode 100644
index 000000000..8facec553
--- /dev/null
+++ b/fs/cramfs/inflate/inffast.h
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast OF((
+ uInt,
+ uInt,
+ inflate_huft *,
+ inflate_huft *,
+ inflate_blocks_statef *,
+ z_streamp ));
diff --git a/fs/cramfs/inflate/inffixed.h b/fs/cramfs/inflate/inffixed.h
new file mode 100644
index 000000000..77f7e7631
--- /dev/null
+++ b/fs/cramfs/inflate/inffixed.h
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+local uInt fixed_bl = 9;
+local uInt fixed_bd = 5;
+local inflate_huft fixed_tl[] = {
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+ {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+ {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+ {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+ {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+ {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+ {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+ {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+ {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+ {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+ {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+ {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+ {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+ {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+ {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+ {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+ {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+ {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+ {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+ {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+ {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+ {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+ {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+ {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+ {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+ {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+ {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+ {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+ {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+ {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+ {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+ {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+ {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+ {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+ {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+ {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+ {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+ {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+ {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+ {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+ {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+ {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+ {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+ {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+ {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+ {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+ {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+ {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+ {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+ {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+ {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+ {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+ {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+ {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+ {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+ {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+ {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+ {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+ {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+ {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+ {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+ {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+ {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+ {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+ };
+local inflate_huft fixed_td[] = {
+ {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+ {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+ {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+ {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+ {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+ {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+ {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+ {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+ };
diff --git a/fs/cramfs/inflate/inflate.c b/fs/cramfs/inflate/inflate.c
new file mode 100644
index 000000000..c5b7a0c44
--- /dev/null
+++ b/fs/cramfs/inflate/inflate.c
@@ -0,0 +1,330 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+typedef enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ DICT4, /* four dictionary check bytes to go */
+ DICT3, /* three dictionary check bytes to go */
+ DICT2, /* two dictionary check bytes to go */
+ DICT1, /* one dictionary check byte to go */
+ DICT0, /* waiting for inflateSetDictionary */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ inflate_mode mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+int ZEXPORT inflateReset(z)
+z_streamp z;
+{
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+ return Z_OK;
+}
+
+
+int ZEXPORT inflateEnd(z)
+z_streamp z;
+{
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z);
+ z->state = Z_NULL;
+ return Z_OK;
+}
+
+
+int ZEXPORT inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+ static struct internal_state internal_state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != sizeof(z_stream))
+ return Z_VERSION_ERROR;
+
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->msg = Z_NULL;
+ z->state = &internal_state;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+int ZEXPORT inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int ZEXPORT inflate(z, f)
+z_streamp z;
+int f;
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+ return Z_STREAM_ERROR;
+ f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ b = NEXTBYTE;
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if (!(b & PRESET_DICT))
+ {
+ z->state->mode = BLOCKS;
+ break;
+ }
+ z->state->mode = DICT4;
+ case DICT4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = DICT3;
+ case DICT3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = DICT2;
+ case DICT2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = DICT1;
+ case DICT1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+ z->adler = z->state->sub.check.need;
+ z->state->mode = DICT0;
+ return Z_NEED_DICT;
+ case DICT0:
+ z->state->mode = BAD;
+ z->msg = (char*)"need dictionary";
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_STREAM_ERROR;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r == Z_OK)
+ r = f;
+ if (r != Z_STREAM_END)
+ return r;
+ r = f;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = (char*)"incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+#ifdef NEED_DUMMY_RETURN
+ return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+#endif
+}
+
+
+int ZEXPORT inflateSync(z)
+z_streamp z;
+{
+ uInt n; /* number of bytes to look at */
+ Bytef *p; /* pointer to bytes */
+ uInt m; /* number of marker bytes found in a row */
+ uLong r, w; /* temporaries to save total_in and total_out */
+
+ /* set up */
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->mode != BAD)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0;
+ }
+ if ((n = z->avail_in) == 0)
+ return Z_BUF_ERROR;
+ p = z->next_in;
+ m = z->state->sub.marker;
+
+ /* search */
+ while (n && m < 4)
+ {
+ static const Byte mark[4] = {0, 0, 0xff, 0xff};
+ if (*p == mark[m])
+ m++;
+ else if (*p)
+ m = 0;
+ else
+ m = 4 - m;
+ p++, n--;
+ }
+
+ /* restore */
+ z->total_in += p - z->next_in;
+ z->next_in = p;
+ z->avail_in = n;
+ z->state->sub.marker = m;
+
+ /* return no joy or set up to restart on a new block */
+ if (m != 4)
+ return Z_DATA_ERROR;
+ r = z->total_in; w = z->total_out;
+ inflateReset(z);
+ z->total_in = r; z->total_out = w;
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z)
+z_streamp z;
+{
+ if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
+ return Z_STREAM_ERROR;
+ return inflate_blocks_sync_point(z->state->blocks);
+}
diff --git a/fs/cramfs/inflate/inftrees.c b/fs/cramfs/inflate/inftrees.c
new file mode 100644
index 000000000..250c8833e
--- /dev/null
+++ b/fs/cramfs/inflate/inftrees.c
@@ -0,0 +1,392 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+const char inflate_copyright[] =
+ " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ const uIntf *, /* list of base values for non-simple codes */
+ const uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ inflate_huft *, /* space for trees */
+ uInt *, /* hufts used in space */
+ uIntf * )); /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local const uInt cpdext[30] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+
+local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
+uInt n; /* number of codes (assumed <= 288) */
+uInt s; /* number of simple-valued codes (0..s-1) */
+const uIntf *d; /* list of base values for non-simple codes */
+const uIntf *e; /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t; /* result: starting table */
+uIntf *m; /* maximum lookup bits, returns actual */
+inflate_huft *hp; /* space for trees */
+uInt *hn; /* hufts used in space */
+uIntf *v; /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register uInt i; /* counter, current code */
+ register uInt j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
+ register uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ register int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+ n = x[g]; /* set n to length of v */
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = g - w;
+ z = z > (uInt)l ? l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate new table */
+ if (*hn + z > MANY) /* (note: doesn't matter for fixed) */
+ return Z_MEM_ERROR; /* not enough memory */
+ u[h] = q = hp + *hn;
+ *hn += z;
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ j = i >> (w - l);
+ r.base = (uInt)(q - u[h-1] - j); /* offset to this table */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ else
+ *t = q; /* first table is returned result */
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ mask = (1 << w) - 1; /* needed on HP, cc -O bug */
+ while ((i & mask) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, hp, z)
+uIntf *c; /* 19 code lengths */
+uIntf *bb; /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+inflate_huft *hp; /* space for trees */
+z_streamp z; /* for messages */
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+ static unsigned int work_area[19];
+
+ v = work_area;
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+ tb, bb, hp, &hn, v);
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR || *bb == 0)
+ {
+ z->msg = (char*)"incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+}
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
+uInt nl; /* number of literal/length codes */
+uInt nd; /* number of distance codes */
+uIntf *c; /* that many (total) code lengths */
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+inflate_huft *hp; /* space for trees */
+z_streamp z; /* for messages */
+{
+ int r;
+ uInt hn = 0; /* hufts used in space */
+ uIntf *v; /* work area for huft_build */
+ static unsigned int work_area[288];
+
+ /* allocate work area */
+ v = work_area;
+
+ /* build literal/length tree */
+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+ if (r != Z_OK || *bl == 0)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+ }
+
+ /* build distance tree */
+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+ if (r != Z_OK || (*bd == 0 && nl > 257))
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed distance tree";
+ else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ z->msg = (char*)"incomplete distance tree";
+ r = Z_DATA_ERROR;
+ }
+ else if (r != Z_MEM_ERROR)
+ {
+ z->msg = (char*)"empty distance tree with lengths";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+#endif
+ }
+
+ /* done */
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#include "inffixed.h"
+
+
+int inflate_trees_fixed(bl, bd, tl, td, z)
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_streamp z; /* for memory allocation */
+{
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
diff --git a/fs/cramfs/inflate/inftrees.h b/fs/cramfs/inflate/inftrees.h
new file mode 100644
index 000000000..85853e097
--- /dev/null
+++ b/fs/cramfs/inflate/inftrees.h
@@ -0,0 +1,58 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ uInt pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit int's) */
+ uInt base; /* literal, length base, distance base,
+ or table offset */
+};
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1004 huft structures (850 for length/literals
+ and 154 for distances, the latter actually the result of an
+ exhaustive search). The actual maximum is not known, but the
+ value below is more than safe. */
+#define MANY 1440
+
+extern int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+extern int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ inflate_huft *, /* space for trees */
+ z_streamp)); /* for messages */
+
+extern int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ z_streamp)); /* for memory allocation */
diff --git a/fs/cramfs/inflate/infutil.c b/fs/cramfs/inflate/infutil.c
new file mode 100644
index 000000000..23b6d96d0
--- /dev/null
+++ b/fs/cramfs/inflate/infutil.c
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+ uInt n;
+ Bytef *p;
+ Bytef *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ memcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ memcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
diff --git a/fs/cramfs/inflate/infutil.h b/fs/cramfs/inflate/infutil.h
new file mode 100644
index 000000000..99d1135d0
--- /dev/null
+++ b/fs/cramfs/inflate/infutil.h
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONE, /* finished last block, done */
+ BAD} /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ inflate_block_mode mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ inflate_huft *hufts; /* single malloc for tree space */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_streamp ,
+ int));
+
+struct internal_state {int dummy;}; /* for buggy compilers */
+
+#endif
diff --git a/fs/cramfs/inflate/uncompr.c b/fs/cramfs/inflate/uncompr.c
new file mode 100644
index 000000000..45eb47b72
--- /dev/null
+++ b/fs/cramfs/inflate/uncompr.c
@@ -0,0 +1,55 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/fs/cramfs/inflate/zconf.h b/fs/cramfs/inflate/zconf.h
new file mode 100644
index 000000000..adc70c276
--- /dev/null
+++ b/fs/cramfs/inflate/zconf.h
@@ -0,0 +1,90 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+#if defined(__GNUC__) || defined(__386__) || defined(i386)
+# ifndef __32BIT__
+# define __32BIT__
+# endif
+#endif
+
+#if defined(__STDC__) || defined(__cplusplus)
+# ifndef STDC
+# define STDC
+# endif
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# define MAX_MEM_LEVEL 9
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef FAR
+# define FAR
+#endif
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+typedef Byte FAR Bytef;
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+typedef void FAR *voidpf;
+typedef void *voidp;
+
+#include <sys/types.h> /* for off_t */
+#include <unistd.h> /* for SEEK_* and off_t */
+#define z_off_t off_t
+
+#endif /* _ZCONF_H */
diff --git a/fs/cramfs/inflate/zlib.h b/fs/cramfs/inflate/zlib.h
new file mode 100644
index 000000000..f35937912
--- /dev/null
+++ b/fs/cramfs/inflate/zlib.h
@@ -0,0 +1,893 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.1.3, July 9th, 1998
+
+ Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.3"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func nozalloc; /* used to allocate the internal state */
+ free_func nozfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ the compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero).
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may some
+ introduce some output latency (reading input without producing any output)
+ except when forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_SYNC_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ If a preset dictionary is needed at this point (see inflateSetDictionary
+ below), inflate sets strm-adler to the adler32 checksum of the
+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
+ it sets strm->adler to the adler32 checksum of all output produced
+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+ an error code as described below. At the end of the stream, inflate()
+ checks that its computed adler32 checksum is equal to that saved by the
+ compressor and returns Z_STREAM_END only if the checksum is correct.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect
+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+ (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+ case, the application may then call inflateSync to look for a good
+ compression block.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front.
+
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. If a compressed stream with a larger window size is given as
+ input, inflate() will return with the error code Z_DATA_ERROR instead of
+ trying to allocate a larger window.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+ memLevel). msg is set to null if there is no error message. inflateInit2
+ does not perform any decompression apart from reading the zlib header if
+ present: this will be done by inflate(). (So next_in and avail_in may be
+ modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate
+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler32 value returned by this call of
+ inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least 0.1% larger than
+ sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h". (See the description
+ of deflateInit2 for more information about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ const voidp buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running crc with the bytes buf[0..len-1] and return the updated
+ crc. If buf is NULL, this function returns the required initial value
+ for the crc. Pre- and post-conditioning (one's complement) is performed
+ within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int err));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/fs/cramfs/inflate/zutil.h b/fs/cramfs/inflate/zutil.h
new file mode 100644
index 000000000..b3aa1991b
--- /dev/null
+++ b/fs/cramfs/inflate/zutil.h
@@ -0,0 +1,70 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+ /* functions */
+
+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
+ uInt len));
+
+#endif /* _Z_UTIL_H */
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
new file mode 100644
index 000000000..1bd40cb92
--- /dev/null
+++ b/fs/cramfs/inode.c
@@ -0,0 +1,484 @@
+/*
+ * Compressed rom filesystem for Linux.
+ *
+ * Copyright (C) 1999 Linus Torvalds.
+ *
+ * This file is released under the GPL.
+ */
+
+/*
+ * These are the VFS interfaces to the compressed rom filesystem.
+ * The actual compression is based on zlib, see the other files.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+
+#include <asm/uaccess.h>
+
+#include "cramfs.h"
+
+static struct super_operations cramfs_ops;
+static struct inode_operations cramfs_file_inode_operations;
+static struct inode_operations cramfs_dir_inode_operations;
+static struct inode_operations cramfs_symlink_inode_operations;
+
+#define CRAMINO(x) ((x)->offset?(x)->offset<<2:1)
+
+static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
+{
+ struct inode * inode = get_empty_inode();
+
+ if (inode) {
+ inode->i_mode = cramfs_inode->mode;
+ inode->i_uid = cramfs_inode->uid;
+ inode->i_size = cramfs_inode->size;
+ inode->i_gid = cramfs_inode->gid;
+ inode->i_ino = CRAMINO(cramfs_inode);
+ inode->i_sb = sb;
+ inode->i_dev = sb->s_dev;
+ insert_inode_hash(inode);
+ if (S_ISREG(inode->i_mode))
+ inode->i_op = &cramfs_file_inode_operations;
+ else if (S_ISDIR(inode->i_mode))
+ inode->i_op = &cramfs_dir_inode_operations;
+ else if (S_ISLNK(inode->i_mode))
+ inode->i_op = &cramfs_symlink_inode_operations;
+ else {
+ inode->i_size = 0;
+ init_special_inode(inode, inode->i_mode, cramfs_inode->size);
+ }
+ }
+ return inode;
+}
+
+/*
+ * We have our own block cache: don't fill up the buffer cache
+ * with the rom-image, because the way the filesystem is set
+ * up the accesses should be fairly regular and cached in the
+ * page cache and dentry tree anyway..
+ *
+ * This also acts as a way to guarantee contiguous areas of
+ * up to 2*PAGE_CACHE_SIZE, so that the caller doesn't need
+ * to worry about end-of-buffer issues even when decompressing
+ * a full page cache.
+ */
+#define READ_BUFFERS (2)
+static unsigned char read_buffers[READ_BUFFERS][PAGE_CACHE_SIZE*4];
+static int buffer_blocknr[READ_BUFFERS];
+static int last_buffer = 0;
+
+static void *cramfs_read(struct super_block *sb, unsigned int offset)
+{
+ struct buffer_head * bh_array[4];
+ int i, blocknr, buffer;
+
+ blocknr = offset >> PAGE_CACHE_SHIFT;
+ offset &= PAGE_CACHE_SIZE-1;
+ for (i = 0; i < READ_BUFFERS; i++) {
+ if (blocknr == buffer_blocknr[i])
+ return read_buffers[i] + offset;
+ }
+
+ /* Ok, read in four buffers completely first */
+ for (i = 0; i < 4; i++)
+ bh_array[i] = bread(sb->s_dev, blocknr + i, PAGE_CACHE_SIZE);
+
+ /* Ok, copy them to the staging area without sleeping.. */
+ buffer = last_buffer;
+ last_buffer = buffer ^ 1;
+ buffer_blocknr[buffer] = blocknr;
+ for (i = 0; i < 4; i++) {
+ struct buffer_head * bh = bh_array[i];
+ if (bh) {
+ memcpy(read_buffers[buffer] + i*PAGE_CACHE_SIZE, bh->b_data, PAGE_CACHE_SIZE);
+ bforget(bh);
+ }
+ blocknr++;
+ }
+ return read_buffers[buffer] + offset;
+}
+
+
+static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
+{
+ int i;
+ struct cramfs_super super;
+ unsigned long root_offset;
+ struct super_block * retval = NULL;
+
+ lock_super(sb);
+ set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+
+ /* Invalidate the read buffers on mount: think disk change.. */
+ for (i = 0; i < READ_BUFFERS; i++)
+ buffer_blocknr[i] = -1;
+
+ /* Read the first block and get the superblock from it */
+ memcpy(&super, cramfs_read(sb, 0), sizeof(super));
+
+ /* Do sanity checks on the superblock */
+ if (super.magic != CRAMFS_MAGIC) {
+ printk("wrong magic\n");
+ goto out;
+ }
+ if (memcmp(super.signature, CRAMFS_SIGNATURE, sizeof(super.signature))) {
+ printk("wrong signature\n");
+ goto out;
+ }
+
+ /* Check that the root inode is in a sane state */
+ root_offset = super.root.offset << 2;
+ if (root_offset < sizeof(struct cramfs_super)) {
+ printk("root offset too small\n");
+ goto out;
+ }
+ if (root_offset >= super.size) {
+ printk("root offset too large (%lu %u)\n", root_offset, super.size);
+ goto out;
+ }
+ if (!S_ISDIR(super.root.mode)) {
+ printk("root is not a directory\n");
+ goto out;
+ }
+
+ /* Set it all up.. */
+ sb->s_op = &cramfs_ops;
+ sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
+ retval = sb;
+
+out:
+ unlock_super(sb);
+ return retval;
+}
+
+/* Nothing to do.. */
+static void cramfs_put_super(struct super_block *sb)
+{
+ return;
+}
+
+static int cramfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+{
+ struct statfs tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.f_type = CRAMFS_MAGIC;
+ tmp.f_bsize = PAGE_CACHE_SIZE;
+ tmp.f_blocks = 0;
+ tmp.f_namelen = 255;
+ return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+}
+
+/*
+ * Read a cramfs directory entry..
+ *
+ * Remember: the inode number is the byte offset of the start
+ * of the directory..
+ */
+static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+ struct inode *inode = filp->f_dentry->d_inode;
+ struct super_block *sb = inode->i_sb;
+ unsigned int offset;
+ int copied;
+
+ /* Offset within the thing.. */
+ offset = filp->f_pos;
+ if (offset >= inode->i_size)
+ return 0;
+ /* Directory entries are always 4-byte aligned */
+ if (offset & 3)
+ return -EINVAL;
+
+ copied = 0;
+ while (offset < inode->i_size) {
+ struct cramfs_inode *de;
+ unsigned long nextoffset;
+ char *name;
+ int namelen, error;
+
+ de = cramfs_read(sb, offset + inode->i_ino);
+ name = (char *)(de+1);
+
+ /*
+ * Namelengths on disk are shifted by two
+ * and the name padded out to 4-byte boundaries
+ * with zeroes.
+ */
+ namelen = de->namelen << 2;
+ nextoffset = offset + sizeof(*de) + namelen;
+ for (;;) {
+ if (!namelen)
+ return -EIO;
+ if (name[namelen-1])
+ break;
+ namelen--;
+ }
+ error = filldir(dirent, name, namelen, offset, CRAMINO(de));
+ if (error)
+ break;
+
+ offset = nextoffset;
+ filp->f_pos = offset;
+ copied++;
+ }
+ return 0;
+}
+
+/*
+ * Lookup and fill in the inode data..
+ */
+static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
+{
+ unsigned int offset = 0;
+
+ while (offset < dir->i_size) {
+ struct cramfs_inode *de;
+ char *name;
+ int namelen;
+
+ de = cramfs_read(dir->i_sb, offset + dir->i_ino);
+ name = (char *)(de+1);
+ namelen = de->namelen << 2;
+ offset += sizeof(*de) + namelen;
+
+ /* Quick check that the name is roughly the right length */
+ if (((dentry->d_name.len + 3) & ~3) != namelen)
+ continue;
+
+ for (;;) {
+ if (!namelen)
+ return ERR_PTR(-EIO);
+ if (name[namelen-1])
+ break;
+ namelen--;
+ }
+ if (namelen != dentry->d_name.len)
+ continue;
+ if (memcmp(dentry->d_name.name, name, namelen))
+ continue;
+ d_add(dentry, get_cramfs_inode(dir->i_sb, de));
+ return NULL;
+ }
+ d_add(dentry, NULL);
+ return NULL;
+}
+
+static int cramfs_readpage(struct dentry *dentry, struct page * page)
+{
+ struct inode *inode = dentry->d_inode;
+ unsigned long maxblock, bytes;
+
+ maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ bytes = 0;
+ if (page->index < maxblock) {
+ struct super_block *sb = inode->i_sb;
+ unsigned long block_offset = inode->i_ino + page->index*4;
+ unsigned long start_offset = inode->i_ino + maxblock*4;
+ unsigned long end_offset;
+
+ end_offset = *(u32 *) cramfs_read(sb, block_offset);
+ if (page->index)
+ start_offset = *(u32 *) cramfs_read(sb, block_offset-4);
+
+ bytes = inode->i_size & (PAGE_CACHE_SIZE - 1);
+ if (page->index < maxblock)
+ bytes = PAGE_CACHE_SIZE;
+
+ cramfs_uncompress_block((void *) page_address(page), PAGE_CACHE_SIZE, cramfs_read(sb, start_offset), end_offset - start_offset);
+ }
+ memset((void *) (page_address(page) + bytes), 0, PAGE_CACHE_SIZE - bytes);
+ SetPageUptodate(page);
+ UnlockPage(page);
+ return 0;
+}
+
+static struct page *get_symlink_page(struct dentry *dentry)
+{
+ return read_cache_page(&dentry->d_inode->i_data, 0, (filler_t *)cramfs_readpage, dentry);
+}
+
+static int cramfs_readlink(struct dentry *dentry, char *buffer, int len)
+{
+ struct inode *inode = dentry->d_inode;
+ int retval;
+
+ if (!inode || !S_ISLNK(inode->i_mode))
+ return -EBADF;
+
+ retval = inode->i_size;
+ if (retval) {
+ int len;
+ struct page *page = get_symlink_page(dentry);
+
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+ wait_on_page(page);
+ len = retval;
+ retval = -EIO;
+ if (Page_Uptodate(page)) {
+ retval = -EFAULT;
+ if (!copy_to_user(buffer, (void *) page_address(page), len))
+ retval = len;
+ }
+ page_cache_release(page);
+ }
+ return retval;
+}
+
+static struct dentry *cramfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
+{
+ struct page *page = get_symlink_page(dentry);
+ struct dentry *result;
+
+ if (IS_ERR(page)) {
+ dput(base);
+ return ERR_PTR(PTR_ERR(page));
+ }
+
+ result = lookup_dentry((void *) page_address(page), base, follow);
+ page_cache_release(page);
+ return result;
+}
+
+/*
+ * Our operations:
+ *
+ * A regular file can be read and mmap'ed.
+ */
+static struct file_operations cramfs_file_operations = {
+ NULL, /* lseek - default */
+ generic_file_read, /* read */
+ NULL, /* write - bad */
+ NULL, /* readdir */
+ NULL, /* poll - default */
+ NULL, /* ioctl */
+ generic_file_mmap, /* mmap */
+ NULL, /* open */
+ NULL, /* flush */
+ NULL, /* release */
+ NULL, /* fsync */
+ NULL, /* fasync */
+};
+
+/*
+ * A directory can only readdir
+ */
+static struct file_operations cramfs_directory_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read */
+ NULL, /* write - bad */
+ cramfs_readdir, /* readdir */
+ NULL, /* poll - default */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* open */
+ NULL, /* flush */
+ NULL, /* release */
+ NULL, /* fsync */
+ NULL, /* fasync */
+};
+
+static struct inode_operations cramfs_file_inode_operations = {
+ &cramfs_file_operations,
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* get_block */
+ cramfs_readpage, /* readpage */
+ NULL, /* writepage */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL /* revalidate */
+};
+
+static struct inode_operations cramfs_dir_inode_operations = {
+ &cramfs_directory_operations,
+ NULL, /* create */
+ cramfs_lookup, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* get_block */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL /* revalidate */
+};
+
+static struct inode_operations cramfs_symlink_inode_operations = {
+ NULL, /* symlinks do not have files */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ cramfs_readlink, /* readlink */
+ cramfs_follow_link, /* follow_link */
+ NULL, /* get_block */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL /* revalidate */
+};
+
+static struct super_operations cramfs_ops = {
+ NULL, /* read inode */
+ NULL, /* write inode */
+ NULL, /* put inode */
+ NULL, /* delete inode */
+ NULL, /* notify change */
+ cramfs_put_super, /* put super */
+ NULL, /* write super */
+ cramfs_statfs, /* statfs */
+ NULL /* remount */
+};
+
+static struct file_system_type cramfs_fs_type = {
+ "cramfs",
+ FS_REQUIRES_DEV,
+ cramfs_read_super,
+ NULL
+};
+
+static int __init init_cramfs_fs(void)
+{
+ cramfs_uncompress_init();
+ return register_filesystem(&cramfs_fs_type);
+}
+
+static void __exit exit_cramfs_fs(void)
+{
+ cramfs_uncompress_exit();
+ unregister_filesystem(&cramfs_fs_type);
+}
+
+module_init(init_cramfs_fs)
+module_exit(exit_cramfs_fs)
diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c
new file mode 100644
index 000000000..8e92eb122
--- /dev/null
+++ b/fs/cramfs/uncompress.c
@@ -0,0 +1,60 @@
+/*
+ * uncompress.c
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * cramfs interfaces to the uncompression library. There's really just
+ * three entrypoints:
+ *
+ * - cramfs_uncompress_init() - called to initialize the thing.
+ * - cramfs_uncompress_exit() - tell me when you're done
+ * - cramfs_uncompress_block() - uncompress a block.
+ *
+ * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
+ * only have one stream, and we'll initialize it only once even if it
+ * then is used by multiple filesystems.
+ */
+
+#include <linux/kernel.h>
+
+#include "inflate/zlib.h"
+
+static z_stream stream;
+static int initialized = 0;
+
+int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
+{
+ int err;
+
+ stream.next_in = src;
+ stream.avail_in = srclen;
+
+ stream.next_out = dst;
+ stream.avail_out = dstlen;
+
+ inflateReset(&stream);
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ printk("Error %d while decompressing!\n", err);
+ printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
+ }
+ return stream.total_out;
+}
+
+int cramfs_uncompress_init(void)
+{
+ if (!initialized++) {
+ stream.next_in = NULL;
+ stream.avail_in = 0;
+ inflateInit(&stream);
+ }
+ return 0;
+}
+
+int cramfs_uncompress_exit(void)
+{
+ if (!--initialized)
+ inflateEnd(&stream);
+ return 0;
+}
diff --git a/fs/dcache.c b/fs/dcache.c
index 75a44c8d9..a9a81328a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -410,7 +410,7 @@ void shrink_dcache_parent(struct dentry * parent)
* ...
* 6 - base-level: try to shrink a bit.
*/
-int shrink_dcache_memory(int priority, unsigned int gfp_mask)
+int shrink_dcache_memory(int priority, unsigned int gfp_mask, zone_t * zone)
{
if (gfp_mask & __GFP_IO) {
int count = 0;
diff --git a/fs/devices.c b/fs/devices.c
index b44acfacf..3efb5822a 100644
--- a/fs/devices.c
+++ b/fs/devices.c
@@ -37,9 +37,7 @@ static struct device_struct chrdevs[MAX_CHRDEV] = {
{ NULL, NULL },
};
-static struct device_struct blkdevs[MAX_BLKDEV] = {
- { NULL, NULL },
-};
+extern int get_blkdev_list(char *);
int get_device_list(char * page)
{
@@ -52,12 +50,7 @@ int get_device_list(char * page)
len += sprintf(page+len, "%3d %s\n", i, chrdevs[i].name);
}
}
- len += sprintf(page+len, "\nBlock devices:\n");
- for (i = 0; i < MAX_BLKDEV ; i++) {
- if (blkdevs[i].fops) {
- len += sprintf(page+len, "%3d %s\n", i, blkdevs[i].name);
- }
- }
+ len += get_blkdev_list(page+len);
return len;
}
@@ -103,16 +96,6 @@ static struct file_operations * get_fops(
return ret;
}
-
-/*
- Return the function table of a device.
- Load the driver if needed.
-*/
-struct file_operations * get_blkfops(unsigned int major)
-{
- return get_fops (major,0,MAX_BLKDEV,"block-major-%d",blkdevs);
-}
-
struct file_operations * get_chrfops(unsigned int major, unsigned int minor)
{
return get_fops (major,minor,MAX_CHRDEV,"char-major-%d",chrdevs);
@@ -139,27 +122,6 @@ int register_chrdev(unsigned int major, const char * name, struct file_operation
return 0;
}
-int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
-{
- if (major == 0) {
- for (major = MAX_BLKDEV-1; major > 0; major--) {
- if (blkdevs[major].fops == NULL) {
- blkdevs[major].name = name;
- blkdevs[major].fops = fops;
- return major;
- }
- }
- return -EBUSY;
- }
- if (major >= MAX_BLKDEV)
- return -EINVAL;
- if (blkdevs[major].fops && blkdevs[major].fops != fops)
- return -EBUSY;
- blkdevs[major].name = name;
- blkdevs[major].fops = fops;
- return 0;
-}
-
int unregister_chrdev(unsigned int major, const char * name)
{
if (major >= MAX_CHRDEV)
@@ -173,119 +135,6 @@ int unregister_chrdev(unsigned int major, const char * name)
return 0;
}
-int unregister_blkdev(unsigned int major, const char * name)
-{
- if (major >= MAX_BLKDEV)
- return -EINVAL;
- if (!blkdevs[major].fops)
- return -EINVAL;
- if (strcmp(blkdevs[major].name, name))
- return -EINVAL;
- blkdevs[major].name = NULL;
- blkdevs[major].fops = NULL;
- return 0;
-}
-
-/*
- * This routine checks whether a removable media has been changed,
- * and invalidates all buffer-cache-entries in that case. This
- * is a relatively slow routine, so we have to try to minimize using
- * it. Thus it is called only upon a 'mount' or 'open'. This
- * is the best way of combining speed and utility, I think.
- * People changing diskettes in the middle of an operation deserve
- * to lose :-)
- */
-int check_disk_change(kdev_t dev)
-{
- int i;
- struct file_operations * fops;
- struct super_block * sb;
-
- i = MAJOR(dev);
- if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
- return 0;
- if (fops->check_media_change == NULL)
- return 0;
- if (!fops->check_media_change(dev))
- return 0;
-
- printk(KERN_DEBUG "VFS: Disk change detected on device %s\n",
- bdevname(dev));
-
- sb = get_super(dev);
- if (sb && invalidate_inodes(sb))
- printk("VFS: busy inodes on changed media.\n");
-
- invalidate_buffers(dev);
-
- if (fops->revalidate)
- fops->revalidate(dev);
- return 1;
-}
-
-/*
- * Called every time a block special file is opened
- */
-int blkdev_open(struct inode * inode, struct file * filp)
-{
- int ret = -ENODEV;
- filp->f_op = get_blkfops(MAJOR(inode->i_rdev));
- if (filp->f_op != NULL){
- ret = 0;
- if (filp->f_op->open != NULL)
- ret = filp->f_op->open(inode,filp);
- }
- return ret;
-}
-
-int blkdev_release(struct inode * inode)
-{
- struct file_operations *fops = get_blkfops(MAJOR(inode->i_rdev));
- if (fops && fops->release)
- return fops->release(inode,NULL);
- return 0;
-}
-
-
-/*
- * Dummy default file-operations: the only thing this does
- * is contain the open that then fills in the correct operations
- * depending on the special file...
- */
-struct file_operations def_blk_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- blkdev_open, /* open */
- NULL, /* flush */
- NULL, /* release */
-};
-
-struct inode_operations blkdev_inode_operations = {
- &def_blk_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
-};
-
/*
* Called every time a character special file is opened
*/
@@ -307,38 +156,12 @@ int chrdev_open(struct inode * inode, struct file * filp)
* is contain the open that then fills in the correct operations
* depending on the special file...
*/
-struct file_operations def_chr_fops = {
- NULL, /* lseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- chrdev_open, /* open */
- NULL, /* flush */
- NULL, /* release */
+static struct file_operations def_chr_fops = {
+ open: chrdev_open
};
-struct inode_operations chrdev_inode_operations = {
- &def_chr_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+static struct inode_operations chrdev_inode_operations = {
+ &def_chr_fops /* default file operations */
};
/*
@@ -352,18 +175,6 @@ char * kdevname(kdev_t dev)
return buffer;
}
-char * bdevname(kdev_t dev)
-{
- static char buffer[32];
- const char * name = blkdevs[MAJOR(dev)].name;
-
- if (!name)
- name = "unknown-block";
-
- sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
- return buffer;
-}
-
char * cdevname(kdev_t dev)
{
static char buffer[32];
@@ -385,8 +196,9 @@ void init_special_inode(struct inode *inode, umode_t mode, int rdev)
} else if (S_ISBLK(mode)) {
inode->i_op = &blkdev_inode_operations;
inode->i_rdev = to_kdev_t(rdev);
+ inode->i_bdev = bdget(rdev);
} else if (S_ISFIFO(mode))
- init_fifo(inode);
+ inode->i_op = &fifo_inode_operations;
else if (S_ISSOCK(mode))
;
else
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index b11cae5ba..56433a343 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -284,10 +284,8 @@ static void devpts_read_inode(struct inode *inode)
if ( ino >= sbi->max_ptys )
return; /* Bogus */
- inode->i_mode = S_IFCHR;
- inode->i_rdev = MKDEV(0,0); /* Gets filled in by devpts_pty_new() */
-
- inode->i_op = &chrdev_inode_operations;
+ /* Gets filled in by devpts_pty_new() */
+ init_special_inode(inode,S_IFCHR,0);
return;
}
diff --git a/fs/devpts/root.c b/fs/devpts/root.c
index 9b4d194f2..92978217f 100644
--- a/fs/devpts/root.c
+++ b/fs/devpts/root.c
@@ -25,17 +25,6 @@ static struct file_operations devpts_root_operations = {
NULL, /* read */
NULL, /* write */
devpts_root_readdir, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* flush */
- NULL, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
};
struct inode_operations devpts_root_inode_operations = {
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index 05a3334f7..4e84b1abb 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -21,8 +21,6 @@ static struct file_operations efs_dir_operations = {
NULL, /* release */
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
extern int efs_get_block(struct inode *, long, struct buffer_head *, int);
diff --git a/fs/efs/file.c b/fs/efs/file.c
index adcc03120..8a2a8163d 100644
--- a/fs/efs/file.c
+++ b/fs/efs/file.c
@@ -74,8 +74,6 @@ static struct file_operations efs_file_operations = {
NULL, /* release */
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
struct inode_operations efs_file_inode_operations = {
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index b6a2ad3fa..7ed3db6ad 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -131,16 +131,10 @@ void efs_read_inode(struct inode *inode) {
inode->i_op = &efs_symlink_inode_operations;
break;
case S_IFCHR:
- inode->i_rdev = device;
- inode->i_op = &chrdev_inode_operations;
- break;
case S_IFBLK:
- inode->i_rdev = device;
- inode->i_op = &blkdev_inode_operations;
- break;
case S_IFIFO:
- init_fifo(inode);
- break;
+ init_special_inode(inode, inode->i_mode, device);
+ break;
default:
printk(KERN_WARNING "EFS: unsupported inode mode %o\n", inode->i_mode);
goto read_inode_error;
diff --git a/fs/exec.c b/fs/exec.c
index e329252d1..7a7858066 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -42,14 +42,6 @@
#include <linux/kmod.h>
#endif
-/*
- * Here are the actual binaries that will be accepted:
- * add more with "register_binfmt()" if using modules...
- *
- * These are defined again for the 'real' modules if you are using a
- * module definition for these routines.
- */
-
static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
int register_binfmt(struct linux_binfmt * fmt)
@@ -269,6 +261,41 @@ int copy_strings_kernel(int argc,char ** argv, struct linux_binprm *bprm)
return r;
}
+/*
+ * This routine is used to map in a page into an address space: needed by
+ * execve() for the initial stack and environment pages.
+ */
+static void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address)
+{
+ pgd_t * pgd;
+ pmd_t * pmd;
+ pte_t * pte;
+
+ if (page_count(page) != 1)
+ printk("mem_map disagrees with %p at %08lx\n", page, address);
+ pgd = pgd_offset(tsk->mm, address);
+ pmd = pmd_alloc(pgd, address);
+ if (!pmd) {
+ __free_page(page);
+ oom(tsk);
+ return;
+ }
+ pte = pte_alloc(pmd, address);
+ if (!pte) {
+ __free_page(page);
+ oom(tsk);
+ return;
+ }
+ if (!pte_none(*pte)) {
+ pte_ERROR(*pte);
+ __free_page(page);
+ return;
+ }
+ flush_page_to_ram(page);
+ set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY))));
+/* no need for flush_tlb */
+}
+
int setup_arg_pages(struct linux_binprm *bprm)
{
unsigned long stack_base;
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 26db0a623..8920f55a0 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -15,46 +15,3 @@
* This file will contain the Access Control Lists management for the
* second extended file system.
*/
-
-
-/*
- * ext2_permission ()
- *
- * Check for access rights
- */
-int ext2_permission (struct inode * inode, int mask)
-{
- unsigned short mode = inode->i_mode;
-
- /*
- * Nobody gets write access to a file on a readonly-fs
- */
- if ((mask & S_IWOTH) &&
- (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) &&
- IS_RDONLY(inode))
- return -EROFS;
- /*
- * Nobody gets write access to an immutable file
- */
- if ((mask & S_IWOTH) && IS_IMMUTABLE(inode))
- return -EACCES;
-
- /*
- * If no ACL, checks using the file mode
- */
- else if (current->fsuid == inode->i_uid)
- mode >>= 6;
- else if (in_group_p (inode->i_gid))
- mode >>= 3;
- /*
- * Access is always granted for root. We now check last,
- * though, for BSD process accounting correctness
- */
- if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
- return 0;
- if ((mask == S_IROTH) ||
- (S_ISDIR(mode) && !(mask & ~(S_IROTH | S_IXOTH))))
- if (capable(CAP_DAC_READ_SEARCH))
- return 0;
- return -EACCES;
-}
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 6c232ce79..43a425bbb 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -118,8 +118,8 @@ error_out:
*
* Return the slot used to store the bitmap, or a -ve error code.
*/
-static int load__block_bitmap (struct super_block * sb,
- unsigned int block_group)
+static int __load_block_bitmap (struct super_block * sb,
+ unsigned int block_group)
{
int i, j, retval = 0;
unsigned long block_bitmap_number;
@@ -136,7 +136,7 @@ static int load__block_bitmap (struct super_block * sb,
if (sb->u.ext2_sb.s_block_bitmap_number[block_group] ==
block_group)
return block_group;
- ext2_error (sb, "load_block_bitmap",
+ ext2_error (sb, "__load_block_bitmap",
"block_group != block_bitmap_number");
}
retval = read_block_bitmap (sb, block_group, block_group);
@@ -192,7 +192,7 @@ static int load__block_bitmap (struct super_block * sb,
* Return the slot number of the group in the superblock bitmap cache's on
* success, or a -ve error code.
*
- * There is still one inconsistancy here --- if the number of groups in this
+ * There is still one inconsistency here --- if the number of groups in this
* filesystems is <= EXT2_MAX_GROUP_LOADED, then we have no way of
* differentiating between a group for which we have never performed a bitmap
* IO request, and a group for which the last bitmap read request failed.
@@ -224,7 +224,7 @@ static inline int load_block_bitmap (struct super_block * sb,
* If not, then do a full lookup for this block group.
*/
else {
- slot = load__block_bitmap (sb, block_group);
+ slot = __load_block_bitmap (sb, block_group);
}
/*
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 2cc69ee5b..c97292620 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -43,8 +43,6 @@ static struct file_operations ext2_dir_operations = {
NULL, /* no special release code */
ext2_sync_file, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
/*
@@ -67,7 +65,7 @@ struct inode_operations ext2_dir_inode_operations = {
NULL, /* readpage */
NULL, /* writepage */
NULL, /* truncate */
- ext2_permission, /* permission */
+ NULL, /* permission */
NULL /* revalidate */
};
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 5ebba9da1..1c915e274 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -29,9 +29,7 @@
#define MAX(a,b) (((a)>(b))?(a):(b))
static long long ext2_file_lseek(struct file *, long long, int);
-#if BITS_PER_LONG < 64
static int ext2_open_file (struct inode *, struct file *);
-#endif
#define EXT2_MAX_SIZE(bits) \
(((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \
@@ -121,11 +119,11 @@ static int ext2_release_file (struct inode * inode, struct file * filp)
return 0;
}
-#if BITS_PER_LONG < 64
/*
* Called when an inode is about to be open.
* We use this to disallow opening RW large files on 32bit systems if
- * the caller didn't specify O_LARGEFILE.
+ * the caller didn't specify O_LARGEFILE. On 64bit systems we force
+ * on this flag in sys_open.
*/
static int ext2_open_file (struct inode * inode, struct file * filp)
{
@@ -133,7 +131,6 @@ static int ext2_open_file (struct inode * inode, struct file * filp)
return -EFBIG;
return 0;
}
-#endif
/*
* We have mostly NULL's here: the current defaults are ok for
@@ -147,17 +144,11 @@ static struct file_operations ext2_file_operations = {
NULL, /* poll - default */
ext2_ioctl, /* ioctl */
generic_file_mmap, /* mmap */
-#if BITS_PER_LONG == 64
- NULL, /* no special open is needed */
-#else
ext2_open_file,
-#endif
NULL, /* flush */
ext2_release_file, /* release */
ext2_sync_file, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
struct inode_operations ext2_file_inode_operations = {
@@ -177,6 +168,6 @@ struct inode_operations ext2_file_inode_operations = {
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
ext2_truncate, /* truncate */
- ext2_permission, /* permission */
+ NULL, /* permission */
NULL, /* revalidate */
};
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index dadd3c67e..cefde46fd 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -723,33 +723,6 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
return 0;
}
-static struct file_system_type ext2_fs_type = {
- "ext2",
- FS_REQUIRES_DEV /* | FS_IBASKET */, /* ibaskets have unresolved bugs */
- ext2_read_super,
- NULL
-};
-
-int __init init_ext2_fs(void)
-{
- return register_filesystem(&ext2_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
- return init_ext2_fs();
-}
-
-void cleanup_module(void)
-{
- unregister_filesystem(&ext2_fs_type);
-}
-
-#endif
-
int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
{
unsigned long overhead;
@@ -805,3 +778,25 @@ int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
tmp.f_namelen = EXT2_NAME_LEN;
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
+
+static struct file_system_type ext2_fs_type = {
+ "ext2",
+ FS_REQUIRES_DEV /* | FS_IBASKET */, /* ibaskets have unresolved bugs */
+ ext2_read_super,
+ NULL
+};
+
+static int __init init_ext2_fs(void)
+{
+ return register_filesystem(&ext2_fs_type);
+}
+
+static void __exit exit_ext2_fs(void)
+{
+ unregister_filesystem(&ext2_fs_type);
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_ext2_fs)
+module_exit(exit_ext2_fs)
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 628c0bb9c..c31d02024 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -10,6 +10,7 @@
* VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu>
* Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk>
* Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV
+ * Short name translation 1999 by Wolfram Pienkoss <wp@bsz.shk.th.schule.de>
*/
#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
@@ -55,22 +56,21 @@ struct file_operations fat_dir_operations = {
/*
* Convert Unicode 16 to UTF8, translated Unicode, or ASCII.
- * If uni_xlate is enabled and we
- * can't get a 1:1 conversion, use a colon as an escape character since
- * it is normally invalid on the vfat filesystem. The following three
- * characters are a sort of uuencoded 16 bit Unicode value. This lets
- * us do a full dump and restore of Unicode filenames. We could get
- * into some trouble with long Unicode names, but ignore that right now.
+ * If uni_xlate is enabled and we can't get a 1:1 conversion, use a
+ * colon as an escape character since it is normally invalid on the vfat
+ * filesystem. The following four characters are the hexadecimal digits
+ * of Unicode value. This lets us do a full dump and restore of Unicode
+ * filenames. We could get into some trouble with long Unicode names,
+ * but ignore that right now.
* Ahem... Stack smashing in ring 0 isn't fun. Fixed.
*/
static int
uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate,
struct nls_table *nls)
{
- unsigned char *ip, *op;
- unsigned char ch, cl;
- unsigned char *uni_page;
- unsigned short val;
+ unsigned char *ip, *op, *uni_page, ch, cl, nc;
+ unsigned int ec;
+ int k;
ip = uni;
op = ascii;
@@ -84,14 +84,15 @@ uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate,
*op++ = uni_page[cl];
} else {
if (uni_xlate == 1) {
- *op++ = ':';
- val = (cl << 8) + ch;
- op[2] = fat_uni2esc[val & 0x3f];
- val >>= 6;
- op[1] = fat_uni2esc[val & 0x3f];
- val >>= 6;
- *op = fat_uni2esc[val & 0x3f];
- op += 3;
+ *op = ':';
+ ec = (ch << 8) + cl;
+ for (k = 4; k > 0; k--) {
+ nc = ec & 0xF;
+ op[k] = nc > 9 ? nc + ('a' - 10)
+ : nc + '0';
+ ec >>= 4;
+ }
+ op += 5;
} else {
*op++ = '?';
}
@@ -119,8 +120,31 @@ static void dump_de(struct msdos_dir_entry *de)
printk("]\n");
}
#endif
-static int memicmp(const char *s1, const char *s2, int len) {
- while(len--) if (tolower(*s1++)!=tolower(*s2++)) return 1;
+
+static inline unsigned char
+fat_tolower(struct nls_table *t, unsigned char c)
+{
+ unsigned char nc = t->charset2lower[c];
+
+ return nc ? nc : c;
+}
+
+static inline struct nls_unicode
+fat_short2lower_uni(struct nls_table *t, unsigned char c)
+{
+ unsigned char nc = t->charset2lower[c];
+
+ return nc ? t->charset2uni[nc] : t->charset2uni[c];
+}
+
+static int
+fat_strnicmp(struct nls_table *t, const unsigned char *s1,
+ const unsigned char *s2, int len)
+{
+ while(len--)
+ if (fat_tolower(t, *s1++) != fat_tolower(t, *s2++))
+ return 1;
+
return 0;
}
@@ -128,23 +152,21 @@ static int memicmp(const char *s1, const char *s2, int len) {
* Return values: negative -> error, 0 -> not found, positive -> found,
* value is the total amount of slots, including the shortname entry.
*/
-int fat_search_long(
- struct inode *inode, const char *name, int name_len, int anycase,
- loff_t *spos, loff_t *lpos)
+int fat_search_long(struct inode *inode, const char *name, int name_len,
+ int anycase, loff_t *spos, loff_t *lpos)
{
struct super_block *sb = inode->i_sb;
- int ino,i,i2,last;
- char c;
struct buffer_head *bh = NULL;
struct msdos_dir_entry *de;
- loff_t cpos = 0;
- char bufname[14];
- unsigned char long_slots;
+ struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
+ struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
+ struct nls_unicode bufuname[14];
+ unsigned char xlate_len, long_slots, *unicode = NULL;
+ char c, bufname[260]; /* 256 + 4 */
int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
int utf8 = MSDOS_SB(sb)->options.utf8;
- unsigned char *unicode = NULL;
- struct nls_table *nls = MSDOS_SB(sb)->nls_io;
- int res = 0;
+ int ino, i, i2, last, res = 0;
+ loff_t cpos = 0;
while(1) {
if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
@@ -157,7 +179,7 @@ parse_record:
continue;
if (de->attr != ATTR_EXT && IS_FREE(de->name))
continue;
- if (de->attr == ATTR_EXT) {
+ if (de->attr == ATTR_EXT) {
struct msdos_dir_slot *ds;
int offset;
unsigned char id;
@@ -226,36 +248,42 @@ parse_long:
for (i = 0, last = 0; i < 8;) {
if (!(c = de->name[i])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
if (c == 0x05) c = 0xE5;
- if ((bufname[i++] = c) != ' ')
+ bufuname[i++] = fat_short2lower_uni(nls_disk, c);
+ if (c != ' ')
last = i;
}
i = last;
- bufname[i++] = '.';
+ bufuname[i++] = fat_short2lower_uni(nls_disk, '.');
for (i2 = 0; i2 < 3; i2++) {
if (!(c = de->ext[i2])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
- if ((bufname[i++] = c) != ' ')
+ bufuname[i++] = fat_short2lower_uni(nls_disk, c);
+ if (c != ' ')
last = i;
}
if (!last)
continue;
- if (last==name_len)
- if ((!anycase && !memcmp(name, bufname, last)) ||
- (anycase && !memicmp(name, bufname, last)))
- goto Found;
+ memset(&bufuname[last], 0, sizeof(struct nls_unicode));
+ xlate_len = utf8
+ ?utf8_wcstombs(bufname, (__u16 *) &bufuname, 260)
+ :uni16_to_x8(bufname, (unsigned char *) &bufuname,
+ uni_xlate, nls_io);
+ if (xlate_len == name_len)
+ if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
+ (anycase && !fat_strnicmp(nls_io, name, bufname,
+ xlate_len)))
+ goto Found;
+
if (long_slots) {
- char longname[260]; /* 256 + 4 */
- unsigned char long_len;
- long_len = utf8
- ?utf8_wcstombs(longname, (__u16 *) unicode, 260)
- :uni16_to_x8(longname, unicode, uni_xlate, nls);
- if (long_len != name_len)
+ xlate_len = utf8
+ ?utf8_wcstombs(bufname, (__u16 *) unicode, 260)
+ :uni16_to_x8(bufname, unicode, uni_xlate, nls_io);
+ if (xlate_len != name_len)
continue;
- if ((!anycase && !memcmp(name, longname, long_len)) ||
- (anycase && !memicmp(name, longname, long_len)))
+ if ((!anycase && !memcmp(name, bufname, xlate_len)) ||
+ (anycase && !fat_strnicmp(nls_io, name, bufname,
+ xlate_len)))
goto Found;
}
}
@@ -272,31 +300,23 @@ EODir:
return res;
}
-static int fat_readdirx(
- struct inode *inode,
- struct file *filp,
- void *dirent,
- filldir_t filldir,
- int shortnames,
- int both)
+static int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
+ filldir_t filldir, int shortnames, int both)
{
struct super_block *sb = inode->i_sb;
- int ino,inum,i,i2,last;
- char c;
struct buffer_head *bh;
struct msdos_dir_entry *de;
- unsigned long lpos;
- loff_t cpos;
- unsigned char long_slots;
+ struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
+ struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
+ struct nls_unicode bufuname[14], *ptuname = &bufuname[0];
+ unsigned char long_slots, *unicode = NULL;
+ char c, bufname[56], *ptname = bufname;
+ unsigned long lpos, dummy, *furrfu = &lpos;
int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
+ int isvfat = MSDOS_SB(sb)->options.isvfat;
int utf8 = MSDOS_SB(sb)->options.utf8;
- unsigned char *unicode = NULL;
- struct nls_table *nls = MSDOS_SB(sb)->nls_io;
- char bufname[14];
- char *ptname = bufname;
- int dotoffset = 0;
- unsigned long *furrfu = &lpos;
- unsigned long dummy;
+ int ino,inum,i,i2,last, dotoffset = 0;
+ loff_t cpos;
cpos = filp->f_pos;
/* Fake . and .. for the root directory. */
@@ -322,7 +342,7 @@ GetNew:
if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
goto EODir;
/* Check for long filename entry */
- if (MSDOS_SB(sb)->options.isvfat) {
+ if (isvfat) {
if (de->name[0] == (__s8) DELETED_FLAG)
goto RecEnd;
if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
@@ -334,7 +354,7 @@ GetNew:
goto RecEnd;
}
- if (MSDOS_SB(sb)->options.isvfat && de->attr == ATTR_EXT) {
+ if (isvfat && de->attr == ATTR_EXT) {
struct msdos_dir_slot *ds;
int offset;
unsigned char id;
@@ -403,23 +423,27 @@ ParseLong:
}
if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {
+ *ptuname = fat_short2lower_uni(nls_disk, '.');
*ptname++ = '.';
dotoffset = 1;
}
for (i = 0, last = 0; i < 8;) {
if (!(c = de->name[i])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
/* see namei.c, msdos_format_name */
if (c == 0x05) c = 0xE5;
- if ((ptname[i++] = c) != ' ')
+ ptuname[i] = fat_short2lower_uni(nls_disk, c);
+ ptname[i++] = (c>='A' && c<='Z') ? c+32 : c;
+ if (c != ' ')
last = i;
}
i = last;
+ ptuname[i] = fat_short2lower_uni(nls_disk, '.');
ptname[i++] = '.';
for (i2 = 0; i2 < 3; i2++) {
if (!(c = de->ext[i2])) break;
- if (c >= 'A' && c <= 'Z') c += 32;
- if ((ptname[i++] = c) != ' ')
+ ptuname[i] = fat_short2lower_uni(nls_disk, c);
+ ptname[i++] = (c>='A' && c<='Z') ? c+32 : c;
+ if (c != ' ')
last = i;
}
if (!last)
@@ -442,6 +466,13 @@ ParseLong:
inum = iunique(sb, MSDOS_ROOT_INO);
}
+ if (isvfat) {
+ memset(&bufuname[i], 0, sizeof(struct nls_unicode));
+ i = utf8 ? utf8_wcstombs(bufname, (__u16 *) &bufuname, 56)
+ : uni16_to_x8(bufname, (unsigned char *) &bufuname,
+ uni_xlate, nls_io);
+ }
+
if (!long_slots||shortnames) {
if (both)
bufname[i] = '\0';
@@ -451,7 +482,7 @@ ParseLong:
char longname[275];
unsigned char long_len = utf8
? utf8_wcstombs(longname, (__u16 *) unicode, 275)
- : uni16_to_x8(longname, unicode, uni_xlate, nls);
+ : uni16_to_x8(longname, unicode, uni_xlate, nls_io);
if (both) {
memcpy(&longname[long_len+1], bufname, i);
long_len += i;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 033c40c2b..3919f6517 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -653,13 +653,13 @@ fat_read_super(struct super_block *sb, void *data, int silent,
if (sbi->options.isvfat && !opts.utf8) {
p = opts.iocharset ? opts.iocharset : "iso8859-1";
sbi->nls_io = load_nls(p);
- if (! sbi->nls_io) {
+ if (! sbi->nls_io)
/* Fail only if explicit charset specified */
if (opts.iocharset)
goto out_unload_nls;
- sbi->nls_io = load_nls_default();
- }
}
+ if (! sbi->nls_io)
+ sbi->nls_io = load_nls_default();
root_inode=get_empty_inode();
if (!root_inode)
@@ -681,8 +681,7 @@ fat_read_super(struct super_block *sb, void *data, int silent,
out_no_root:
printk("get root inode failed\n");
iput(root_inode);
- if (sbi->nls_io)
- unload_nls(sbi->nls_io);
+ unload_nls(sbi->nls_io);
out_unload_nls:
unload_nls(sbi->nls_disk);
goto out_fail;
diff --git a/fs/fifo.c b/fs/fifo.c
index 516e690c9..88d8bd33b 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -153,28 +153,9 @@ err_nolock_nocleanup:
* depending on the access mode of the file...
*/
static struct file_operations def_fifo_fops = {
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- fifo_open, /* will set read or write pipe_fops */
- NULL,
- NULL,
- NULL,
- NULL
+ open: fifo_open, /* will set read or write pipe_fops */
};
struct inode_operations fifo_inode_operations = {
&def_fifo_fops, /* default file operations */
};
-
-
-/* Goner. Filesystems do not use it anymore. */
-
-void init_fifo(struct inode * inode)
-{
- inode->i_op = &fifo_inode_operations;
-}
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 08d4aaf1b..bae48e19a 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -32,6 +32,7 @@
#include <linux/devpts_fs.h>
#include <linux/bfs_fs.h>
#include <linux/adfs_fs.h>
+#include <linux/openprom_fs.h>
#include <linux/major.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
@@ -51,12 +52,12 @@ extern int init_coda(void);
extern int init_devpts_fs(void);
#endif
-void __init filesystem_setup(void)
-{
-#ifdef CONFIG_EXT2_FS
- init_ext2_fs();
+#ifdef CONFIG_SUN_OPENPROMFS
+extern int init_openprom_fs(void);
#endif
+void __init filesystem_setup(void)
+{
#ifdef CONFIG_MINIX_FS
init_minix_fs();
#endif
@@ -160,6 +161,10 @@ void __init filesystem_setup(void)
#ifdef CONFIG_BFS_FS
init_bfs_fs();
#endif
+
+#ifdef CONFIG_SUN_OPENPROMFS
+ init_openprom_fs();
+#endif
#ifdef CONFIG_NLS
init_nls();
diff --git a/fs/hfs/dir_cap.c b/fs/hfs/dir_cap.c
index 602d85c52..cdf01737a 100644
--- a/fs/hfs/dir_cap.c
+++ b/fs/hfs/dir_cap.c
@@ -70,8 +70,6 @@ static struct file_operations hfs_cap_dir_operations = {
NULL, /* no special release code */
file_fsync, /* fsync - default */
NULL, /* fasync - default */
- NULL, /* check_media_change - none */
- NULL /* revalidate - none */
};
struct inode_operations hfs_cap_ndir_inode_operations = {
diff --git a/fs/hfs/dir_dbl.c b/fs/hfs/dir_dbl.c
index bc32f23c1..1e13465d1 100644
--- a/fs/hfs/dir_dbl.c
+++ b/fs/hfs/dir_dbl.c
@@ -69,8 +69,6 @@ static struct file_operations hfs_dbl_dir_operations = {
NULL, /* no special release code */
file_fsync, /* fsync - default */
NULL, /* fasync - default */
- NULL, /* check_media_change - none */
- NULL /* revalidate - none */
};
struct inode_operations hfs_dbl_dir_inode_operations = {
diff --git a/fs/hfs/dir_nat.c b/fs/hfs/dir_nat.c
index 855d3434e..ab274d18f 100644
--- a/fs/hfs/dir_nat.c
+++ b/fs/hfs/dir_nat.c
@@ -75,8 +75,6 @@ static struct file_operations hfs_nat_dir_operations = {
NULL, /* no special release code */
file_fsync, /* fsync - default */
NULL, /* fasync - default */
- NULL, /* check_media_change - none */
- NULL, /* revalidate - none */
NULL /* lock - none */
};
diff --git a/fs/hfs/file.c b/fs/hfs/file.c
index ec1d5ada4..943249478 100644
--- a/fs/hfs/file.c
+++ b/fs/hfs/file.c
@@ -45,8 +45,6 @@ static struct file_operations hfs_file_operations = {
NULL, /* release */
file_fsync, /* fsync - default */
NULL, /* fasync - default */
- NULL, /* check_media_change - none */
- NULL, /* revalidate - none */
NULL /* lock - none */
};
diff --git a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c
index 23566021b..4e723af63 100644
--- a/fs/hfs/file_cap.c
+++ b/fs/hfs/file_cap.c
@@ -59,8 +59,6 @@ static struct file_operations hfs_cap_info_operations = {
NULL, /* no special release code */
file_fsync, /* fsync - default */
NULL, /* fasync - default */
- NULL, /* check_media_change - none */
- NULL, /* revalidate - none */
NULL /* lock - none */
};
diff --git a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c
index bb7d82e4f..efbe84f75 100644
--- a/fs/hfs/file_hdr.c
+++ b/fs/hfs/file_hdr.c
@@ -60,8 +60,6 @@ static struct file_operations hfs_hdr_operations = {
NULL, /* no special release code */
file_fsync, /* fsync - default */
NULL, /* fasync - default */
- NULL, /* check_media_change - none */
- NULL, /* revalidate - none */
NULL /* lock - none */
};
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index e4167bfdc..0b6ab8053 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -22,8 +22,6 @@ static const struct file_operations hpfs_file_ops =
hpfs_file_release, /* release */
hpfs_file_fsync, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL, /* lock */
};
@@ -63,8 +61,6 @@ static const struct file_operations hpfs_dir_ops =
hpfs_dir_release, /* no special release code */
hpfs_file_fsync, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL, /* lock */
};
diff --git a/fs/inode.c b/fs/inode.c
index 0dcdf2a87..4990b0497 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -257,7 +257,10 @@ void clear_inode(struct inode *inode)
DQUOT_DROP(inode);
if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)
inode->i_sb->s_op->clear_inode(inode);
-
+ if (inode->i_bdev) {
+ bdput(inode->i_bdev);
+ inode->i_bdev = NULL;
+ }
inode->i_state = 0;
}
@@ -392,7 +395,7 @@ void prune_icache(int goal)
dispose_list(freeable);
}
-int shrink_icache_memory(int priority, int gfp_mask)
+int shrink_icache_memory(int priority, int gfp_mask, zone_t *zone)
{
if (gfp_mask & __GFP_IO)
{
@@ -472,6 +475,7 @@ static void clean_inode(struct inode *inode)
inode->i_generation = 0;
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
inode->i_pipe = NULL;
+ inode->i_bdev = NULL;
}
/*
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 84aa2ec30..d14c18071 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -425,71 +425,54 @@ static int parse_options(char *options, struct iso9660_options * popt)
*/
#define WE_OBEY_THE_WRITTEN_STANDARDS 1
-static unsigned int isofs_get_last_session(kdev_t dev,s32 session )
+static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
{
- struct cdrom_multisession ms_info;
- unsigned int vol_desc_start;
- struct inode inode_fake;
- struct file_operations *fops;
- extern struct file_operations * get_blkfops(unsigned int);
- int i;
-
- vol_desc_start=0;
- fops = get_blkfops(MAJOR(dev));
- if (fops && fops->ioctl)
- {
- /* Whoops. We must save the old FS, since otherwise
- * we would destroy the kernels idea about FS on root
- * mount in read_super... [chexum]
- */
- mm_segment_t old_fs=get_fs();
- inode_fake.i_rdev=dev;
- init_waitqueue_head(&inode_fake.i_wait);
- ms_info.addr_format=CDROM_LBA;
- /* If a minor device was explicitly opened, set session to the
- * minor number. For instance, if /dev/hdc1 is mounted, session
- * 1 on the CD-ROM is selected. CD_PART_MAX gives access to
- * a max of 64 sessions on IDE. SCSI drives must still use
- * the session option to mount.
- */
- if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR))
+ struct cdrom_multisession ms_info;
+ unsigned int vol_desc_start;
+ struct block_device *bdev = sb->s_bdev;
+ kdev_t dev = sb->s_dev;
+ int i;
+
+ vol_desc_start=0;
+ ms_info.addr_format=CDROM_LBA;
+ /* If a minor device was explicitly opened, set session to the
+ * minor number. For instance, if /dev/hdc1 is mounted, session
+ * 1 on the CD-ROM is selected. CD_PART_MAX gives access to
+ * a max of 64 sessions on IDE. SCSI drives must still use
+ * the session option to mount.
+ */
+ if ((MINOR(dev) % CD_PART_MAX) && (MAJOR(dev) != SCSI_CDROM_MAJOR))
session = MINOR(dev) % CD_PART_MAX;
- set_fs(KERNEL_DS);
- if(session >= 0 && session <= 99) {
- struct cdrom_tocentry Te;
- Te.cdte_track=session;
- Te.cdte_format=CDROM_LBA;
- i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
- NULL,
- CDROMREADTOCENTRY,
- (unsigned long) &Te);
- set_fs(old_fs);
- if(!i) printk(KERN_ERR"Session %d start %d type %d\n",session,Te.cdte_addr.lba,Te.cdte_ctrl&CDROM_DATA_TRACK);
- if(i || (Te.cdte_ctrl&CDROM_DATA_TRACK) != 4)
- printk(KERN_ERR"Invalid session number or type of track\n");
- else return Te.cdte_addr.lba;
- }
- i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
- NULL,
- CDROMMULTISESSION,
- (unsigned long) &ms_info);
- set_fs(old_fs);
- if(session > 0) printk(KERN_ERR"Invalid session number\n");
+ if(session >= 0 && session <= 99) {
+ struct cdrom_tocentry Te;
+ Te.cdte_track=session;
+ Te.cdte_format=CDROM_LBA;
+ i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te);
+ if (!i) {
+ printk(KERN_DEBUG "Session %d start %d type %d\n",
+ session, Te.cdte_addr.lba,
+ Te.cdte_ctrl&CDROM_DATA_TRACK);
+ if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4)
+ return Te.cdte_addr.lba;
+ }
+
+ printk(KERN_ERR "Invalid session number or type of track\n");
+ }
+ i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
+ if(session > 0) printk(KERN_ERR "Invalid session number\n");
#if 0
- printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
- if (i==0)
- {
- printk("isofs.inode: XA disk: %s\n", ms_info.xa_flag ? "yes":"no");
- printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
+ printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
+ if (i==0) {
+ printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no");
+ printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba);
}
#endif
- if (i==0)
+ if (i==0)
#if WE_OBEY_THE_WRITTEN_STANDARDS
if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
#endif
- vol_desc_start=ms_info.addr.lba;
- }
- return vol_desc_start;
+ vol_desc_start=ms_info.addr.lba;
+ return vol_desc_start;
}
/*
@@ -569,7 +552,7 @@ static struct super_block *isofs_read_super(struct super_block *s, void *data,
s->u.isofs_sb.s_high_sierra = high_sierra = 0; /* default is iso9660 */
vol_desc_start = (opt.sbsector != -1) ?
- opt.sbsector : isofs_get_last_session(dev,opt.session);
+ opt.sbsector : isofs_get_last_session(s,opt.session);
for (iso_blknum = vol_desc_start+16;
iso_blknum < vol_desc_start+100; iso_blknum++)
@@ -927,7 +910,8 @@ static int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
int isofs_get_block(struct inode *inode, long iblock,
struct buffer_head *bh_result, int create)
{
- off_t b_off, offset, sect_size;
+ unsigned long b_off;
+ unsigned offset, sect_size;
unsigned int firstext;
unsigned long nextino;
int i, err;
@@ -942,30 +926,21 @@ int isofs_get_block(struct inode *inode, long iblock,
if (iblock < 0)
goto abort_negative;
- b_off = iblock << ISOFS_BUFFER_BITS(inode);
+ b_off = iblock;
- /* If we are beyond the end of this file, don't give out any
- * blocks.
+ /* If we are *way* beyond the end of the file, print a message.
+ * Access beyond the end of the file up to the next page boundary
+ * is normal, however because of the way the page cache works.
+ * In this case, we just return 0 so that we can properly fill
+ * the page with useless information without generating any
+ * I/O errors.
*/
- if (b_off > inode->i_size) {
- off_t max_legal_read_offset;
-
- /* If we are *way* beyond the end of the file, print a message.
- * Access beyond the end of the file up to the next page boundary
- * is normal, however because of the way the page cache works.
- * In this case, we just return 0 so that we can properly fill
- * the page with useless information without generating any
- * I/O errors.
- */
- max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1)
- & ~(PAGE_SIZE - 1);
- if (b_off >= max_legal_read_offset)
- goto abort_beyond_end;
- }
+ if (b_off > ((inode->i_size + PAGE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode)))
+ goto abort_beyond_end;
offset = 0;
firstext = inode->u.isofs_i.i_first_extent;
- sect_size = inode->u.isofs_i.i_section_size;
+ sect_size = inode->u.isofs_i.i_section_size >> ISOFS_BUFFER_BITS(inode);
nextino = inode->u.isofs_i.i_next_section_ino;
i = 0;
@@ -990,8 +965,7 @@ int isofs_get_block(struct inode *inode, long iblock,
}
bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr = firstext +
- ((b_off - offset) >> ISOFS_BUFFER_BITS(inode));
+ bh_result->b_blocknr = firstext + b_off - offset;
bh_result->b_state |= (1UL << BH_Mapped);
err = 0;
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 4240f622e..6445c225c 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -53,8 +53,6 @@ static struct file_operations minix_file_operations = {
NULL, /* release */
minix_sync_file, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
struct inode_operations minix_file_inode_operations = {
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 6cc9522fa..66582c216 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -177,6 +177,7 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
kdev_t dev = s->s_dev;
const char * errmsg;
struct inode *root_inode;
+ unsigned int hblock;
/* N.B. These should be compile-time tests.
Unfortunately that is impossible. */
@@ -186,6 +187,11 @@ static struct super_block *minix_read_super(struct super_block *s, void *data,
panic("bad V2 i-node size");
MOD_INC_USE_COUNT;
+
+ hblock = get_hardblocksize(dev);
+ if (hblock && hblock > BLOCK_SIZE)
+ goto out_bad_hblock;
+
lock_super(s);
set_blocksize(dev, BLOCK_SIZE);
if (!(bh = bread(dev,1,BLOCK_SIZE)))
@@ -322,11 +328,16 @@ out_no_fs:
brelse(bh);
goto out_unlock;
+out_bad_hblock:
+ printk("MINIX-fs: blocksize too small for device.\n");
+ goto out;
+
out_bad_sb:
printk("MINIX-fs: unable to read superblock\n");
out_unlock:
- s->s_dev = 0;
unlock_super(s);
+ out:
+ s->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
}
diff --git a/fs/namei.c b/fs/namei.c
index 95ee1c127..599c873e6 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -17,6 +17,7 @@
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
#include <linux/pagemap.h>
+#include <linux/dcache.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
@@ -550,83 +551,6 @@ static inline int may_create(struct inode *dir, struct dentry *child) {
return permission(dir,MAY_WRITE | MAY_EXEC);
}
-static inline struct dentry *get_parent(struct dentry *dentry)
-{
- return dget(dentry->d_parent);
-}
-
-static inline void unlock_dir(struct dentry *dir)
-{
- up(&dir->d_inode->i_sem);
- dput(dir);
-}
-
-/*
- * We need to do a check-parent every time
- * after we have locked the parent - to verify
- * that the parent is still our parent and
- * that we are still hashed onto it..
- *
- * This is requied in case two processes race
- * on removing (or moving) the same entry: the
- * parent lock will serialize them, but the
- * other process will be too late..
- */
-#define check_parent(dir, dentry) \
- ((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
-
-/*
- * Locking the parent is needed to:
- * - serialize directory operations
- * - make sure the parent doesn't change from
- * under us in the middle of an operation.
- *
- * NOTE! Right now we'd rather use a "struct inode"
- * for this, but as I expect things to move toward
- * using dentries instead for most things it is
- * probably better to start with the conceptually
- * better interface of relying on a path of dentries.
- */
-static inline struct dentry *lock_parent(struct dentry *dentry)
-{
- struct dentry *dir = dget(dentry->d_parent);
-
- down(&dir->d_inode->i_sem);
- return dir;
-}
-
-/*
- * Whee.. Deadlock country. Happily there are only two VFS
- * operations that do this..
- */
-static inline void double_lock(struct dentry *d1, struct dentry *d2)
-{
- struct semaphore *s1 = &d1->d_inode->i_sem;
- struct semaphore *s2 = &d2->d_inode->i_sem;
-
- if (s1 != s2) {
- if ((unsigned long) s1 < (unsigned long) s2) {
- struct semaphore *tmp = s2;
- s2 = s1; s1 = tmp;
- }
- down(s1);
- }
- down(s2);
-}
-
-static inline void double_unlock(struct dentry *d1, struct dentry *d2)
-{
- struct semaphore *s1 = &d1->d_inode->i_sem;
- struct semaphore *s2 = &d2->d_inode->i_sem;
-
- up(s1);
- if (s1 != s2)
- up(s2);
- dput(d1);
- dput(d2);
-}
-
-
/*
* Special case: O_CREAT|O_EXCL implies O_NOFOLLOW for security
* reasons.
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 00279fc6a..f687cfdab 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -53,8 +53,6 @@ static struct file_operations nfs_file_operations = {
nfs_release, /* release */
nfs_fsync, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
nfs_lock, /* lock */
};
diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c
index b087bd7f6..7de7eb5c4 100644
--- a/fs/ntfs/fs.c
+++ b/fs/ntfs/fs.c
@@ -421,8 +421,6 @@ static struct file_operations ntfs_file_operations_nommap = {
NULL, /* release */
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL, /* lock */
};
@@ -602,8 +600,6 @@ static struct file_operations ntfs_file_operations = {
NULL, /* release */
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL, /* lock */
};
@@ -633,17 +629,6 @@ static struct file_operations ntfs_dir_operations = {
NULL, /* read */
NULL, /* write */
ntfs_readdir, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* flush */
- NULL, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL, /* lock */
};
static struct inode_operations ntfs_dir_inode_operations = {
diff --git a/fs/open.c b/fs/open.c
index c5f571ce1..82260bd5d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -789,6 +789,9 @@ asmlinkage long sys_open(const char * filename, int flags, int mode)
char * tmp;
int fd, error;
+#if BITS_PER_LONG != 32
+ flags |= O_LARGEFILE;
+#endif
tmp = getname(filename);
fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
diff --git a/fs/openpromfs/.cvsignore b/fs/openpromfs/.cvsignore
new file mode 100644
index 000000000..857dd22e9
--- /dev/null
+++ b/fs/openpromfs/.cvsignore
@@ -0,0 +1,2 @@
+.depend
+.*.flags
diff --git a/fs/openpromfs/Makefile b/fs/openpromfs/Makefile
new file mode 100644
index 000000000..a97a5615d
--- /dev/null
+++ b/fs/openpromfs/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the Linux minix filesystem routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile.
+
+O_TARGET := openpromfs.o
+O_OBJS := inode.o
+M_OBJS := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff --git a/fs/proc/openpromfs.c b/fs/openpromfs/inode.c
index 55f290664..b09462b89 100644
--- a/fs/proc/openpromfs.c
+++ b/fs/openpromfs/inode.c
@@ -1,7 +1,7 @@
-/* $Id: openpromfs.c,v 1.36 1999/08/31 07:01:03 davem Exp $
+/* $Id: inode.c,v 1.3 2000/01/04 10:02:29 jj Exp $
* openpromfs.c: /proc/openprom handling routines
*
- * Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
*/
@@ -9,8 +9,10 @@
#include <linux/types.h>
#include <linux/string.h>
#include <linux/fs.h>
-#include <linux/proc_fs.h>
+#include <linux/openprom_fs.h>
+#include <linux/locks.h>
#include <linux/init.h>
+#include <linux/malloc.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
@@ -50,11 +52,12 @@ static u16 options = 0xffff;
static u16 aliases = 0xffff;
static int aliases_nodes = 0;
static char *alias_names [ALIASES_NNODES];
-extern struct openpromfs_dev *openprom_devices;
-#define NODE(ino) nodes[ino - PROC_OPENPROM_FIRST]
-#define NODE2INO(node) (node + PROC_OPENPROM_FIRST)
-#define NODEP2INO(no) (no + PROC_OPENPROM_FIRST + last_node)
+#define OPENPROM_ROOT_INO 16
+#define OPENPROM_FIRST_INO OPENPROM_ROOT_INO
+#define NODE(ino) nodes[ino - OPENPROM_FIRST_INO]
+#define NODE2INO(node) (node + OPENPROM_FIRST_INO)
+#define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
static int openpromfs_create (struct inode *, struct dentry *, int);
static int openpromfs_readdir(struct file *, void *, filldir_t);
@@ -527,7 +530,7 @@ int property_release (struct inode *inode, struct file *filp)
op->value, op->len + 1);
restore_flags (flags);
if (error <= 0)
- printk (KERN_WARNING "/proc/openprom: "
+ printk (KERN_WARNING "openpromfs: "
"Couldn't write property %s\n",
op->name);
} else if ((op->flag & OPP_BINARY) || !op->len) {
@@ -536,11 +539,11 @@ int property_release (struct inode *inode, struct file *filp)
op->value, op->len);
restore_flags (flags);
if (error <= 0)
- printk (KERN_WARNING "/proc/openprom: "
+ printk (KERN_WARNING "openpromfs: "
"Couldn't write property %s\n",
op->name);
} else {
- printk (KERN_WARNING "/proc/openprom: "
+ printk (KERN_WARNING "openpromfs: "
"Unknown property type of %s\n",
op->name);
}
@@ -661,7 +664,6 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
#define OPFSL_DIR 0
#define OPFSL_PROPERTY 1
#define OPFSL_NODENUM 2
-#define OPFSL_DEVICE 3
int type = 0;
char buffer[128];
char *p;
@@ -671,7 +673,6 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
unsigned int len;
int i;
struct inode *inode;
- struct openpromfs_dev *d = NULL;
char buffer2[64];
inode = NULL;
@@ -703,7 +704,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
}
}
n = NODE(dir->i_ino).node;
- dirnode = dir->i_ino - PROC_OPENPROM_FIRST;
+ dirnode = dir->i_ino - OPENPROM_FIRST_INO;
if (!ino) {
int j = NODEP2INO(NODE(dir->i_ino).first_prop);
if (dirnode != aliases) {
@@ -733,28 +734,19 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
}
}
if (!ino) {
- for (d = openprom_devices; d; d = d->next)
- if ((d->node == n) && (strlen (d->name) == len)
- && !strncmp (d->name, name, len)) {
- ino = d->inode;
- type = OPFSL_DEVICE;
- break;
- }
- }
- if (!ino) {
ino = lookup_children (NODE(dir->i_ino).child, name, len);
if (ino)
type = OPFSL_DIR;
else
return ERR_PTR(-ENOENT);
}
- inode = iget (dir->i_sb, ino, 0);
+ inode = iget (dir->i_sb, ino);
if (!inode)
return ERR_PTR(-EINVAL);
switch (type) {
case OPFSL_DIR:
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
- if (ino == PROC_OPENPROM_FIRST + aliases) {
+ if (ino == OPENPROM_FIRST_INO + aliases) {
inode->i_mode |= S_IWUSR;
inode->i_op = &openprom_alias_inode_operations;
} else
@@ -785,9 +777,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
inode->u.generic_ip = (void *)(long)(((u16)dirnode) |
(((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));
break;
- case OPFSL_DEVICE:
- init_special_inode(d->mode, kdev_to_nr(d->rdev));
- }
+ }
inode->i_gid = 0;
inode->i_uid = 0;
@@ -805,7 +795,6 @@ static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filld
char buffer[128];
u16 node;
char *p;
- struct openpromfs_dev *d;
char buffer2[64];
ino = inode->i_ino;
@@ -819,7 +808,7 @@ static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filld
case 1:
if (filldir(dirent, "..", 2, i,
(NODE(ino).parent == 0xffff) ?
- PROC_ROOT_INO : NODE2INO(NODE(ino).parent)) < 0)
+ OPENPROM_ROOT_INO : NODE2INO(NODE(ino).parent)) < 0)
return 0;
i++;
filp->f_pos++;
@@ -848,7 +837,7 @@ static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filld
} else
i--;
n = NODE(ino).node;
- if (ino == PROC_OPENPROM_FIRST + aliases) {
+ if (ino == OPENPROM_FIRST_INO + aliases) {
for (j++; i < aliases_nodes; i++, j++) {
if (alias_names [i]) {
if (filldir (dirent, alias_names [i],
@@ -871,18 +860,6 @@ static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filld
}
}
}
- for (d = openprom_devices; d; d = d->next) {
- if (d->node == n) {
- if (i) i--;
- else {
- if (filldir(dirent, d->name,
- strlen(d->name),
- filp->f_pos, d->inode) < 0)
- return 0;
- filp->f_pos++;
- }
- }
- }
}
return 0;
}
@@ -1041,31 +1018,6 @@ static u16 get_nodes (u16 parent, u32 node)
}
-#ifdef MODULE
-void openpromfs_use (struct inode *inode, int inc)
-{
- static int root_fresh = 1;
- static int dec_first = 1;
- if (inc) {
- if (inode->i_count == 1)
- MOD_INC_USE_COUNT;
- else if (root_fresh && inode->i_ino == PROC_OPENPROM_FIRST) {
- root_fresh = 0;
- MOD_INC_USE_COUNT;
- }
- } else {
- if (inode->i_ino == PROC_OPENPROM_FIRST)
- root_fresh = 0;
- if (!dec_first)
- MOD_DEC_USE_COUNT;
- }
- dec_first = 0;
-}
-
-#else
-#define openpromfs_use 0
-#endif
-
static struct file_operations openprom_operations = {
NULL, /* lseek - default */
NULL, /* read - bad */
@@ -1082,8 +1034,9 @@ static struct inode_operations openprom_inode_operations = {
static void openprom_read_inode(struct inode * inode)
{
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- if (inode->i_ino == PROC_OPENPROM) {
+ if (inode->i_ino == OPENPROM_ROOT_INO) {
inode->i_op = &openprom_inode_operations;
+ inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
}
}
@@ -1096,7 +1049,7 @@ static int openprom_statfs(struct super_block *sb, struct statfs *buf, int bufsi
{
struct statfs tmp;
- tmp.f_type = PROC_SUPER_MAGIC; /* FIXME */
+ tmp.f_type = OPENPROM_SUPER_MAGIC;
tmp.f_bsize = PAGE_SIZE/sizeof(long); /* ??? */
tmp.f_blocks = 0;
tmp.f_bfree = 0;
@@ -1128,9 +1081,9 @@ struct super_block *openprom_read_super(struct super_block *s,void *data,
lock_super(s);
s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
- s->s_magic = PROC_SUPER_MAGIC; /* FIXME */
+ s->s_magic = OPENPROM_SUPER_MAGIC;
s->s_op = &openprom_sops;
- root_inode = iget(s, PROC_OPENPROM);
+ root_inode = iget(s, OPENPROM_ROOT_INO);
if (!root_inode)
goto out_no_root;
s->s_root = d_alloc_root(root_inode);
@@ -1140,29 +1093,30 @@ struct super_block *openprom_read_super(struct super_block *s,void *data,
return s;
out_no_root:
- printk("proc_read_super: get root inode failed\n");
+ printk("openprom_read_super: get root inode failed\n");
iput(root_inode);
s->s_dev = 0;
unlock_super(s);
+ MOD_DEC_USE_COUNT;
return NULL;
}
static struct file_system_type openprom_fs_type = {
- "openprom",
+ "openpromfs",
0,
- openprom_read_super,
+ openprom_read_super,
NULL
};
-static int init_openprom_fs(void)
+int init_openprom_fs(void)
{
nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
if (!nodes) {
- printk (KERN_WARNING "/proc/openprom: can't get free page\n");
+ printk (KERN_WARNING "openpromfs: can't get free page\n");
return -EIO;
}
if (get_nodes (0xffff, prom_root_node) == 0xffff) {
- printk (KERN_WARNING "/proc/openprom: couldn't setup tree\n");
+ printk (KERN_WARNING "openpromfs: couldn't setup tree\n");
return -EIO;
}
nodes[last_node].first_prop = first_prop;
diff --git a/fs/partitions/Config.in b/fs/partitions/Config.in
index de35b3d57..869dcb76d 100644
--- a/fs/partitions/Config.in
+++ b/fs/partitions/Config.in
@@ -3,64 +3,62 @@
#
bool 'Advanced partition selection' CONFIG_PARTITION_ADVANCED
if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
- bool 'Alpha OSF partition support' CONFIG_OSF_PARTITION
- bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
- bool 'PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
+ bool ' Acorn partition support' CONFIG_ACORN_PARTITION
+ if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
+# bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
+ bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS
+ bool ' Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
+ bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
+ bool ' RISCiX partition support' CONFIG_ACORN_PARTITION_RISCIX
+ fi
+ bool ' Alpha OSF partition support' CONFIG_OSF_PARTITION
+ bool ' Amiga partition table support' CONFIG_AMIGA_PARTITION
+ bool ' Atari partition table support' CONFIG_ATARI_PARTITION
+ bool ' Macintosh partition map support' CONFIG_MAC_PARTITION
+ bool ' PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
+ if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
+ bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
+ bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
+ bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
+ fi
else
- if [ "$ARCH" = "alpha" ]; then
- define_bool CONFIG_OSF_PARTITION y
- fi
- if [ "$ARCH" = "ppc" -o "$CONFIG_MAC" = "y" ]; then
- define_bool CONFIG_MAC_PARTITION y
- fi
- if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
- "$CONFIG_MAC" != "y" ]; then
- define_bool CONFIG_MSDOS_PARTITION y
- fi
+ if [ "$ARCH" = "alpha" ]; then
+ define_bool CONFIG_OSF_PARTITION y
+ fi
+ if [ "$ARCH" = "ppc" -o "$CONFIG_MAC" = "y" ]; then
+ define_bool CONFIG_MAC_PARTITION y
+ fi
+ if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
+ "$CONFIG_MAC" != "y" ]; then
+ define_bool CONFIG_MSDOS_PARTITION y
+ fi
+ if [ "$CONFIG_AMIGA" = "y" ]; then
+ define_bool CONFIG_AMIGA_PARTITION y
+ fi
+ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+ define_bool CONFIG_ACORN_PARTITION y
+ define_bool CONFIG_ACORN_PARTITION_ADFS y
+# define_bool CONFIG_ACORN_PARTITION_CUMANA y
+ define_bool CONFIG_ACORN_PARTITION_ICS y
+ define_bool CONFIG_ACORN_PARTITION_POWERTEC y
+ define_bool CONFIG_ACORN_PARTITION_RISCIX y
+ fi
+ if [ "$CONFIG_ATARI" = "y" ]; then
+ define_bool CONFIG_ATARI_PARTITION y
+ fi
fi
-if [ "$CONFIG_PARTITION_ADVANCED" = "y" -a \
- "$CONFIG_MSDOS_PARTITION" = "y" ]; then
- bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
- bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
- bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
-fi
-if [ "$CONFIG_SGI_IP22" != "y" ]; then
- bool 'SGI partition support' CONFIG_SGI_PARTITION
+if [ "$CONFIG_SGI_IP22" != "y" -a "$CONFIG_SGI_IP27" != "y" ]; then
+ bool 'SGI partition support' CONFIG_SGI_PARTITION
else
- define_bool CONFIG_SGI_PARTITION y
-fi
-if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
- bool 'Ultrix partition table support' CONFIG_ULTRIX_PARTITION
+ define_bool CONFIG_SGI_PARTITION y
fi
-if [ "$ARCH" != "sparc" -a "$ARCH" != "sparc64" ]; then
- bool 'Sun partition tables support' CONFIG_SUN_PARTITION
+if [ "$CONFIG_DECSTATION" != "y" ]; then
+ bool 'Ultrix partition table support' CONFIG_ULTRIX_PARTITION
else
- define_bool CONFIG_SUN_PARTITION y
+ define_bool CONFIG_ULTRIX_PARTITION y
fi
-if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
- bool 'Amiga partition table support' CONFIG_AMIGA_PARTITION
- bool 'Atari partition table support' CONFIG_ATARI_PARTITION
- bool 'Acorn partition support' CONFIG_ACORN_PARTITION
- if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
- bool ' Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
-# bool ' Cumana partition support' CONFIG_ACORN_PARTITION_CUMANA
- bool ' ICS partition support' CONFIG_ACORN_PARTITION_ICS
- bool ' PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
- bool ' RISCiX partition support' CONFIG_ACORN_PARTITION_RISCIX
- fi
+if [ "$ARCH" != "sparc" -a "$ARCH" != "sparc64" ]; then
+ bool 'Sun partition tables support' CONFIG_SUN_PARTITION
else
- if [ "$CONFIG_AMIGA" = "y" ]; then
- define_bool CONFIG_AMIGA_PARTITION y
- fi
- if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
- define_bool CONFIG_ACORN_PARTITION y
- define_bool CONFIG_ACORN_PARTITION_ADFS y
-# define_bool CONFIG_ACORN_PARTITION_CUMANA y
- define_bool CONFIG_ACORN_PARTITION_ICS y
- define_bool CONFIG_ACORN_PARTITION_POWERTEC y
- define_bool CONFIG_ACORN_PARTITION_RISCIX y
- fi
-fi
-if [ "$CONFIG_ATARI" = "y" ]; then
- define_bool CONFIG_ATARI_PARTITION y
+ define_bool CONFIG_SUN_PARTITION y
fi
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index e8bb4774f..fade4acf2 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -16,16 +16,6 @@ endif
OX_OBJS := procfs_syms.o
M_OBJS :=
-ifeq ($(CONFIG_SUN_OPENPROMFS),y)
-O_OBJS += openpromfs.o
-OX_OBJS := openprom-dev.o
-else
- ifeq ($(CONFIG_SUN_OPENPROMFS),m)
- M_OBJS += openpromfs.o
- OX_OBJS := openprom-dev.o
- endif
-endif
-
ifeq ($(CONFIG_PROC_DEVICETREE),y)
O_OBJS += proc_devtree.o
endif
diff --git a/fs/proc/base.c b/fs/proc/base.c
index eac10cbd4..1dd50817c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -513,7 +513,7 @@ static struct pid_entry base_stuff[] = {
E(PROC_PID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
E(PROC_PID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_PID_STATM, "statm", S_IFREG|S_IRUGO),
-#ifdef SMP
+#ifdef __SMP__
E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO),
#endif
#if CONFIG_AP1000
@@ -643,7 +643,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
* grab the reference to task.
*/
inode->u.proc_i.task = task;
- atomic_inc(&mem_map[MAP_NR(task)].count);
+ get_task_struct(task);
if (!task->p_pptr)
goto out_unlock;
@@ -865,7 +865,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
case PROC_PID_MAPS:
inode->i_op = &proc_maps_inode_operations;
break;
-#ifdef SMP
+#ifdef __SMP__
case PROC_PID_CPU:
inode->i_op = &proc_info_inode_operations;
inode->u.proc_i.op.proc_read = proc_pid_cpu;
@@ -932,7 +932,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
read_lock(&tasklist_lock);
task = find_task_by_pid(pid);
if (task)
- atomic_inc(&mem_map[MAP_NR(task)].count);
+ get_task_struct(task);
read_unlock(&tasklist_lock);
if (!task)
goto out;
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 28635ff14..f63bcac6e 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -119,7 +119,7 @@ struct memelfnote
extern char saved_command_line[];
-static size_t get_kcore_size(int *num_vma, int *elf_buflen)
+static size_t get_kcore_size(int *num_vma, size_t *elf_buflen)
{
size_t try, size = 0;
struct vm_struct *m;
diff --git a/fs/proc/omirr.c b/fs/proc/omirr.c
index f205dd753..bdbcb0cbf 100644
--- a/fs/proc/omirr.c
+++ b/fs/proc/omirr.c
@@ -272,8 +272,6 @@ static struct file_operations omirr_operations = {
omirr_release,
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
struct inode_operations proc_omirr_inode_operations = {
diff --git a/fs/proc/openprom-dev.c b/fs/proc/openprom-dev.c
deleted file mode 100644
index 79ef8d549..000000000
--- a/fs/proc/openprom-dev.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/fs/proc/openprom-dev.c
- *
- * handling of devices attached to openpromfs.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-struct openpromfs_dev *openprom_devices = NULL;
-static ino_t openpromdev_ino = PROC_OPENPROMD_FIRST;
-
-int proc_openprom_regdev(struct openpromfs_dev *d)
-{
- if (openpromdev_ino == PROC_OPENPROMD_FIRST + PROC_NOPENPROMD)
- return -1;
- d->next = openprom_devices;
- d->inode = openpromdev_ino++;
- openprom_devices = d;
- return 0;
-}
-
-int proc_openprom_unregdev(struct openpromfs_dev *d)
-{
- if (d == openprom_devices) {
- openprom_devices = d->next;
- } else if (!openprom_devices)
- return -1;
- else {
- struct openpromfs_dev *p;
-
- for (p = openprom_devices; p->next != d && p->next; p = p->next);
- if (!p->next) return -1;
- p->next = d->next;
- }
- return 0;
-}
-
-#if defined(CONFIG_SUN_OPENPROMFS_MODULE)
-EXPORT_SYMBOL(openprom_devices);
-#endif
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 83a0d7619..75780167a 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -73,9 +73,6 @@ void __init proc_root_init(void)
proc_root_fs = proc_mkdir("fs", 0);
proc_root_driver = proc_mkdir("driver", 0);
#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
-#ifdef CONFIG_SUN_OPENPROMFS
- openpromfs_init ();
-#endif
/* just give it a mountpoint */
proc_mkdir("openprom", 0);
#endif
diff --git a/fs/qnx4/BUGS b/fs/qnx4/BUGS
index 64d81b4bb..e81ef78d5 100644
--- a/fs/qnx4/BUGS
+++ b/fs/qnx4/BUGS
@@ -1,4 +1,13 @@
-Last update: 03-07-1998
+Last update: 1999-12-23
+
+- Fragmented files and directories were incorrectly handled.
+ Fixed 1999-12-23, Anders.
+
+- readdir sometimes returned the same dir entry more than once.
+ Fixed 1999-12-13, Anders.
+
+- File names with a length of exactly 16 chars were handled incorrectly.
+ Fixed 1999-12-11, Anders.
- Files in a subdir can't be accessed, I think that the inode information
is not correctly copied at some point. Solved 06-06-1998, Richard.
diff --git a/fs/qnx4/README b/fs/qnx4/README
index e7300730b..55cc90bae 100644
--- a/fs/qnx4/README
+++ b/fs/qnx4/README
@@ -1,9 +1,9 @@
This is a snapshot of the QNX4 filesystem for Linux.
- Please send diffs and remarks to <qnxfs@rtc-one.net> .
+ Please send diffs and remarks to <al@alarsen.net> .
Credits :
Richard "Scuba" A. Frowijn <scuba@wxs.nl>
Frank "Jedi/Sector One" Denis <j@4u.net>
-
+Anders Larsen <al@alarsen.net>
diff --git a/fs/qnx4/TODO b/fs/qnx4/TODO
index fab3623f8..bb29a8aae 100644
--- a/fs/qnx4/TODO
+++ b/fs/qnx4/TODO
@@ -1,5 +1,8 @@
Name : QNX4 TODO list
-Last update: 29-06-1998
+Last update: 1999-12-23
+
+ - Writing is still unsupported (it may compile, but it certainly won't
+ bring you any joy).
- qnx4_checkroot (inode.c), currently there's a look for the '/' in
the root direntry, if so then the current mounted device is a qnx4
@@ -12,10 +15,6 @@ Last update: 29-06-1998
- Bitmap functions. To find out the free space, largest free block, etc.
Partly done (RO), Richard, 05/06/1998. Optimized 20-06-1998, Frank.
- - Symbolic links. symlinks.c have to be rewritten.
-
- - Extended files.
-
- Complete write, unlink and truncate functions : the bitmap should be
updated.
diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c
index b73f36deb..c399f85a8 100644
--- a/fs/qnx4/bitmap.c
+++ b/fs/qnx4/bitmap.c
@@ -1,12 +1,12 @@
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 28-05-1998 by Richard Frowijn : first release.
* 20-06-1998 by Frank Denis : basic optimisations.
* 25-06-1998 by Frank Denis : qnx4_is_free, qnx4_set_bitmap, qnx4_bmap .
@@ -86,7 +86,7 @@ unsigned long qnx4_count_free_inodes(struct super_block *sb)
return qnx4_count_free_blocks(sb) * QNX4_INODES_PER_BLOCK; /* FIXME */
}
-int qnx4_is_free(struct super_block *sb, int block)
+int qnx4_is_free(struct super_block *sb, long block)
{
int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
int size = sb->u.qnx4_sb.BitMap->di_size;
@@ -115,18 +115,9 @@ int qnx4_is_free(struct super_block *sb, int block)
return ret;
}
-int qnx4_bmap(struct inode *inode, int block)
-{
- QNX4DEBUG(("qnx4: bmap on block [%d]\n", block));
- if (block < 0) {
- return 0;
- }
- return !qnx4_is_free(inode->i_sb, block);
-}
-
#ifdef CONFIG_QNX4FS_RW
-int qnx4_set_bitmap(struct super_block *sb, int block, int busy)
+int qnx4_set_bitmap(struct super_block *sb, long block, int busy)
{
int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
int size = sb->u.qnx4_sb.BitMap->di_size;
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 810c3accd..831219999 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -1,12 +1,12 @@
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 28-05-1998 by Richard Frowijn : first release.
* 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
*/
@@ -20,55 +20,60 @@
#include <asm/segment.h>
-static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir);
-
static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct inode *inode = filp->f_dentry->d_inode;
unsigned int offset;
struct buffer_head *bh;
struct qnx4_inode_entry *de;
- long blknum;
- int i;
+ struct qnx4_link_info *le;
+ unsigned long blknum;
+ int ix, ino;
int size;
- blknum = inode->u.qnx4_i.i_first_xtnt.xtnt_blk - 1 +
- ((filp->f_pos >> 6) >> 3);
-
QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos));
- QNX4DEBUG(("BlkNum = %ld\n", (long) blknum));
while (filp->f_pos < inode->i_size) {
+ blknum = qnx4_block_map( inode, filp->f_pos / QNX4_BLOCK_SIZE );
bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
if(bh==NULL)
{
printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
break;
}
- i = (filp->f_pos - (((filp->f_pos >> 6) >> 3) << 9)) & 0x3f;
- while (i < QNX4_INODES_PER_BLOCK) {
- offset = i * QNX4_DIR_ENTRY_SIZE;
+ ix = (filp->f_pos / QNX4_DIR_ENTRY_SIZE - (filp->f_pos / QNX4_BLOCK_SIZE) * QNX4_INODES_PER_BLOCK) % QNX4_INODES_PER_BLOCK;
+ while (ix < QNX4_INODES_PER_BLOCK) {
+ offset = ix * QNX4_DIR_ENTRY_SIZE;
de = (struct qnx4_inode_entry *) (bh->b_data + offset);
size = strlen(de->di_fname);
if (size) {
+ if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX )
+ size = QNX4_SHORT_NAME_MAX;
+ else if ( size > QNX4_NAME_MAX )
+ size = QNX4_NAME_MAX;
- QNX4DEBUG(("qnx4_readdir:%s\n", de->di_fname));
-
- if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
- if (de->di_status) {
- if (filldir(dirent, de->di_fname, size, filp->f_pos, de->di_first_xtnt.xtnt_blk) < 0) {
- brelse(bh);
- return 0;
- }
+ if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) {
+ QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname));
+ if ( ( de->di_status & QNX4_FILE_LINK ) == 0 )
+ ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
+ else
+ {
+ le = (struct qnx4_link_info*)de;
+ ino = ( le->dl_inode_blk - 1 ) *
+ QNX4_INODES_PER_BLOCK +
+ le->dl_inode_ndx;
+ }
+ if (filldir(dirent, de->di_fname, size, filp->f_pos, ino) < 0) {
+ brelse(bh);
+ return 0;
}
}
}
- i++;
+ ix++;
filp->f_pos += QNX4_DIR_ENTRY_SIZE;
}
brelse(bh);
- blknum++;
}
UPDATE_ATIME(inode);
@@ -77,52 +82,19 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
static struct file_operations qnx4_dir_operations =
{
- NULL, /* lseek - default */
- NULL, /* read */
- NULL, /* write - bad */
- qnx4_readdir, /* readdir */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* no special flush code */
- NULL, /* no special release code */
- file_fsync, /* default fsync */
- NULL, /* default fasync */
- NULL, /* default check_media_change */
- NULL, /* default revalidate */
+ readdir: qnx4_readdir,
+ fsync: file_fsync,
};
struct inode_operations qnx4_dir_inode_operations =
{
- &qnx4_dir_operations,
-#ifdef CONFIG_QNX4FS_RW
- qnx4_create,
-#else
- NULL, /* create */
-#endif
- qnx4_lookup,
- NULL, /* link */
+ default_file_ops: &qnx4_dir_operations,
#ifdef CONFIG_QNX4FS_RW
- qnx4_unlink, /* unlink */
-#else
- NULL,
+ create: qnx4_create,
#endif
- NULL, /* symlink */
- NULL, /* mkdir */
+ lookup: qnx4_lookup,
#ifdef CONFIG_QNX4FS_RW
- qnx4_rmdir, /* rmdir */
-#else
- NULL,
+ unlink: qnx4_unlink,
+ rmdir: qnx4_rmdir,
#endif
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
};
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 49ea90921..80ab1f590 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -1,12 +1,12 @@
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 25-05-1998 by Richard Frowijn : first release.
* 21-06-1998 by Frank Denis : wrote qnx4_readpage to use generic_file_read.
* 27-06-1998 by Frank Denis : file overwriting.
@@ -34,8 +34,6 @@
#define MAX(a,b) (((a)>(b))?(a):(b))
-static int qnx4_readpage(struct dentry *dentry, struct page *page);
-
#ifdef CONFIG_QNX4FS_RW
static ssize_t qnx4_file_write(struct file *filp, const char *buf,
size_t count, loff_t * ppos)
@@ -124,7 +122,7 @@ static ssize_t qnx4_file_write(struct file *filp, const char *buf,
}
break;
}
- update_vm_cache(inode, pos, p, c);
+// update_vm_cache(inode, pos, p, c);
mark_buffer_uptodate(bh, 1);
mark_buffer_dirty(bh, 0);
brelse(bh);
@@ -145,112 +143,28 @@ static ssize_t qnx4_file_write(struct file *filp, const char *buf,
#endif
/*
- * We have moostly NULL's here: the current defaults are ok for
+ * We have mostly NULL's here: the current defaults are ok for
* the qnx4 filesystem.
*/
static struct file_operations qnx4_file_operations =
{
- NULL, /* lseek - default */
- generic_file_read, /* read */
+ read: generic_file_read,
#ifdef CONFIG_QNX4FS_RW
- qnx4_file_write, /* write */
-#else
- NULL,
+ write: qnx4_file_write,
#endif
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- generic_file_mmap, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* no special flush code */
- NULL, /* release */
-#ifdef CONFIG_QNX4FS_RW
- qnx4_sync_file, /* fsync */
-#else
- NULL,
+ mmap: generic_file_mmap,
+#ifdef CONFIG_QNX4FS_RW
+ fsync: qnx4_sync_file,
#endif
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
};
struct inode_operations qnx4_file_inode_operations =
{
- &qnx4_file_operations, /* default file operations */
- NULL, /* create? It's not a directory */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- qnx4_bmap, /* get_block */
- qnx4_readpage, /* readpage */
- NULL, /* writepage */
+ default_file_ops: &qnx4_file_operations,
+ get_block: qnx4_get_block,
+ readpage: block_read_full_page,
#ifdef CONFIG_QNX4FS_RW
- qnx4_truncate, /* truncate */
-#else
- NULL,
+ writepage: block_write_full_page,
+ truncate: qnx4_truncate,
#endif
- NULL, /* permission */
- NULL /* revalidate */
};
-
-static int qnx4_readpage(struct dentry *dentry, struct page *page)
-{
- struct inode *inode = dentry->d_inode;
- struct qnx4_inode_info *qnx4_ino = &inode->u.qnx4_i;
- unsigned long buf;
- unsigned long offset, avail, readlen;
- unsigned long start;
- unsigned long count;
- struct buffer_head *bh;
- int res = -EIO;
-
- QNX4DEBUG(("qnx4: readpage index=[%ld]\n", (long) page->index));
-
- if (qnx4_ino->i_xblk != 0) {
- printk("qnx4: sorry, this file is extended, don't know how to handle it (yet) !\n");
- return -EIO;
- }
- atomic_inc(&page->count);
- buf = page_address(page);
- clear_bit(PG_uptodate, &page->flags);
- clear_bit(PG_error, &page->flags);
- offset = page->index<<PAGE_SHIFT;
-
- if (offset < inode->i_size) {
- res = 0;
- avail = inode->i_size - offset;
- readlen = MIN(avail, PAGE_SIZE);
- start = qnx4_ino->i_first_xtnt.xtnt_blk + (offset >> 9) - 1;
- count = PAGE_SIZE / QNX4_BLOCK_SIZE;
- do {
- QNX4DEBUG(("qnx4: reading page starting at [%ld]\n", (long) start));
- if ((bh = bread(inode->i_dev, start, QNX4_BLOCK_SIZE)) == NULL) {
- printk("qnx4: data corrupted or I/O error.\n");
- res = -EIO;
- } else {
- memcpy((void *) buf, bh->b_data, QNX4_BLOCK_SIZE);
- }
- buf += QNX4_BLOCK_SIZE;
- start++;
- count--;
- } while (count != 0);
- }
- if (res != 0) {
- set_bit(PG_error, &page->flags);
- memset((void *) buf, 0, PAGE_SIZE);
- } else {
- set_bit(PG_uptodate, &page->flags);
- }
- Unlock_Page(page);
-/* free_page(buf); */
-
- return res;
-}
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index e75c4d93e..f77e4e2a5 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -1,12 +1,12 @@
-/*
+/*
* QNX4 file system, Linux implementation.
- *
- * Version : 0.1
- *
+ *
+ * Version : 0.2.1
+ *
* Using parts of the xiafs filesystem.
- *
+ *
* History :
- *
+ *
* 01-06-1998 by Richard Frowijn : first release.
* 20-06-1998 by Frank Denis : Linux 2.1.99+ support, boot signature, misc.
* 30-06-1998 by Frank Denis : first step to write inodes.
@@ -49,7 +49,7 @@ int qnx4_sync_inode(struct inode *inode)
kdevname(inode->i_dev), inode->i_ino);
err = -1;
}
- brelse (bh);
+ brelse (bh);
} else if (!bh) {
err = -1;
}
@@ -120,28 +120,17 @@ static int qnx4_statfs(struct super_block *, struct statfs *, int);
static struct super_operations qnx4_sops =
{
- qnx4_read_inode,
-#ifdef CONFIG_QNX4FS_RW
- qnx4_write_inode,
-#else
- NULL,
-#endif
- NULL, /* put_inode */
+ read_inode: qnx4_read_inode,
#ifdef CONFIG_QNX4FS_RW
- qnx4_delete_inode,
-#else
- NULL, /* delete_inode */
+ write_inode: qnx4_write_inode,
+ delete_inode: qnx4_delete_inode,
#endif
- NULL, /* notify_change */
- qnx4_put_super,
+ put_super: qnx4_put_super,
#ifdef CONFIG_QNX4FS_RW
- qnx4_write_super,
-#else
- NULL,
+ write_super: qnx4_write_super,
#endif
- qnx4_statfs,
- qnx4_remount,
- NULL /* clear_inode */
+ statfs: qnx4_statfs,
+ remount_fs: qnx4_remount,
};
static int qnx4_remount(struct super_block *sb, int *flags, char *data)
@@ -215,6 +204,89 @@ struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
return NULL;
}
+int qnx4_get_block( struct inode *inode, long iblock, struct buffer_head *bh, int create )
+{
+ unsigned long phys;
+
+ QNX4DEBUG(("qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock));
+
+ phys = qnx4_block_map( inode, iblock );
+ if ( phys )
+ {
+ // logical block is before EOF
+ bh->b_dev = inode->i_dev;
+ bh->b_blocknr = phys;
+ bh->b_state |= (1UL << BH_Mapped);
+ }
+ else if ( create )
+ {
+ // to be done.
+ }
+ return 0;
+}
+
+unsigned long qnx4_block_map( struct inode *inode, long iblock )
+{
+ int ix;
+ long offset, i_xblk;
+ unsigned long block = 0;
+ struct buffer_head *bh = 0;
+ struct qnx4_xblk *xblk = 0;
+ struct qnx4_inode_info *qnx4_inode = &inode->u.qnx4_i;
+ qnx4_nxtnt_t nxtnt = qnx4_inode->i_num_xtnts;
+
+ if ( iblock < qnx4_inode->i_first_xtnt.xtnt_size )
+ {
+ // iblock is in the first extent. This is easy.
+ block = qnx4_inode->i_first_xtnt.xtnt_blk + iblock - 1;
+ }
+ else
+ {
+ // iblock is beyond first extent. We have to follow the extent chain.
+ i_xblk = qnx4_inode->i_xblk;
+ offset = iblock - qnx4_inode->i_first_xtnt.xtnt_size;
+ ix = 0;
+ while ( --nxtnt > 0 )
+ {
+ if ( ix == 0 )
+ {
+ // read next xtnt block.
+ bh = bread( inode->i_dev, i_xblk - 1, QNX4_BLOCK_SIZE );
+ if ( !bh )
+ {
+ QNX4DEBUG(("qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));
+ return -EIO;
+ }
+ xblk = (struct qnx4_xblk*)bh->b_data;
+ if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) )
+ {
+ QNX4DEBUG(("qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));
+ break;
+ }
+ }
+ if ( offset < xblk->xblk_xtnts[ix].xtnt_size )
+ {
+ // got it!
+ block = xblk->xblk_xtnts[ix].xtnt_blk + offset - 1;
+ break;
+ }
+ offset -= xblk->xblk_xtnts[ix].xtnt_size;
+ if ( ++ix > QNX4_MAX_XTNTS_PER_XBLK )
+ {
+ i_xblk = xblk->xblk_next_xblk;
+ ix = 0;
+ brelse( bh );
+ bh = 0;
+ }
+ }
+ if ( bh )
+ brelse( bh );
+ }
+
+ QNX4DEBUG(("qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block));
+ return block;
+}
+
static int qnx4_statfs(struct super_block *sb,
struct statfs *buf, int bufsize)
{
@@ -238,7 +310,7 @@ static int qnx4_statfs(struct super_block *sb,
* it really _is_ a qnx4 filesystem, and to check the size
* of the directory entry.
*/
-static const char *qnx4_checkroot(struct super_block *s)
+static const char *qnx4_checkroot(struct super_block *sb)
{
struct buffer_head *bh;
struct qnx4_inode_entry *rootdir;
@@ -246,14 +318,14 @@ static const char *qnx4_checkroot(struct super_block *s)
int i, j;
int found = 0;
- if (*(s->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
+ if (*(sb->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
return "no qnx4 filesystem (no root dir).";
} else {
- QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(s->s_dev)));
- rd = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
- rl = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
+ QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(sb->s_dev)));
+ rd = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
+ rl = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
for (j = 0; j < rl; j++) {
- bh = bread(s->s_dev, rd + j, QNX4_BLOCK_SIZE); /* root dir, first block */
+ bh = bread(sb->s_dev, rd + j, QNX4_BLOCK_SIZE); /* root dir, first block */
if (bh == NULL) {
return "unable to read root entry.";
}
@@ -263,13 +335,12 @@ static const char *qnx4_checkroot(struct super_block *s)
QNX4DEBUG(("Rootdir entry found : [%s]\n", rootdir->di_fname));
if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
found = 1;
- s->u.qnx4_sb.BitMap = rootdir; /* keep bitmap inode known */
+ sb->u.qnx4_sb.BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
+ memcpy( sb->u.qnx4_sb.BitMap, rootdir, sizeof( struct qnx4_inode_entry ) ); /* keep bitmap inode known */
break;
}
}
}
- /* WAIT! s->u.qnx4_sb.BitMap points into bh->b_data
- and now we release bh?? */
brelse(bh);
if (found != 0) {
break;
@@ -282,13 +353,12 @@ static const char *qnx4_checkroot(struct super_block *s)
return NULL;
}
-static struct super_block *qnx4_read_super(struct super_block *s,
+static struct super_block *qnx4_read_super(struct super_block *s,
void *data, int silent)
{
struct buffer_head *bh;
kdev_t dev = s->s_dev;
struct inode *root;
- char *tmpc;
const char *errmsg;
MOD_INC_USE_COUNT;
@@ -306,9 +376,7 @@ static struct super_block *qnx4_read_super(struct super_block *s,
printk("qnx4: unable to read the boot sector\n");
goto outnobh;
}
- tmpc = (char *) bh->b_data;
- if (tmpc[4] != 'Q' || tmpc[5] != 'N' || tmpc[6] != 'X' ||
- tmpc[7] != '4' || tmpc[8] != 'F' || tmpc[9] != 'S') {
+ if ( memcmp( (char*)bh->b_data + 4, "QNX4FS", 6 ) ) {
if (!silent)
printk("qnx4: wrong fsid in boot sector.\n");
goto out;
@@ -328,7 +396,7 @@ static struct super_block *qnx4_read_super(struct super_block *s,
s->u.qnx4_sb.sb_buf = bh;
s->u.qnx4_sb.sb = (struct qnx4_super_block *) bh->b_data;
-
+
/* check before allocating dentries, inodes, .. */
errmsg = qnx4_checkroot(s);
if (errmsg != NULL) {
@@ -336,18 +404,18 @@ static struct super_block *qnx4_read_super(struct super_block *s,
printk("qnx4: %s\n", errmsg);
goto out;
}
-
+
/* does root not have inode number QNX4_ROOT_INO ?? */
root = iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
if (!root) {
printk("qnx4: get inode failed\n");
goto out;
}
-
+
s->s_root = d_alloc_root(root);
if (s->s_root == NULL)
goto outi;
-
+
brelse(bh);
unlock_super(s);
s->s_dirt = 1;
@@ -368,6 +436,7 @@ static struct super_block *qnx4_read_super(struct super_block *s,
static void qnx4_put_super(struct super_block *sb)
{
+ kfree_s( sb->u.qnx4_sb.BitMap, sizeof( struct qnx4_inode_entry ) );
MOD_DEC_USE_COUNT;
return;
}
@@ -434,7 +503,7 @@ static struct file_system_type qnx4_fs_type =
int __init init_qnx4_fs(void)
{
- printk("QNX4 filesystem v0.2 registered.\n");
+ printk("QNX4 filesystem 0.2.1 registered.\n");
return register_filesystem(&qnx4_fs_type);
}
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c
index feb014b8e..0b6e087e5 100644
--- a/fs/qnx4/namei.c
+++ b/fs/qnx4/namei.c
@@ -1,7 +1,7 @@
/*
* QNX4 file system, Linux implementation.
*
- * Version : 0.1
+ * Version : 0.2.1
*
* Using parts of the xiafs filesystem.
*
@@ -33,7 +33,8 @@ static int qnx4_match(int len, const char *name,
struct buffer_head *bh, unsigned long *offset)
{
struct qnx4_inode_entry *de;
- int namelen;
+ struct qnx4_link_info *le;
+ int namelen, thislen;
if (bh == NULL) {
printk("qnx4: matching unassigned buffer !\n");
@@ -41,23 +42,24 @@ static int qnx4_match(int len, const char *name,
}
de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
*offset += QNX4_DIR_ENTRY_SIZE;
- if ((de->di_status & 0x08) == 0x08) {
+ if ((de->di_status & QNX4_FILE_LINK) != 0) {
namelen = QNX4_NAME_MAX;
} else {
- namelen = _SHORT_NAME_MAX;
+ namelen = QNX4_SHORT_NAME_MAX;
}
/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
return 1;
}
- if (len != strlen(de->di_fname)) {
+ thislen = strlen( de->di_fname );
+ if ( thislen > namelen )
+ thislen = namelen;
+ if (len != thislen) {
return 0;
}
if (strncmp(name, de->di_fname, len) == 0) {
- if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
- if (de->di_status) {
- return 1;
- }
+ if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
+ return 1;
}
}
return 0;
@@ -75,19 +77,19 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
return NULL;
}
bh = NULL;
- blkofs = dir->u.qnx4_i.i_first_xtnt.xtnt_blk - 1;
- offset = block = 0;
- while (block * QNX4_BLOCK_SIZE + offset < dir->i_size) {
+ block = offset = blkofs = 0;
+ while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
if (!bh) {
- bh = qnx4_bread(dir, block + blkofs, 0);
+ block = qnx4_block_map( dir, blkofs );
+ bh = qnx4_bread(dir, block, 0);
if (!bh) {
- block++;
+ blkofs++;
continue;
}
}
*res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
if (qnx4_match(len, name, bh, &offset)) {
- *ino = (block + blkofs) * QNX4_INODES_PER_BLOCK +
+ *ino = block * QNX4_INODES_PER_BLOCK +
(offset / QNX4_DIR_ENTRY_SIZE) - 1;
return bh;
}
@@ -97,7 +99,7 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
brelse(bh);
bh = NULL;
offset = 0;
- block++;
+ blkofs++;
}
brelse(bh);
*res_dir = NULL;
diff --git a/fs/qnx4/symlinks.c b/fs/qnx4/symlinks.c
index ed7cdfca6..827b837ee 100644
--- a/fs/qnx4/symlinks.c
+++ b/fs/qnx4/symlinks.c
@@ -1,7 +1,7 @@
/*
* QNX4 file system, Linux implementation.
*
- * Version : 0.1
+ * Version : 0.2.1
*
* Using parts of the xiafs filesystem.
*
@@ -31,88 +31,8 @@ static struct dentry *qnx4_follow_link(struct dentry *, struct dentry *, unsigne
*/
struct inode_operations qnx4_symlink_inode_operations =
{
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- qnx4_readlink, /* readlink */
- qnx4_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: qnx4_get_block,
+ readpage: block_read_full_page,
};
-
-static struct dentry *qnx4_follow_link(struct dentry *dentry,
- struct dentry *base, unsigned int follow)
-{
-#if 0
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
-
- if (!inode) {
- return ERR_PTR(-ENOENT);
- }
- if (current->link_count > 5) {
- return ERR_PTR(-ELOOP);
- }
- if (!(bh = qnx4_bread(inode, 0, 0))) {
- return ERR_PTR(-EIO);
- }
- current->link_count++;
- current->link_count--;
- brelse(bh);
- return 0;
-#else
- printk("qnx4: qnx4_follow_link needs to be fixed.\n");
- return ERR_PTR(-EIO);
-#endif
-}
-
-static int qnx4_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
- int i;
- char c;
- struct qnx4_inode_info *qnx4_ino;
-
- QNX4DEBUG(("qnx4: qnx4_readlink() called\n"));
-
- if (buffer == NULL || inode == NULL || !S_ISLNK(inode->i_mode)) {
- return -EINVAL;
- }
- qnx4_ino = &inode->u.qnx4_i;
- if (buflen > 1023) {
- buflen = 1023;
- }
- bh = bread(inode->i_dev, qnx4_ino->i_first_xtnt.xtnt_blk,
- QNX4_BLOCK_SIZE);
- if (bh == NULL) {
- QNX4DEBUG(("qnx4: NULL symlink bh\n"));
- return 0;
- }
- QNX4DEBUG(("qnx4: qnx4_bread sym called -> [%s]\n",
- bh->b_data));
- if (bh->b_data[0] != 0) {
- i = 0;
- while (i < buflen && (c = bh->b_data[i])) {
- i++;
- put_user(c, buffer++);
- }
- brelse(bh);
- return i;
- } else {
- brelse(bh);
- memcpy(buffer, "fixme", 5);
- return 5;
- }
-}
diff --git a/fs/read_write.c b/fs/read_write.c
index eb729a4fd..c15ce4c73 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -39,11 +39,15 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin)
static inline loff_t llseek(struct file *file, loff_t offset, int origin)
{
loff_t (*fn)(struct file *, loff_t, int);
+ loff_t retval;
fn = default_llseek;
if (file->f_op && file->f_op->llseek)
fn = file->f_op->llseek;
- return fn(file, offset, origin);
+ lock_kernel();
+ retval = fn(file, offset, origin);
+ unlock_kernel();
+ return retval;
}
asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
@@ -53,7 +57,6 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
struct dentry * dentry;
struct inode * inode;
- lock_kernel();
retval = -EBADF;
file = fget(fd);
if (!file)
@@ -72,7 +75,6 @@ asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
out_putf:
fput(file);
bad:
- unlock_kernel();
return retval;
}
@@ -87,7 +89,6 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
struct inode * inode;
loff_t offset;
- lock_kernel();
retval = -EBADF;
file = fget(fd);
if (!file)
@@ -112,7 +113,6 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
out_putf:
fput(file);
bad:
- unlock_kernel();
return retval;
}
#endif
@@ -264,7 +264,6 @@ asmlinkage ssize_t sys_readv(unsigned long fd, const struct iovec * vector,
struct file * file;
ssize_t ret;
- lock_kernel();
ret = -EBADF;
file = fget(fd);
@@ -275,7 +274,6 @@ asmlinkage ssize_t sys_readv(unsigned long fd, const struct iovec * vector,
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
@@ -285,19 +283,16 @@ asmlinkage ssize_t sys_writev(unsigned long fd, const struct iovec * vector,
struct file * file;
ssize_t ret;
- lock_kernel();
ret = -EBADF;
file = fget(fd);
if (!file)
goto bad_file;
- if (file->f_op && file->f_op->write && (file->f_mode & FMODE_WRITE)) {
+ if (file->f_op && file->f_op->write && (file->f_mode & FMODE_WRITE))
ret = do_readv_writev(VERIFY_READ, file, vector, count);
- }
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
@@ -312,8 +307,6 @@ asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
struct file * file;
ssize_t (*read)(struct file *, char *, size_t, loff_t *);
- lock_kernel();
-
ret = -EBADF;
file = fget(fd);
if (!file)
@@ -333,7 +326,6 @@ asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
out:
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
@@ -344,8 +336,6 @@ asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
struct file * file;
ssize_t (*write)(struct file *, const char *, size_t, loff_t *);
- lock_kernel();
-
ret = -EBADF;
file = fget(fd);
if (!file)
@@ -366,6 +356,5 @@ asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
out:
fput(file);
bad_file:
- unlock_kernel();
return ret;
}
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 287f4f60b..692754912 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -459,8 +459,6 @@ static struct file_operations romfs_file_operations = {
NULL, /* release */
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
static struct inode_operations romfs_file_inode_operations = {
@@ -489,16 +487,6 @@ static struct file_operations romfs_dir_operations = {
NULL, /* read */
NULL, /* write - bad */
romfs_readdir, /* readdir */
- NULL, /* poll - default */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* flush */
- NULL, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
/* Merged dir/symlink op table. readdir/lookup/readlink/follow_link
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 189c853f9..f5aff8730 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -379,8 +379,6 @@ static struct file_operations smb_file_operations =
smb_file_release, /* release(struct inode*, struct file*) */
smb_fsync, /* fsync(struct file*, struct dentry*) */
NULL, /* fasync(struct file*, int) */
- NULL, /* check_media_change(kdev_t dev) */
- NULL, /* revalidate(kdev_t dev) */
NULL /* lock(struct file*, int, struct file_lock*) */
};
diff --git a/fs/stat.c b/fs/stat.c
index 709477439..725df6fc8 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -280,3 +280,124 @@ asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
unlock_kernel();
return error;
}
+
+
+/* ---------- LFS-64 ----------- */
+#if !defined(__alpha__) && !defined(__mips64)
+
+static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
+{
+ struct stat64 tmp;
+ unsigned int blocks, indirect;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.st_dev = kdev_t_to_nr(inode->i_dev);
+ tmp.st_ino = inode->i_ino;
+ tmp.st_mode = inode->i_mode;
+ tmp.st_nlink = inode->i_nlink;
+ tmp.st_uid = inode->i_uid;
+ tmp.st_gid = inode->i_gid;
+ tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+ tmp.st_atime = inode->i_atime;
+ tmp.st_mtime = inode->i_mtime;
+ tmp.st_ctime = inode->i_ctime;
+ tmp.st_size = inode->i_size;
+/*
+ * st_blocks and st_blksize are approximated with a simple algorithm if
+ * they aren't supported directly by the filesystem. The minix and msdos
+ * filesystems don't keep track of blocks, so they would either have to
+ * be counted explicitly (by delving into the file itself), or by using
+ * this simple algorithm to get a reasonable (although not 100% accurate)
+ * value.
+ */
+
+/*
+ * Use minix fs values for the number of direct and indirect blocks. The
+ * count is now exact for the minix fs except that it counts zero blocks.
+ * Everything is in units of BLOCK_SIZE until the assignment to
+ * tmp.st_blksize.
+ */
+#define D_B 7
+#define I_B (BLOCK_SIZE / sizeof(unsigned short))
+
+ if (!inode->i_blksize) {
+ blocks = (tmp.st_size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS;
+ if (blocks > D_B) {
+ indirect = (blocks - D_B + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1) {
+ indirect = (indirect - 1 + I_B - 1) / I_B;
+ blocks += indirect;
+ if (indirect > 1)
+ blocks++;
+ }
+ }
+ tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
+ tmp.st_blksize = BLOCK_SIZE;
+ } else {
+ tmp.st_blocks = inode->i_blocks;
+ tmp.st_blksize = inode->i_blksize;
+ }
+ return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags)
+{
+ struct dentry * dentry;
+ int error;
+
+ lock_kernel();
+ dentry = namei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ error = do_revalidate(dentry);
+ if (!error)
+ error = cp_new_stat64(dentry->d_inode, statbuf);
+
+ dput(dentry);
+ }
+ unlock_kernel();
+ return error;
+}
+
+asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags)
+{
+ struct dentry * dentry;
+ int error;
+
+ lock_kernel();
+ dentry = lnamei(filename);
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ error = do_revalidate(dentry);
+ if (!error)
+ error = cp_new_stat64(dentry->d_inode, statbuf);
+
+ dput(dentry);
+ }
+ unlock_kernel();
+ return error;
+}
+
+asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags)
+{
+ struct file * f;
+ int err = -EBADF;
+
+ lock_kernel();
+ f = fget(fd);
+ if (f) {
+ struct dentry * dentry = f->f_dentry;
+
+ err = do_revalidate(dentry);
+ if (!err)
+ err = cp_new_stat64(dentry->d_inode, statbuf);
+ fput(f);
+ }
+ unlock_kernel();
+ return err;
+}
+
+#endif /* LFS-64 */
diff --git a/fs/super.c b/fs/super.c
index 9f901236b..4c67729aa 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -45,7 +45,6 @@
static DECLARE_MUTEX(mount_sem);
extern void wait_for_keypress(void);
-extern struct file_operations * get_blkfops(unsigned int major);
extern int root_mountflags;
@@ -181,7 +180,6 @@ int register_filesystem(struct file_system_type * fs)
return 0;
}
-#ifdef CONFIG_MODULES
int unregister_filesystem(struct file_system_type * fs)
{
struct file_system_type ** tmp;
@@ -197,7 +195,6 @@ int unregister_filesystem(struct file_system_type * fs)
}
return -EINVAL;
}
-#endif
static int fs_index(const char * __name)
{
@@ -532,7 +529,8 @@ struct super_block *get_empty_super(void)
return s;
}
-static struct super_block * read_super(kdev_t dev,const char *name,int flags,
+static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
+ const char *name, int flags,
void *data, int silent)
{
struct super_block * s;
@@ -543,7 +541,7 @@ static struct super_block * read_super(kdev_t dev,const char *name,int flags,
check_disk_change(dev);
s = get_super(dev);
if (s)
- goto out;
+ goto found; /* ought to set ->s_bdev */
type = get_fs_type(name);
if (!type) {
@@ -555,23 +553,30 @@ static struct super_block * read_super(kdev_t dev,const char *name,int flags,
if (!s)
goto out;
s->s_dev = dev;
+ s->s_bdev = bdev;
s->s_flags = flags;
s->s_dirt = 0;
sema_init(&s->s_vfs_rename_sem,1);
/* N.B. Should lock superblock now ... */
if (!type->read_super(s, data, silent))
goto out_fail;
- s->s_dev = dev; /* N.B. why do this again?? */
s->s_type = type;
+bd_get:
+ /* tell bdcache that we are going to keep this one */
+ if (bdev)
+ atomic_inc(&bdev->bd_count);
out:
return s;
- /* N.B. s_dev should be cleared in type->read_super */
out_fail:
s->s_dev = 0;
+ s->s_bdev = 0;
out_null:
s = NULL;
goto out;
+found:
+ s->s_bdev = bdev;
+ goto bd_get;
}
/*
@@ -634,9 +639,10 @@ static void d_mount(struct dentry *covered, struct dentry *dentry)
dentry->d_covers = covered;
}
-static int do_umount(kdev_t dev, int unmount_root, int flags)
+static struct block_device *do_umount(kdev_t dev, int unmount_root, int flags)
{
struct super_block * sb;
+ struct block_device *bdev;
int retval;
retval = -ENOENT;
@@ -683,7 +689,7 @@ static int do_umount(kdev_t dev, int unmount_root, int flags)
retval = 0;
if (!(sb->s_flags & MS_RDONLY))
retval = do_remount_sb(sb, MS_RDONLY, 0);
- return retval;
+ return ERR_PTR(retval);
}
retval = d_umount(sb);
@@ -708,43 +714,44 @@ static int do_umount(kdev_t dev, int unmount_root, int flags)
}
sb->s_dev = 0; /* Free the superblock */
+ bdev = sb->s_bdev;
+ sb->s_bdev = NULL;
unlock_super(sb);
remove_vfsmnt(dev);
+
+ return bdev;
+
out:
- return retval;
+ return ERR_PTR(retval);
}
static int umount_dev(kdev_t dev, int flags)
{
int retval;
- struct inode * inode = get_empty_inode();
+ struct block_device *bdev;
- retval = -ENOMEM;
- if (!inode)
- goto out;
-
- inode->i_rdev = dev;
retval = -ENXIO;
if (MAJOR(dev) >= MAX_BLKDEV)
- goto out_iput;
+ goto out;
fsync_dev(dev);
down(&mount_sem);
- retval = do_umount(dev, 0, flags);
- if (!retval) {
- fsync_dev(dev);
- if (dev != ROOT_DEV) {
- blkdev_release(inode);
+ bdev = do_umount(dev, 0, flags);
+ if (IS_ERR(bdev))
+ retval = PTR_ERR(bdev);
+ else {
+ retval = 0;
+ if (bdev) {
+ blkdev_put(bdev, BDEV_FS);
+ bdput(bdev);
+ } else {
put_unnamed_dev(dev);
}
}
-
up(&mount_sem);
-out_iput:
- iput(inode);
out:
return retval;
}
@@ -753,12 +760,6 @@ out:
* Now umount can handle mount points as well as block devices.
* This is important for filesystems which use unnamed block devices.
*
- * There is a little kludge here with the dummy_inode. The current
- * vfs release functions only use the r_dev field in the inode so
- * we give them the info they need without using a real inode.
- * If any other fields are ever needed by any block device release
- * functions, they should be faked here. -- jrs
- *
* We now support a flag for forced unmount like the other 'big iron'
* unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
*/
@@ -842,14 +843,29 @@ int fs_may_mount(kdev_t dev)
* Anyone using this new feature must know what he/she is doing.
*/
-int do_mount(kdev_t dev, const char * dev_name, const char * dir_name,
- const char * type, int flags, void * data)
+int do_mount(struct block_device *bdev, const char *dev_name,
+ const char *dir_name, const char * type, int flags, void * data)
{
+ kdev_t dev;
struct dentry * dir_d;
struct super_block * sb;
struct vfsmount *vfsmnt;
int error;
+ if (bdev) {
+ mode_t mode = FMODE_READ; /* we always need it ;-) */
+ if (!(flags & MS_RDONLY))
+ mode |= FMODE_WRITE;
+ dev = to_kdev_t(bdev->bd_dev);
+ error = blkdev_get(bdev, mode, 0, BDEV_FS);
+ if (error)
+ return error;
+ } else {
+ dev = get_unnamed_dev();
+ if (!dev)
+ return -EMFILE; /* huh? */
+ }
+
error = -EACCES;
if (!(flags & MS_RDONLY) && dev && is_read_only(dev))
goto out;
@@ -876,7 +892,7 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name,
* read_super just does a get_super().
*/
error = -EINVAL;
- sb = read_super(dev, type, flags, data, 0);
+ sb = read_super(dev, bdev, type, flags, data, 0);
if (!sb)
goto dput_and_out;
@@ -886,20 +902,30 @@ int do_mount(kdev_t dev, const char * dev_name, const char * dir_name,
*/
error = -EBUSY;
if (!fs_may_mount(dev))
- goto dput_and_out;
+ goto bdput_and_out;
error = -ENOMEM;
vfsmnt = add_vfsmnt(sb, dev_name, dir_name);
if (vfsmnt) {
d_mount(dget(dir_d), sb->s_root);
- error = 0;
+ dput(dir_d);
+ up(&mount_sem);
+ return 0;
}
+bdput_and_out:
+ sb->s_bdev = NULL;
+ if (bdev)
+ bdput(bdev);
dput_and_out:
dput(dir_d);
up(&mount_sem);
out:
- return error;
+ if (bdev)
+ blkdev_put(bdev, BDEV_FS);
+ else
+ put_unnamed_dev(dev);
+ return error;
}
@@ -1019,11 +1045,10 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
struct file_system_type * fstype;
struct dentry * dentry = NULL;
struct inode * inode = NULL;
- kdev_t dev;
+ struct block_device *bdev = NULL;
int retval;
unsigned long flags = 0;
unsigned long page = 0;
- struct file dummy; /* allows read-write or read-only flag */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -1049,7 +1074,6 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
if (!fstype)
goto out;
- memset(&dummy, 0, sizeof(dummy));
if (fstype->fs_flags & FS_REQUIRES_DEV) {
dentry = namei(dev_name);
retval = PTR_ERR(dentry);
@@ -1065,28 +1089,7 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
if (IS_NODEV(inode))
goto dput_and_out;
- dev = inode->i_rdev;
- retval = -ENXIO;
- if (MAJOR(dev) >= MAX_BLKDEV)
- goto dput_and_out;
-
- retval = -ENOTBLK;
- dummy.f_op = get_blkfops(MAJOR(dev));
- if (!dummy.f_op)
- goto dput_and_out;
-
- if (dummy.f_op->open) {
- dummy.f_dentry = dentry;
- dummy.f_mode = (new_flags & MS_RDONLY) ? 1 : 3;
- retval = dummy.f_op->open(inode, &dummy);
- if (retval)
- goto dput_and_out;
- }
-
- } else {
- retval = -EMFILE;
- if (!(dev = get_unnamed_dev()))
- goto out;
+ bdev = inode->i_bdev;
}
page = 0;
@@ -1094,27 +1097,17 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
flags = new_flags & ~MS_MGC_MSK;
retval = copy_mount_options(data, &page);
if (retval < 0)
- goto clean_up;
+ goto dput_and_out;
}
- retval = do_mount(dev, dev_name, dir_name, fstype->name, flags,
+ retval = do_mount(bdev, dev_name, dir_name, fstype->name, flags,
(void *) page);
free_page(page);
- if (retval)
- goto clean_up;
dput_and_out:
dput(dentry);
out:
unlock_kernel();
return retval;
-
-clean_up:
- if (dummy.f_op) {
- if (dummy.f_op->release)
- dummy.f_op->release(inode, NULL);
- } else
- put_unnamed_dev(dev);
- goto dput_and_out;
}
void __init mount_root(void)
@@ -1122,8 +1115,8 @@ void __init mount_root(void)
struct file_system_type * fs_type;
struct super_block * sb;
struct vfsmount *vfsmnt;
- struct inode * d_inode = NULL;
- struct file filp;
+ struct block_device *bdev = NULL;
+ mode_t mode;
int retval;
#ifdef CONFIG_ROOT_NFS
@@ -1132,6 +1125,7 @@ void __init mount_root(void)
if ((fs_type = get_fs_type("nfs"))) {
sb = get_empty_super(); /* "can't fail" */
sb->s_dev = get_unnamed_dev();
+ sb->s_bdev = NULL;
sb->s_flags = root_mountflags;
sema_init(&sb->s_vfs_rename_sem,1);
vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
@@ -1179,23 +1173,17 @@ void __init mount_root(void)
}
#endif
- memset(&filp, 0, sizeof(filp));
- d_inode = get_empty_inode();
- if (!d_inode)
- panic(__FUNCTION__ ": unable to allocate root inode");
- d_inode->i_rdev = ROOT_DEV;
- filp.f_dentry = NULL;
- if ( root_mountflags & MS_RDONLY)
- filp.f_mode = 1; /* read only */
- else
- filp.f_mode = 3; /* read write */
- retval = blkdev_open(d_inode, &filp);
+ bdev = bdget(kdev_t_to_nr(ROOT_DEV));
+ if (!bdget)
+ panic(__FUNCTION__ ": unable to allocate root device");
+ mode = FMODE_READ;
+ if (!(root_mountflags & MS_RDONLY))
+ mode |= FMODE_WRITE;
+ retval = blkdev_get(bdev, mode, 0, BDEV_FS);
if (retval == -EROFS) {
root_mountflags |= MS_RDONLY;
- filp.f_mode = 1;
- retval = blkdev_open(d_inode, &filp);
+ retval = blkdev_get(bdev, FMODE_READ, 0, BDEV_FS);
}
- iput(d_inode);
if (retval)
/*
* Allow the user to distinguish between failed open
@@ -1206,7 +1194,7 @@ void __init mount_root(void)
else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if (!(fs_type->fs_flags & FS_REQUIRES_DEV))
continue;
- sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
+ sb = read_super(ROOT_DEV,bdev,fs_type->name,root_mountflags,NULL,1);
if (sb) {
sb->s_flags = root_mountflags;
current->fs->root = dget(sb->s_root);
@@ -1215,8 +1203,10 @@ void __init mount_root(void)
fs_type->name,
(sb->s_flags & MS_RDONLY) ? " readonly" : "");
vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
- if (vfsmnt)
+ if (vfsmnt) {
+ bdput(bdev); /* sb holds a reference */
return;
+ }
panic("VFS: add_vfsmnt failed for root fs");
}
}
@@ -1270,16 +1260,20 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
error = -ENOTDIR;
}
if (error) {
- int umount_error;
+ struct block_device *bdev;
printk(KERN_NOTICE "Trying to unmount old root ... ");
- umount_error = do_umount(old_root_dev,1, 0);
- if (!umount_error) {
+ bdev = do_umount(old_root_dev,1, 0);
+ if (!IS_ERR(bdev)) {
printk("okay\n");
invalidate_buffers(old_root_dev);
+ if (bdev) {
+ blkdev_put(bdev, BDEV_FS);
+ bdput(bdev);
+ }
return 0;
}
- printk(KERN_ERR "error %d\n",umount_error);
+ printk(KERN_ERR "error %d\n",PTR_ERR(bdev));
return error;
}
remove_vfsmnt(old_root_dev);
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index f54b8d6bc..2a0d03850 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -57,8 +57,6 @@ static struct file_operations sysv_file_operations = {
NULL, /* release */
sysv_sync_file, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
struct inode_operations sysv_file_inode_operations = {
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 03e66fe23..41274039d 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -104,7 +104,7 @@ static int read_block_bitmap(struct super_block * sb, unsigned int block,
return retval;
}
-static int load__block_bitmap(struct super_block * sb, unsigned int block_group)
+static int __load_block_bitmap(struct super_block * sb, unsigned int block_group)
{
int i, j, retval = 0;
unsigned long block_bitmap_number;
@@ -188,7 +188,7 @@ static inline int load_block_bitmap(struct super_block *sb,
}
else
{
- slot = load__block_bitmap(sb, block_group);
+ slot = __load_block_bitmap(sb, block_group);
}
if (slot < 0)
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 84218eb14..7b7d065ff 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -62,8 +62,6 @@ static struct file_operations udf_dir_operations = {
NULL, /* release */
udf_sync_file, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL /* lock */
};
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 2e17d81d4..81cddaa3f 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -46,31 +46,23 @@
static loff_t udf_file_llseek(struct file *, loff_t, int);
static ssize_t udf_file_read_adinicb (struct file *, char *, size_t, loff_t *);
static ssize_t udf_file_write (struct file *, const char *, size_t, loff_t *);
-#if BITS_PER_LONG < 64
static int udf_open_file(struct inode *, struct file *);
-#endif
static int udf_release_file(struct inode *, struct file *);
static struct file_operations udf_file_operations = {
udf_file_llseek, /* llseek */
generic_file_read, /* read */
udf_file_write, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- udf_ioctl, /* ioctl */
+ NULL, /* readdir */
+ NULL, /* poll */
+ udf_ioctl, /* ioctl */
generic_file_mmap, /* mmap */
-#if BITS_PER_LONG == 64
- NULL, /* open */
-#else
udf_open_file, /* open */
-#endif
- NULL, /* flush */
+ NULL, /* flush */
udf_release_file, /* release */
udf_sync_file, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
+ NULL, /* fasync */
+ NULL /* lock */
};
struct inode_operations udf_file_inode_operations = {
@@ -111,8 +103,6 @@ static struct file_operations udf_file_operations_adinicb = {
udf_release_file, /* release */
udf_sync_file, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
NULL /* lock */
};
@@ -426,7 +416,6 @@ static int udf_release_file(struct inode * inode, struct file * filp)
return 0;
}
-#if BITS_PER_LONG < 64
/*
* udf_open_file
*
@@ -435,6 +424,7 @@ static int udf_release_file(struct inode * inode, struct file * filp)
*
* DESCRIPTION
* Use this to disallow opening RW large files on 32 bit systems.
+ * On 64 bit systems we force on O_LARGEFILE in sys_open.
*
* HISTORY
*
@@ -445,4 +435,3 @@ static int udf_open_file(struct inode * inode, struct file * filp)
return -EFBIG;
return 0;
}
-#endif
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 05e03def5..e2e12df8e 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1147,19 +1147,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
}
case FILE_TYPE_BLOCK:
{
- inode->i_op = &blkdev_inode_operations;
inode->i_mode |= S_IFBLK;
break;
}
case FILE_TYPE_CHAR:
{
- inode->i_op = &chrdev_inode_operations;
inode->i_mode |= S_IFCHR;
break;
}
case FILE_TYPE_FIFO:
{
- init_fifo(inode);
+ init_special_inode(inode, inode->i_mode | S_IFIFO, 0);
+ break;
}
case FILE_TYPE_SYMLINK:
{
@@ -1185,9 +1184,9 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
if (dsea)
{
- inode->i_rdev = to_kdev_t(
- (le32_to_cpu(dsea->majorDeviceIdent)) << 8) |
- (le32_to_cpu(dsea->minorDeviceIdent) & 0xFF);
+ init_special_inode(inode, inode->i_mode,
+ ((le32_to_cpu(dsea->majorDeviceIdent)) << 8) |
+ (le32_to_cpu(dsea->minorDeviceIdent) & 0xFF));
/* Developer ID ??? */
udf_release_data(tbh);
}
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
index 0f763b5d1..dee98ad71 100644
--- a/fs/udf/lowlevel.c
+++ b/fs/udf/lowlevel.c
@@ -38,60 +38,36 @@ typedef struct scsi_cmnd Scsi_Cmnd;
#include "udf_sb.h"
unsigned int
-udf_get_last_session(kdev_t dev)
+udf_get_last_session(struct super_block *sb)
{
struct cdrom_multisession ms_info;
unsigned int vol_desc_start;
- struct inode inode_fake;
- extern struct file_operations * get_blkfops(unsigned int);
+ struct block_device *bdev = sb->s_bdev;
int i;
vol_desc_start=0;
- if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
- {
- /* Whoops. We must save the old FS, since otherwise
- * we would destroy the kernels idea about FS on root
- * mount in read_super... [chexum]
- */
- mm_segment_t old_fs=get_fs();
- inode_fake.i_rdev=dev;
- ms_info.addr_format=CDROM_LBA;
- set_fs(KERNEL_DS);
- i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
- NULL,
- CDROMMULTISESSION,
- (unsigned long) &ms_info);
- set_fs(old_fs);
-
+ ms_info.addr_format=CDROM_LBA;
+ i=ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
#define WE_OBEY_THE_WRITTEN_STANDARDS 1
-
- if (i == 0)
- {
- udf_debug("XA disk: %s, vol_desc_start=%d\n",
- (ms_info.xa_flag ? "yes" : "no"), ms_info.addr.lba);
+ if (i == 0) {
+ udf_debug("XA disk: %s, vol_desc_start=%d\n",
+ (ms_info.xa_flag ? "yes" : "no"), ms_info.addr.lba);
#if WE_OBEY_THE_WRITTEN_STANDARDS
- if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
+ if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */
#endif
- vol_desc_start = ms_info.addr.lba;
- }
- else
- {
- udf_debug("CDROMMULTISESSION not supported: rc=%d\n", i);
- }
- }
- else
- {
- udf_debug("Device doesn't know how to ioctl?\n");
+ vol_desc_start = ms_info.addr.lba;
+ } else {
+ udf_debug("CDROMMULTISESSION not supported: rc=%d\n", i);
}
return vol_desc_start;
}
unsigned int
-udf_get_last_block(kdev_t dev, int *flags)
+udf_get_last_block(struct super_block *sb, int *flags)
{
extern int *blksize_size[];
- struct inode inode_fake;
- extern struct file_operations * get_blkfops(unsigned int);
+ kdev_t dev = sb->s_dev;
+ struct block_device *bdev = sb->s_bdev;
int ret;
unsigned long lblock;
unsigned int hbsize = get_hardblocksize(dev);
@@ -107,44 +83,20 @@ udf_get_last_block(kdev_t dev, int *flags)
else if (hbsize > secsize)
div = hbsize / secsize;
- if (get_blkfops(MAJOR(dev))->ioctl!=NULL)
- {
- /* Whoops. We must save the old FS, since otherwise
- * we would destroy the kernels idea about FS on root
- * mount in read_super... [chexum]
- */
- mm_segment_t old_fs=get_fs();
- inode_fake.i_rdev=dev;
- set_fs(KERNEL_DS);
-
- lblock = 0;
- ret = get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
- NULL,
- BLKGETSIZE,
- (unsigned long) &lblock);
-
- if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */
- {
- if (mult)
- lblock *= mult;
- else if (div)
- lblock /= div;
- }
- else /* CDROM */
- {
- ret = get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
- NULL,
- CDROM_LAST_WRITTEN,
- (unsigned long) &lblock);
- }
-
- set_fs(old_fs);
- if (!ret && lblock)
- return lblock - 1;
- }
- else
- {
- udf_debug("Device doesn't know how to ioctl?\n");
+ lblock = 0;
+ ret = ioctl_by_bdev(bdev, BLKGETSIZE, (unsigned long) &lblock);
+
+ if (!ret && lblock != 0x7FFFFFFF) {
+ /* Hard Disk */
+ if (mult)
+ lblock *= mult;
+ else if (div)
+ lblock /= div;
+ } else {
+ /* CDROM */
+ ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
}
+ if (!ret && lblock)
+ return lblock - 1;
return 0;
}
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index ea921eeb3..ebf344832 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -702,24 +702,7 @@ int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
mark_inode_dirty(dir);
dir->i_version = ++event;
}
- if (S_ISREG(inode->i_mode))
- {
- inode->i_op = &udf_file_inode_operations;
- }
- else if (S_ISCHR(inode->i_mode))
- {
- inode->i_op = &chrdev_inode_operations;
- }
- else if (S_ISBLK(inode->i_mode))
- {
- inode->i_op = &blkdev_inode_operations;
- }
- else if (S_ISFIFO(inode->i_mode))
- {
- init_fifo(inode);
- }
- if (S_ISBLK(mode) || S_ISCHR(mode))
- inode->i_rdev = to_kdev_t(rdev);
+ init_special_inode(inode, mode, rdev);
mark_inode_dirty(inode);
if (fibh.sbh != fibh.ebh)
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 31fecbde2..aba702b57 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1335,14 +1335,14 @@ udf_read_super(struct super_block *sb, void *options, int silent)
goto error_out;
if ( uopt.session == 0xFFFFFFFF )
- UDF_SB_SESSION(sb) = udf_get_last_session(sb->s_dev);
+ UDF_SB_SESSION(sb) = udf_get_last_session(sb);
else
UDF_SB_SESSION(sb) = uopt.session;
udf_debug("Multi-session=%d\n", UDF_SB_SESSION(sb));
if ( uopt.lastblock == 0xFFFFFFFF )
- UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb->s_dev, &(UDF_SB(sb)->s_flags));
+ UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb, &(UDF_SB(sb)->s_flags));
else
UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 48dec10c5..f50ca705c 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -158,8 +158,8 @@ extern struct buffer_head *udf_read_untagged(struct super_block *, Uint32, Uint3
extern void udf_release_data(struct buffer_head *);
/* lowlevel.c */
-extern unsigned int udf_get_last_session(kdev_t);
-extern unsigned int udf_get_last_block(kdev_t, int *);
+extern unsigned int udf_get_last_session(struct super_block *);
+extern unsigned int udf_get_last_block(struct super_block *, int *);
/* partition.c */
extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index f2be33cfa..a828f3036 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -190,8 +190,6 @@ static struct file_operations ufs_dir_operations = {
NULL, /* release */
file_fsync, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
};
struct inode_operations ufs_dir_inode_operations = {
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index b014e6c14..fa4734d23 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -133,8 +133,6 @@ static struct file_operations ufs_file_operations = {
ufs_release_file, /* release */
NULL, /* fsync */
NULL, /* fasync */
- NULL, /* check_media_change */
- NULL /* revalidate */
};
struct inode_operations ufs_file_inode_operations = {
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 497f69867..33413b8cd 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -764,7 +764,7 @@ int ufs_symlink (struct inode * dir, struct dentry * dentry,
err = -ENAMETOOLONG;
l = strlen(symname)+1;
- if (l > dir->i_sb->s_blocksize)
+ if (l > sb->s_blocksize)
goto out;
err = -EIO;
@@ -774,8 +774,7 @@ int ufs_symlink (struct inode * dir, struct dentry * dentry,
}
inode->i_mode = S_IFLNK | S_IRWXUGO;
- /***if (l > sizeof (inode->u.ufs_i.i_data)) {***/
- if (1) {
+ if (l > sb->u.ufs_sb.s_uspi->s_maxsymlinklen) {
/* slow symlink */
inode->i_op = &ufs_symlink_inode_operations;
err = block_symlink(inode, symname, l);
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index a3419a5a8..11a13baec 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -497,6 +497,7 @@ struct super_block * ufs_read_super (struct super_block * sb, void * data,
uspi->s_fshift = 10;
uspi->s_sbsize = super_block_size = 2048;
uspi->s_sbbase = 0;
+ uspi->s_maxsymlinklen = 56;
flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUN | UFS_CG_SUN;
break;
@@ -507,6 +508,7 @@ struct super_block * ufs_read_super (struct super_block * sb, void * data,
uspi->s_fshift = 10;
uspi->s_sbsize = super_block_size = 2048;
uspi->s_sbbase = 0;
+ uspi->s_maxsymlinklen = 56;
flags |= UFS_DE_OLD | UFS_UID_EFT | UFS_ST_SUNx86 | UFS_CG_SUN;
break;
@@ -760,6 +762,10 @@ magic_found:
uspi->s_bpf = uspi->s_fsize << 3;
uspi->s_bpfshift = uspi->s_fshift + 3;
uspi->s_bpfmask = uspi->s_bpf - 1;
+ if ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
+ UFS_MOUNT_UFSTYPE_44BSD)
+ uspi->s_maxsymlinklen =
+ SWAB32(usb3->fs_u2.fs_44.fs_maxsymlinklen);
sb->u.ufs_sb.s_flags = flags;
sb->u.ufs_sb.s_swab = swab;
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 2ee7aaf0a..0dea64e75 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -8,6 +8,8 @@
* VFAT filesystem to <chaffee@cs.berkeley.edu>. Specify
* what file operation caused you trouble and if you can duplicate
* the problem, send a script that demonstrates it.
+ *
+ * Short name translation 1999 by Wolfram Pienkoss <wp@bsz.shk.th.schule.de>
*/
#define __NO_VERSION__
@@ -161,6 +163,69 @@ static int parse_options(char *options, struct fat_mount_options *opts)
return 1;
}
+static inline unsigned char
+vfat_getlower(struct nls_table *t, unsigned char c)
+{
+ return t->charset2lower[c];
+}
+
+static inline unsigned char
+vfat_tolower(struct nls_table *t, unsigned char c)
+{
+ unsigned char nc = t->charset2lower[c];
+
+ return nc ? nc : c;
+}
+
+static inline unsigned char
+vfat_getupper(struct nls_table *t, unsigned char c)
+{
+ return t->charset2upper[c];
+}
+
+static inline unsigned char
+vfat_toupper(struct nls_table *t, unsigned char c)
+{
+ unsigned char nc = t->charset2upper[c];
+
+ return nc ? nc : c;
+}
+
+static int
+vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
+ const unsigned char *s2, int len)
+{
+ while(len--)
+ if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
+ return 1;
+
+ return 0;
+}
+
+static inline unsigned char
+vfat_uni2short(struct nls_table *t, struct nls_unicode uc)
+{
+ unsigned char *up;
+
+ up = t->page_uni2charset[uc.uni2];
+ if (up)
+ return up[uc.uni1];
+
+ return 0;
+}
+
+static inline unsigned char
+vfat_uni2upper_short(struct nls_table *t, struct nls_unicode uc)
+{
+ unsigned char *up;
+
+ up = t->page_uni2charset[uc.uni2];
+ if (up)
+ return vfat_toupper(t, up[uc.uni1]);
+
+ return 0;
+}
+
/*
* Compute the hash for the vfat name corresponding to the dentry.
* Note: if the name is invalid, we leave the hash code unchanged so
@@ -190,9 +255,9 @@ static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
*/
static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
{
+ struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
const char *name;
int len;
- char c;
unsigned long hash;
len = qstr->len;
@@ -201,10 +266,8 @@ static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
len--;
hash = init_name_hash();
- while (len--) {
- c = tolower(*name++);
- hash = partial_name_hash(tolower(c), hash);
- }
+ while (len--)
+ hash = partial_name_hash(vfat_tolower(t, *name++), hash);
qstr->hash = end_name_hash(hash);
return 0;
@@ -215,6 +278,7 @@ static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
*/
static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
+ struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
int alen, blen;
/* A filename cannot end in '.' or we treat it like it has none */
@@ -225,7 +289,7 @@ static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
while (blen && b->name[blen-1] == '.')
blen--;
if (alen == blen) {
- if (strnicmp(a->name, b->name, alen) == 0)
+ if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
return 0;
}
return 1;
@@ -339,8 +403,6 @@ static int vfat_valid_longname(const char *name, int len, int xlate)
unsigned char c;
int i, baselen;
- if (IS_FREE(name)) return -EINVAL;
-
if (len && name[len-1] == ' ') return -EINVAL;
if (len >= 256) return -EINVAL;
for (i = 0; i < len; i++) {
@@ -369,44 +431,47 @@ static int vfat_valid_longname(const char *name, int len, int xlate)
return 0;
}
-static int vfat_valid_shortname(const char *name,int len,int utf8)
+static int vfat_valid_shortname(struct nls_table *nls, struct nls_unicode *name,
+ int len)
{
- const char *walk;
- unsigned char c;
+ struct nls_unicode *walk;
+ unsigned char c, l;
int space;
- int baselen;
+
+ c = vfat_uni2upper_short(nls, *name);
+ if (IS_FREE(&c))
+ return -EINVAL;
space = 1; /* disallow names starting with a dot */
- c = 0;
for (walk = name; len && walk-name < 8;) {
- c = *walk++;
len--;
- if (utf8 && (c & 0x80)) return -EINVAL;
+ l = vfat_uni2short(nls, *walk++);
+ c = vfat_getupper(nls, l);
+ if (!c) return -EINVAL;
+ if (l != vfat_tolower(nls, c)) return -EINVAL;
if (strchr(replace_chars,c)) return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
if (c < ' '|| c==':') return -EINVAL;
if (c == '.') break;
space = c == ' ';
}
if (space) return -EINVAL;
if (len && c != '.') {
- c = *walk++;
len--;
+ c = vfat_uni2upper_short(nls, *walk++);
if (c != '.') return -EINVAL;
}
- baselen = walk - name;
if (c == '.') {
- baselen--;
if (len >= 4) return -EINVAL;
while (len > 0) {
- c = *walk++;
len--;
- if (utf8 && (c & 0x80)) return -EINVAL;
+ l = vfat_uni2short(nls, *walk++);
+ c = vfat_getupper(nls, l);
+ if (!c) return -EINVAL;
+ if (l != vfat_tolower(nls, c)) return -EINVAL;
if (strchr(replace_chars,c))
return -EINVAL;
if (c < ' ' || c == '.'|| c==':')
return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
space = c == ' ';
}
if (space) return -EINVAL;
@@ -428,36 +493,41 @@ static int vfat_find_form(struct inode *dir,char *name)
return 0;
}
-static int vfat_format_name(const char *name,int len,char *res,int utf8)
+static int vfat_format_name(struct nls_table *nls, struct nls_unicode *name,
+ int len, char *res)
{
char *walk;
unsigned char c;
int space;
+ c = vfat_uni2upper_short(nls, *name);
+ if (IS_FREE(&c))
+ return -EINVAL;
+
space = 1; /* disallow names starting with a dot */
- for (walk = res; len-- && (c=*name++)!='.' ; walk++) {
+ for (walk = res; len--; walk++) {
+ c = vfat_uni2upper_short(nls, *name++);
+ if (c == '.') break;
+ if (!c) return -EINVAL;
if (walk-res == 8) return -EINVAL;
- if (utf8 && (c & 0x80)) return -EINVAL;
if (strchr(replace_chars,c)) return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
if (c < ' '|| c==':') return -EINVAL;
space = c == ' ';
- *walk = c >= 'a' && c <= 'z' ? c-32 : c;
+ *walk = c;
}
if (space) return -EINVAL;
if (len >= 0) {
while (walk-res < 8) *walk++ = ' ';
while (len > 0 && walk-res < MSDOS_NAME) {
- c = *name++;
+ c = vfat_uni2upper_short(nls, *name++);
len--;
- if (utf8 && (c & 0x80)) return -EINVAL;
+ if (!c) return -EINVAL;
if (strchr(replace_chars,c))
return -EINVAL;
if (c < ' ' || c == '.'|| c==':')
return -EINVAL;
- if (c >= 'A' && c <= 'Z') return -EINVAL;
space = c == ' ';
- *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
+ *walk++ = c;
}
if (space) return -EINVAL;
if (len) return -EINVAL;
@@ -472,44 +542,35 @@ static char skip_chars[] = ".:\"?<>| ";
/* Given a valid longname, create a unique shortname. Make sure the
* shortname does not exist
*/
-static int vfat_create_shortname(struct inode *dir, const char *name,
- int len, char *name_res, int utf8)
+static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
+ struct nls_unicode *name, int len,
+ char *name_res)
{
- const char *ip, *ext_start, *end;
- char *p;
- int sz, extlen, baselen;
- char msdos_name[13];
- char base[9], ext[4];
- int i;
- char buf[8];
- const char *name_start;
+ struct nls_unicode *ip, *op, *ext_start, *end, *name_start;
+ struct nls_unicode msdos_name[13];
+ char base[9], ext[4], buf[8], *p;
+ int sz, extlen, baselen, i;
- PRINTK2(("Entering vfat_create_shortname: name=%s, len=%d\n", name, len));
+ PRINTK2(("Entering vfat_create_shortname\n"));
sz = 0; /* Make compiler happy */
- if (len && name[len-1]==' ') return -EINVAL;
if (len <= 12) {
/* Do a case insensitive search if the name would be a valid
* shortname if is were all capitalized. However, do not
* allow spaces in short names because Win95 scandisk does
* not like that */
- for (i = 0, p = msdos_name, ip = name; ; i++, p++, ip++) {
+ for (i = 0, op = &msdos_name[0], ip = name; ; i++, ip++, op++) {
if (i == len) {
- if (vfat_format_name(msdos_name,
- len, name_res, utf8) < 0)
+ if (vfat_format_name(nls, &msdos_name[0], len,
+ name_res) < 0)
break;
PRINTK3(("vfat_create_shortname 1\n"));
if (vfat_find_form(dir, name_res) < 0)
return 0;
return -EEXIST;
}
-
- if (*ip == ' ')
+ if (vfat_uni2upper_short(nls, *ip) == ' ')
break;
- if (*ip >= 'A' && *ip <= 'Z') {
- *p = *ip + 32;
- } else {
- *p = *ip;
- }
+ *op = *ip;
}
}
@@ -517,7 +578,7 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
/* Now, we need to create a shortname from the long name */
ext_start = end = &name[len];
while (--ext_start >= name) {
- if (*ext_start == '.') {
+ if (vfat_uni2upper_short(nls, *ext_start) == '.') {
if (ext_start == end - 1) {
sz = len;
ext_start = NULL;
@@ -537,7 +598,11 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
name_start = &name[0];
while (name_start < ext_start)
{
- if (!strchr(skip_chars,*name_start)) break;
+ unsigned char c = vfat_uni2upper_short(nls, *name_start);
+ if (!c)
+ break;
+ if (!strchr(skip_chars, c))
+ break;
name_start++;
}
if (name_start != ext_start) {
@@ -551,16 +616,15 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
for (baselen = i = 0, p = base, ip = name; i < sz && baselen < 8; i++)
{
- if (utf8 && (*ip & 0x80)) {
- *p++ = '_';
+ unsigned char c = vfat_uni2upper_short(nls, *ip);
+ if (!c) {
+ *p++ = c = '_';
baselen++;
- } else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'a' && *ip <= 'z') {
- *p = *ip - 32;
- } else {
- *p = *ip;
- }
- if (strchr(replace_chars, *p)) *p='_';
+ } else if (!strchr(skip_chars, c)) {
+ if (strchr(replace_chars, c))
+ *p = '_';
+ else
+ *p = c;
p++; baselen++;
}
ip++;
@@ -572,18 +636,16 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
extlen = 0;
if (ext_start) {
for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
- if (utf8 && (*ip & 0x80)) {
- *p++ = '_';
+ unsigned char c = vfat_uni2upper_short(nls, *ip);
+ if (!c) {
+ *p++ = c = '_';
extlen++;
- } else if (!strchr(skip_chars, *ip)) {
- if (*ip >= 'a' && *ip <= 'z') {
- *p = *ip - 32;
- } else {
- *p = *ip;
- }
- if (strchr(replace_chars, *p)) *p='_';
- extlen++;
- p++;
+ } else if (!strchr(skip_chars, c)) {
+ if (strchr(replace_chars, c))
+ *p = '_';
+ else
+ *p = c;
+ p++; extlen++;
}
}
}
@@ -641,14 +703,14 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
/* Translate a string, including coded sequences into Unicode */
static int
-xlate_to_uni(const char *name, int len, char *outname, int *outlen,
+xlate_to_uni(const char *name, int len, char *outname, int *longlen, int *outlen,
int escape, int utf8, struct nls_table *nls)
{
- int i;
const unsigned char *ip;
+ unsigned char nc;
char *op;
- int fill;
- unsigned char c1, c2, c3;
+ unsigned int ec;
+ int i, k, fill;
if (utf8) {
*outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
@@ -658,25 +720,40 @@ xlate_to_uni(const char *name, int len, char *outname, int *outlen,
} else {
if (name[len-1] == '.')
len--;
- op = outname;
if (nls) {
for (i = 0, ip = name, op = outname, *outlen = 0;
- i < len && *outlen <= 260; i++, *outlen += 1)
+ i < len && *outlen <= 260; *outlen += 1)
{
if (escape && (*ip == ':')) {
- if (i > len - 4) return -EINVAL;
- c1 = fat_esc2uni[ip[1]];
- c2 = fat_esc2uni[ip[2]];
- c3 = fat_esc2uni[ip[3]];
- if (c1 == 255 || c2 == 255 || c3 == 255)
+ if (i > len - 5)
return -EINVAL;
- *op++ = (c1 << 4) + (c2 >> 2);
- *op++ = ((c2 & 0x3) << 6) + c3;
- ip += 4;
+ ec = 0;
+ for (k = 1; k < 5; k++) {
+ nc = ip[k];
+ ec <<= 4;
+ if (nc >= '0' && nc <= '9') {
+ ec |= nc - '0';
+ continue;
+ }
+ if (nc >= 'a' && nc <= 'f') {
+ ec |= nc - ('a' - 10);
+ continue;
+ }
+ if (nc >= 'A' && nc <= 'F') {
+ ec |= nc - ('A' - 10);
+ continue;
+ }
+ return -EINVAL;
+ }
+ *op++ = ec & 0xFF;
+ *op++ = ec >> 8;
+ ip += 5;
+ i += 5;
} else {
*op++ = nls->charset2uni[*ip].uni1;
*op++ = nls->charset2uni[*ip].uni2;
ip++;
+ i++;
}
}
} else {
@@ -691,6 +768,7 @@ xlate_to_uni(const char *name, int len, char *outname, int *outlen,
if (*outlen > 260)
return -ENAMETOOLONG;
+ *longlen = *outlen;
if (*outlen % 13) {
*op++ = 0;
*op++ = 0;
@@ -709,37 +787,49 @@ xlate_to_uni(const char *name, int len, char *outname, int *outlen,
}
static int
-vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
- char *msdos_name, int *slots,
- int uni_xlate, int utf8, struct nls_table *nls)
+vfat_fill_slots(struct inode *dir, struct msdos_dir_slot *ds, const char *name,
+ int len, int *slots, int uni_xlate)
{
+ struct nls_table *nls_io, *nls_disk;
+ struct nls_unicode *uname;
struct msdos_dir_slot *ps;
struct msdos_dir_entry *de;
- int res;
- int slot;
+ unsigned long page;
unsigned char cksum;
- char *uniname;
const char *ip;
- unsigned long page;
- int unilen;
- int i;
+ char *uniname, msdos_name[MSDOS_NAME];
+ int res, utf8, slot, ulen, unilen, i;
loff_t offset;
+ de = (struct msdos_dir_entry *) ds;
+ utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
+ nls_io = MSDOS_SB(dir->i_sb)->nls_io;
+ nls_disk = MSDOS_SB(dir->i_sb)->nls_disk;
+
if (name[len-1] == '.') len--;
if(!(page = __get_free_page(GFP_KERNEL)))
return -ENOMEM;
uniname = (char *) page;
- res = xlate_to_uni(name, len, uniname, &unilen, uni_xlate, utf8, nls);
- if (res < 0) {
- free_page(page);
- return res;
+ res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,
+ utf8, nls_io);
+ if (res < 0)
+ goto out_free;
+
+ uname = (struct nls_unicode *) page;
+ if (vfat_valid_shortname(nls_disk, uname, ulen) >= 0) {
+ res = vfat_format_name(nls_disk, uname, ulen, de->name);
+ if (!res)
+ goto out_free;
}
+ res = vfat_create_shortname(dir, nls_disk, uname, ulen, msdos_name);
+ if (res)
+ goto out_free;
*slots = unilen / 13;
for (cksum = i = 0; i < 11; i++) {
cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
}
- PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots));
+ PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots));
for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
ps->id = slot;
@@ -756,12 +846,13 @@ vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
ds[0].id |= 0x40;
de = (struct msdos_dir_entry *) ps;
- PRINTK3(("vfat_fill_long_slots 9\n"));
+ PRINTK3(("vfat_fill_slots 9\n"));
strncpy(de->name, msdos_name, MSDOS_NAME);
(*slots)++;
+out_free:
free_page(page);
- return 0;
+ return res;
}
/* We can't get "." or ".." here - VFS takes care of those cases */
@@ -769,29 +860,14 @@ vfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,
static int vfat_build_slots(struct inode *dir,const char *name,int len,
struct msdos_dir_slot *ds, int *slots)
{
- struct msdos_dir_entry *de;
- char msdos_name[MSDOS_NAME];
- int res, xlate, utf8;
- struct nls_table *nls;
+ int res, xlate;
- de = (struct msdos_dir_entry *) ds;
xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
- utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
- nls = MSDOS_SB(dir->i_sb)->nls_io;
-
*slots = 1;
res = vfat_valid_longname(name, len, xlate);
if (res < 0)
return res;
- if (vfat_valid_shortname(name, len, utf8) >= 0) {
- vfat_format_name(name, len, de->name, utf8);
- return 0;
- }
- res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
- if (res < 0)
- return res;
- return vfat_fill_long_slots(ds, name, len, msdos_name, slots, xlate,
- utf8, nls);
+ return vfat_fill_slots(dir, ds, name, len, slots, xlate);
}
static int vfat_add_entry(struct inode *dir,struct qstr* qname,