diff options
Diffstat (limited to 'fs')
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; @@ -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; @@ -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 = { @@ -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*) */ }; @@ -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, |