summaryrefslogtreecommitdiffstats
path: root/fs/fat
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
commitdb7d4daea91e105e3859cf461d7e53b9b77454b2 (patch)
tree9bb65b95440af09e8aca63abe56970dd3360cc57 /fs/fat
parent9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff)
Merge with Linux 2.2.8.
Diffstat (limited to 'fs/fat')
-rw-r--r--fs/fat/cvf.c31
-rw-r--r--fs/fat/dir.c23
-rw-r--r--fs/fat/fatfs_syms.c1
-rw-r--r--fs/fat/file.c4
-rw-r--r--fs/fat/inode.c22
-rw-r--r--fs/fat/misc.c6
-rw-r--r--fs/fat/mmap.c2
7 files changed, 72 insertions, 17 deletions
diff --git a/fs/fat/cvf.c b/fs/fat/cvf.c
index 62b70b160..9dd70f8c5 100644
--- a/fs/fat/cvf.c
+++ b/fs/fat/cvf.c
@@ -1,8 +1,11 @@
-/*
+/*
* CVF extensions for fat-based filesystems
*
* written 1997,1998 by Frank Gockel <gockel@sent13.uni-duisburg.de>
*
+ * please do not remove the next line, dmsdos needs it for verifying patches
+ * CVF-FAT-VERSION-ID: 1.2.0
+ *
*/
#include<linux/sched.h>
@@ -11,6 +14,10 @@
#include<linux/msdos_fs_sb.h>
#include<linux/string.h>
#include<linux/fat_cvf.h>
+#include<linux/config.h>
+#ifdef CONFIG_KMOD
+#include<linux/kmod.h>
+#endif
#define MAX_CVF_FORMATS 3
@@ -95,6 +102,24 @@ int detect_cvf(struct super_block*sb,char*force)
int found_i=-1;
if(force)
+ if(strcmp(force,"autoload")==0)
+ {
+#ifdef CONFIG_KMOD
+ request_module("cvf_autoload");
+ force=NULL;
+#else
+ printk("cannot autoload CVF modules: kmod support is not compiled into kernel\n");
+ return -1;
+#endif
+ }
+
+#ifdef CONFIG_KMOD
+ if(force)
+ if(*force)
+ request_module(force);
+#endif
+
+ if(force)
{ if(*force)
{ for(i=0;i<MAX_CVF_FORMATS;++i)
{ if(cvf_formats[i])
@@ -102,6 +127,8 @@ int detect_cvf(struct super_block*sb,char*force)
return i;
}
}
+ printk("CVF format %s unknown (module not loaded?)\n",force);
+ return -1;
}
}
@@ -115,6 +142,6 @@ int detect_cvf(struct super_block*sb,char*force)
}
if(found==1)return found_i;
- if(found>1)printk("CVF detection ambiguous, use cvf_format=xxx option\n");
+ if(found>1)printk("CVF detection ambiguous, please use cvf_format=xxx option\n");
return -1;
}
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 1c44247a0..b6d6fb405 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -9,6 +9,7 @@
*
* VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu>
* Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk>
+ * Plugged buffer overrun in readdir(). AV
*/
#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
@@ -59,6 +60,7 @@ struct file_operations fat_dir_operations = {
* 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.
+ * Ahem... Stack smashing in ring 0 isn't fun. Fixed.
*/
static int
uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate,
@@ -93,6 +95,11 @@ uni16_to_x8(unsigned char *ascii, unsigned char *uni, int uni_xlate,
*op++ = '?';
}
}
+ /* We have some slack there, so it's OK */
+ if (op>ascii+256) {
+ op = ascii + 256;
+ break;
+ }
}
*op = 0;
return (op - ascii);
@@ -138,8 +145,6 @@ int fat_readdirx(
unsigned char *unicode = NULL;
struct nls_table *nls = MSDOS_SB(sb)->nls_io;
- if (!inode || !S_ISDIR(inode->i_mode))
- return -EBADF;
/* Fake . and .. for the root directory. */
if (inode->i_ino == MSDOS_ROOT_INO) {
while (oldpos < 2) {
@@ -186,9 +191,17 @@ int fat_readdirx(
id = ds->id;
if (id & 0x40) {
slots = id & ~0x40;
- long_slots = slots;
- is_long = 1;
- alias_checksum = ds->alias_checksum;
+ /*
+ * Dirty, but not dirtier than the original,
+ * and plugs the hole.
+ */
+ if (slots > 20)
+ slots = 0;
+ else {
+ long_slots = slots;
+ is_long = 1;
+ alias_checksum = ds->alias_checksum;
+ }
}
get_new_entry = 1;
diff --git a/fs/fat/fatfs_syms.c b/fs/fat/fatfs_syms.c
index f57db8bf3..838c679d4 100644
--- a/fs/fat/fatfs_syms.c
+++ b/fs/fat/fatfs_syms.c
@@ -54,6 +54,7 @@ EXPORT_SYMBOL(lock_fat);
EXPORT_SYMBOL(unlock_fat);
EXPORT_SYMBOL(fat_dir_ioctl);
EXPORT_SYMBOL(fat_readpage);
+EXPORT_SYMBOL(fat_is_binary);
int init_fat_fs(void)
{
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 0ff5f187f..7c9518181 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -456,6 +456,10 @@ void fat_truncate(struct inode *inode)
/* Why no return value? Surely the disk could fail... */
if (IS_IMMUTABLE(inode))
return /* -EPERM */;
+ if(inode->i_sb->s_flags&MS_RDONLY) {
+ printk("FAT: fat_truncate called though fs is read-only, uhh...\n");
+ return /* -EROFS */;
+ }
cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
(void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index e018eb880..339bcb6f6 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -3,6 +3,10 @@
*
* Written 1992,1993 by Werner Almesberger
* VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner
+ *
+ * Fixes:
+ *
+ * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0
*/
#include <linux/version.h>
@@ -328,7 +332,6 @@ fat_read_super(struct super_block *sb, void *data, int silent)
fat_brelse (sb, bh);
goto out_no_bread;
}
- set_blocksize(sb->s_dev, blksize);
/*
* The DOS3 partition size limit is *not* 32M as many people think.
@@ -362,8 +365,16 @@ fat_read_super(struct super_block *sb, void *data, int silent)
fat32 = 1;
MSDOS_SB(sb)->fat_length= CF_LE_W(b->fat32_length)*sector_mult;
MSDOS_SB(sb)->root_cluster = CF_LE_L(b->root_cluster);
- MSDOS_SB(sb)->fsinfo_offset =
- CF_LE_W(b->info_sector) * logical_sector_size + 0x1e0;
+
+ /* MC - if info_sector is 0, don't multiply by 0 */
+ if(CF_LE_W(b->info_sector) == 0) {
+ MSDOS_SB(sb)->fsinfo_offset =
+ logical_sector_size + 0x1e0;
+ } else {
+ MSDOS_SB(sb)->fsinfo_offset =
+ (CF_LE_W(b->info_sector) * logical_sector_size)
+ + 0x1e0;
+ }
if (MSDOS_SB(sb)->fsinfo_offset + sizeof(struct fat_boot_fsinfo) > sb->s_blocksize) {
printk("fat_read_super: Bad fsinfo_offset\n");
fat_brelse(sb, bh);
@@ -411,6 +422,7 @@ fat_read_super(struct super_block *sb, void *data, int silent)
|| !b->secs_track || !b->heads;
}
fat_brelse(sb, bh);
+ set_blocksize(sb->s_dev, blksize);
/*
This must be done after the brelse because the bh is a dummy
allocated by fat_bread (see buffer.c)
@@ -691,8 +703,8 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
if(raw_entry->attr & ATTR_SYS)
if (MSDOS_SB(sb)->options.sys_immutable)
inode->i_flags |= S_IMMUTABLE;
- MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(sb)->options.conversion,
- raw_entry->ext);
+ MSDOS_I(inode)->i_binary =
+ fat_is_binary(MSDOS_SB(sb)->options.conversion, raw_entry->ext);
MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
/* this is as close to the truth as we can get ... */
inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index b398a0bbd..1dfddd3c7 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -51,11 +51,11 @@ void fat_fs_panic(struct super_block *s,const char *msg)
/*
- * is_binary selects optional text conversion based on the conversion mode and
- * the extension part of the file name.
+ * fat_is_binary selects optional text conversion based on the conversion mode
+ * and the extension part of the file name.
*/
-int is_binary(char conversion,char *extension)
+int fat_is_binary(char conversion,char *extension)
{
char *walk;
diff --git a/fs/fat/mmap.c b/fs/fat/mmap.c
index 4cda79196..0494ad013 100644
--- a/fs/fat/mmap.c
+++ b/fs/fat/mmap.c
@@ -113,8 +113,6 @@ int fat_mmap(struct file * file, struct vm_area_struct * vma)
mark_inode_dirty(inode);
}
- vma->vm_file = file;
- file->f_count++;
vma->vm_ops = &fat_file_mmap;
return 0;
}