patch-2.1.50 linux/fs/msdos/namei.c

Next file: linux/fs/namei.c
Previous file: linux/fs/inode.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.49/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
@@ -63,24 +63,6 @@
 	NULL
 };
 
-struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
-{
-	struct super_block *res;
-
-	MOD_INC_USE_COUNT;
-
-	sb->s_op = &msdos_sops;
-	res =  fat_read_super(sb, data, silent);
-	if (res == NULL)
-		MOD_DEC_USE_COUNT;
-
-	return res;
-}
-
-
-
-
-
 /***** Formats an MS-DOS file name. Rejects invalid names. */
 static int msdos_format_name(char conv,const char *name,int len,
 	char *res,int dot_dirs,char dotsOK)
@@ -190,6 +172,73 @@
 	return fat_scan(dir,msdos_name,bh,de,ino,scantype);
 }
 
+
+static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
+{
+	unsigned long hash;
+	char msdos_name[MSDOS_NAME];
+	int error;
+	int i;
+	struct fat_mount_options *options = 
+		& (MSDOS_SB(dentry->d_inode->i_sb)->options);
+	
+	error = msdos_format_name(options->name_check,
+				  qstr->name, qstr->len, msdos_name,1,
+				  options->dotsOK);
+	if(error)
+		return error;
+	hash = init_name_hash();
+	for(i=0; i< MSDOS_NAME; i++)
+		hash = partial_name_hash(msdos_name[i], hash);
+	qstr->hash = end_name_hash(hash);
+	return 0;
+}
+
+
+static int msdos_cmp(struct dentry *dentry,       
+		     struct qstr *a, struct qstr *b)
+{
+	char a_msdos_name[MSDOS_NAME],b_msdos_name[MSDOS_NAME];
+	int error;
+	struct fat_mount_options *options = 
+		& (MSDOS_SB(dentry->d_inode->i_sb)->options);
+
+	error = msdos_format_name(options->name_check,
+				  a->name, a->len, a_msdos_name,1,
+				  options->dotsOK);
+	if(error)
+		return error;
+	error = msdos_format_name(options->name_check,
+				  b->name, b->len, b_msdos_name,1,
+				  options->dotsOK);
+	if(error)
+		return error;
+
+	return memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
+}
+
+
+static struct dentry_operations msdos_dentry_operations = {
+	0, 		/* d_revalidate */
+	msdos_hash,
+	msdos_cmp
+};
+
+struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
+{
+	struct super_block *res;
+
+	MOD_INC_USE_COUNT;
+
+	sb->s_op = &msdos_sops;
+	res =  fat_read_super(sb, data, silent);
+	if (res == NULL)
+		MOD_DEC_USE_COUNT;
+	sb->s_root->d_op = &msdos_dentry_operations;
+	return res;
+}
+
+
 /***** Get inode using directory and name */
 int msdos_lookup(struct inode *dir,struct dentry *dentry)
 {
@@ -201,10 +250,20 @@
 	
 	PRINTK (("msdos_lookup\n"));
 
-	if ((res = msdos_find(dir,dentry->d_name.name,dentry->d_name.len,&bh,&de,&ino)) < 0) {
+	dentry->d_op = &msdos_dentry_operations;
+
+	if(!dir) {
 		d_add(dentry, NULL);
 		return 0;
 	}
+
+	if ((res = msdos_find(dir,dentry->d_name.name,dentry->d_name.len,&bh,&de,&ino)) < 0) {
+		if(res == -ENOENT) {
+			d_add(dentry, NULL);
+			res = 0;
+		}
+		return res;
+	}
 	PRINTK (("msdos_lookup 4\n"));
 	if (bh)
 		fat_brelse(sb, bh);
@@ -229,6 +288,7 @@
 		iput(inode);
 		if (!(inode = iget(next->i_sb,next->i_ino))) {
 			fat_fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
+			d_add(dentry, NULL);
 			return -ENOENT;
 		}
 	}
@@ -248,6 +308,9 @@
 	struct msdos_dir_entry *de;
 	int res,ino;
 
+	if(!dir)
+		return -ENOENT;
+
 	*result = NULL;
 	if ((res = fat_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) {
 		if (res != -ENOENT) return res;
@@ -748,7 +811,10 @@
 	NULL,			/* writepage */
 	fat_bmap,		/* bmap */
 	NULL,			/* truncate */
-	NULL			/* permission */
+	NULL,			/* permission */
+	NULL,                   /* smap */
+	NULL,                   /* updatepage */
+	NULL,                   /* revalidate */
 };
 
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov