summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/sysirix.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
commit86464aed71025541805e7b1515541aee89879e33 (patch)
treee01a457a4912a8553bc65524aa3125d51f29f810 /arch/mips/kernel/sysirix.c
parent88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff)
Merge with Linux 2.2.1.
Diffstat (limited to 'arch/mips/kernel/sysirix.c')
-rw-r--r--arch/mips/kernel/sysirix.c54
1 files changed, 33 insertions, 21 deletions
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index e6c27cd52..0c4503da5 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -1,4 +1,4 @@
-/* $Id: sysirix.c,v 1.14 1999/02/01 01:28:56 ralf Exp $
+/* $Id: sysirix.c,v 1.15 1999/02/06 05:12:57 adevries Exp $
*
* sysirix.c: IRIX system call emulation.
*
@@ -2020,6 +2020,7 @@ out:
asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob)
{
struct file *file;
+ struct dentry *dentry;
struct inode *inode;
struct irix_dirent32 *lastdirent;
struct irix_dirent32_callback buf;
@@ -2031,44 +2032,55 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count
current->pid, fd, dirent, count, eob);
#endif
error = -EBADF;
- if (!(file = fget(fd)))
+ file = fget(fd);
+ if (!file)
goto out;
- /* Shouldn't it be ENOENT? */
- inode = file->f_dentry->d_inode;
- if (!inode)
- goto out_f;
-
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
- goto out_f;
+ dentry = file->f_dentry;
+ if (!dentry)
+ goto out_putf;
- error = -EFAULT;
- if(!access_ok(VERIFY_WRITE, dirent, count) ||
- !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
- goto out_f;
+ inode = dentry->d_inode;
+ if (!inode)
+ goto out_putf;
- __put_user(0, eob);
buf.current_dir = (struct irix_dirent32 *) dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out_putf;
+
+ /*
+ * Get the inode's semaphore to prevent changes
+ * to the directory while we read it.
+ */
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, irix_filldir32);
+ up(&inode->i_sem);
if (error < 0)
- goto out_f;
+ goto out_putf;
+ error = buf.error;
lastdirent = buf.previous;
- if (!lastdirent) {
- error = buf.error;
- goto out_f;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
+ }
+
+ if (put_user(0, eob) < 0) {
+ error = EFAULT;
+ goto out_putf;
}
- lastdirent->d_off = (u32) file->f_pos;
+
+
#ifdef DEBUG_GETDENTS
printk("eob=%d returning %d\n", *eob, count - buf.count);
#endif
error = count - buf.count;
-out_f:
+out_putf:
fput(file);
out:
unlock_kernel();