patch-2.1.44 linux/fs/readdir.c

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

diff -u --recursive --new-file v2.1.43/linux/fs/readdir.c linux/fs/readdir.c
@@ -1,35 +1,20 @@
 /*
- *  fs/readdir.c
+ *  linux/fs/readdir.c
  *
  *  Copyright (C) 1995  Linus Torvalds
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#ifdef CONFIG_TRANS_NAMES
-#include <linux/nametrans.h>
-#endif
-#include <linux/dalloc.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
-/* [T.Schoebel-Theuer] I am assuming that directories never get too large.
- * The problem is that getdents() delivers d_offset's that can be used
- * for lseek() by the user, so I must encode the status information for
- * name translation and dcache baskets in the offset.
- * Note that the linux man page getdents(2) does not mention that
- * the d_offset is fs-specific and can be used for lseek().
- */
-#define BASKET_BIT (1<<30) /* 31 is already used by affs */
-#define TRANS_BIT  (1<<29)
-
 /*
  * Traditional linux readdir() handling..
  *
@@ -50,9 +35,6 @@
 
 struct readdir_callback {
 	struct old_linux_dirent * dirent;
-	struct file * file;
-	int translate;
-	off_t oldoffset;
 	int count;
 };
 
@@ -65,26 +47,11 @@
 		return -EINVAL;
 	buf->count++;
 	dirent = buf->dirent;
-	copy_to_user(dirent->d_name, name, namlen);
-	put_user(0, dirent->d_name + namlen);
-#ifdef CONFIG_TRANS_NAMES
-	if(!buf->translate) {
-		char * cut;
-#ifdef CONFIG_TRANS_RESTRICT
-		struct inode * inode = buf->file->f_inode;
-		cut = testname(inode && inode->i_gid != CONFIG_TRANS_GID, dirent->d_name);
-#else
-		cut = testname(1, dirent->d_name);
-#endif
-		if(cut) {
-			put_user(0, cut);
-			buf->translate = 1;
-		}
-	}
-#endif
 	put_user(ino, &dirent->d_ino);
 	put_user(offset, &dirent->d_offset);
 	put_user(namlen, &dirent->d_namlen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
 	return 0;
 }
 
@@ -93,7 +60,6 @@
 	int error = -EBADF;
 	struct file * file;
 	struct readdir_callback buf;
-	off_t oldpos;
 
 	lock_kernel();
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
@@ -104,21 +70,11 @@
 	error = verify_area(VERIFY_WRITE, dirent, sizeof(struct old_linux_dirent));
 	if (error)
 		goto out;
-	oldpos = file->f_pos;
-	buf.file = file;
-	buf.dirent = dirent;
 	buf.count = 0;
-	buf.translate = 0;
-	if(file->f_pos & TRANS_BIT) {
-		file->f_pos &= ~TRANS_BIT;
-		buf.translate = 1;
-	}
+	buf.dirent = dirent;
 	error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir);
 	if (error < 0)
 		goto out;
-	if(buf.translate) {
-		file->f_pos = oldpos | TRANS_BIT;
-	}
 	error = buf.count;
 out:
 	unlock_kernel();
@@ -139,11 +95,8 @@
 struct getdents_callback {
 	struct linux_dirent * current_dir;
 	struct linux_dirent * previous;
-	struct file * file;
 	int count;
-        int error;
-        int restricted;
-	int do_preload;
+	int error;
 };
 
 static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
@@ -152,51 +105,18 @@
 	struct getdents_callback * buf = (struct getdents_callback *) __buf;
 	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
 
-	/* Do not touch buf->error any more if everything is ok! */
+	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
-		return 	(buf->error = -EINVAL);
-#ifdef CONFIG_DCACHE_PRELOAD
-	if(buf->do_preload && (name[0] != '.' || namlen > 2)) {
-		struct qstr qname = { name, namlen };
-		struct inode * dir = buf->file->f_inode;
-		d_entry_preliminary(dir->i_dentry, &qname, ino);
-	}
-#endif
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent)
+		put_user(offset, &dirent->d_off);
 	dirent = buf->current_dir;
-	copy_to_user(dirent->d_name, name, namlen);
-	put_user(0, dirent->d_name + namlen);
-#ifdef CONFIG_TRANS_NAMES
-	{
-		char * cut;
-#ifdef CONFIG_TRANS_RESTRICT
-		cut = testname(buf->restricted, dirent->d_name);
-#else
-		cut = testname(1, dirent->d_name);
-#endif
-		if(cut) {
-			int newlen = (int)cut - (int)dirent->d_name;
-			int newreclen = ROUND_UP(NAME_OFFSET(dirent) + newlen + 1);
-			/* Either both must fit or none. This way we need
-			 * no status information in f_pos */
-			if (reclen+newlen > buf->count)
-				return -EINVAL;
-			put_user(0, cut);
-			put_user(ino, &dirent->d_ino);
-			put_user(newreclen, &dirent->d_reclen);
-			put_user(offset, &dirent->d_off);
-			((char *) dirent) += newreclen;
-			buf->count -= newreclen;
-			put_user(offset, &dirent->d_off);
-			copy_to_user(dirent->d_name, name, namlen);
-			put_user(0, dirent->d_name + namlen);
-		}
-	}
-#endif
+	buf->previous = dirent;
 	put_user(ino, &dirent->d_ino);
 	put_user(reclen, &dirent->d_reclen);
-	if (buf->previous)
-		put_user(buf->file->f_pos, &buf->previous->d_off);
-	buf->previous = dirent;
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
 	((char *) dirent) += reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
@@ -206,6 +126,7 @@
 asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count)
 {
 	struct file * file;
+	struct linux_dirent * lastdirent;
 	struct getdents_callback buf;
 	int error = -EBADF;
 
@@ -218,72 +139,18 @@
 	error = verify_area(VERIFY_WRITE, dirent, count);
 	if (error)
 		goto out;
-	buf.file = file;
 	buf.current_dir = (struct linux_dirent *) dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
-	buf.restricted = 0;
-#ifdef CONFIG_TRANS_RESTRICT
-	buf.restricted = file->f_inode && file->f_inode->i_gid != CONFIG_TRANS_GID;
-#endif
-	buf.do_preload = 0;
-#ifdef CONFIG_DCACHE_PRELOAD
-	if(file->f_inode && file->f_inode->i_dentry &&
-	   !(file->f_inode->i_sb->s_type->fs_flags & (FS_NO_DCACHE|FS_NO_PRELIM)) &&
-	   !(file->f_inode->i_dentry->d_flag & D_PRELOADED))
-		buf.do_preload = 1;
-#endif
-	
-	if(!(file->f_pos & BASKET_BIT)) {
-		int oldcount;
-		do {
-			oldcount = buf.count;
-			error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
-			if (error < 0)
-				goto out;
-		} while(!buf.error && buf.count != oldcount);
-	}
-	if(!buf.error) {
-		int nr = 0;
-		struct dentry * list = file->f_inode ?
-			d_basket(file->f_inode->i_dentry) : NULL;
-		struct dentry * ptr = list;
-#ifdef CONFIG_DCACHE_PRELOAD
-		if(buf.do_preload) {
-			buf.do_preload = 0;
-			file->f_inode->i_dentry->d_flag |= D_PRELOADED;
-		}
-#endif
-		if(ptr) {
-			if(!(file->f_pos & BASKET_BIT))
-				file->f_pos = BASKET_BIT;
-			do {
-				struct dentry * next = ptr->d_basket_next;
-				struct inode * inode;
-				/* vfs_locks() are missing here */
-				inode = d_inode(&ptr);
-				if(inode) {
-					nr++;
-					if(nr > (file->f_pos & ~BASKET_BIT)) {
-						int err = filldir(&buf, ptr->d_name,
-								  ptr->d_len,
-								  file->f_pos,
-								  inode->i_ino);
-						if(err)
-							break;
-						file->f_pos++;
-					}
-					iput(inode);
-				}
-				ptr = next;
-			} while(ptr != list);
-		}
-	}
-	if (!buf.previous) {
+	error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
+	if (error < 0)
+		goto out;
+	lastdirent = buf.previous;
+	if (!lastdirent) {
 		error = buf.error;
 	} else {
-		put_user(file->f_pos, &buf.previous->d_off);
+		put_user(file->f_pos, &lastdirent->d_off);
 		error = count - buf.count;
 	}
 out:

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