Bounds check on ecc correction
[yaffs2.git] / yaffs_fs.c
index f28a6e8dac80b046dd4782627a6ca8dddc46f380..d90e2915f71655d6163ff8f4de0e13d3e022b8bb 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 const char *yaffs_fs_c_version =
-    "$Id: yaffs_fs.c,v 1.48 2006-05-21 09:39:12 charles Exp $";
+    "$Id: yaffs_fs.c,v 1.51 2006-07-25 21:03:22 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 #include <linux/config.h>
@@ -66,6 +66,11 @@ extern const char *yaffs_guts_c_version;
 #define        BDEVNAME_SIZE           0
 #define        yaffs_devname(sb, buf)  kdevname(sb->s_dev)
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
+/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
+#define __user
+#endif
+
 #endif
 
 #include <asm/uaccess.h>
@@ -646,6 +651,40 @@ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
 static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
 {
        if (inode && obj) {
+
+
+               /* Check mode against the variant type and attempt to repair if broken. */
+               __u32 mode = obj->yst_mode;
+               switch( obj->variantType ){
+               case YAFFS_OBJECT_TYPE_FILE :
+                       if( ! S_ISREG(mode) ){
+                               obj->yst_mode &= ~S_IFMT;
+                               obj->yst_mode |= S_IFREG;
+                       }
+                       break;
+               case YAFFS_OBJECT_TYPE_SYMLINK :
+                       if( ! S_ISLNK(mode) ){
+                               obj->yst_mode &= ~S_IFMT;
+                               obj->yst_mode |= S_IFLNK;
+                       }
+                       break;
+               case YAFFS_OBJECT_TYPE_DIRECTORY :
+                       if( ! S_ISDIR(mode) ){
+                               obj->yst_mode &= ~S_IFMT;
+                               obj->yst_mode |= S_IFDIR;
+                       }
+                       break;
+               case YAFFS_OBJECT_TYPE_UNKNOWN :
+               case YAFFS_OBJECT_TYPE_HARDLINK :
+               case YAFFS_OBJECT_TYPE_SPECIAL :
+               default:
+                       /* TODO? */
+                       break;
+               }
+
                inode->i_ino = obj->objectId;
                inode->i_mode = obj->yst_mode;
                inode->i_uid = obj->yst_uid;
@@ -910,6 +949,9 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
        int error = -ENOSPC;
        uid_t uid = current->fsuid;
        gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+       
+       if((dir->i_mode & S_ISGID) && S_ISDIR(mode))
+               mode |= S_ISGID;
 
        if (parent) {
                T(YAFFS_TRACE_OS,
@@ -1456,6 +1498,14 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,
            T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
            yaffsVersion = 2;
        }       
+       
+       /* Added NCB 26/5/2006 for completeness */
+       if (yaffsVersion == 2 && 
+           mtd->oobblock == 512) {
+           T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
+           yaffsVersion = 1;
+       }       
+
 #endif
 
        if (yaffsVersion == 2) {