summaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c46
1 files changed, 19 insertions, 27 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 12f7cf489..99a1638e1 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -4,8 +4,6 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*/
-#include <asm/segment.h>
-
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -13,25 +11,25 @@
#include <linux/fcntl.h>
#include <linux/string.h>
-extern int fcntl_getlk(unsigned int, struct flock *);
-extern int fcntl_setlk(unsigned int, unsigned int, struct flock *);
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
-static int dupfd(unsigned int fd, unsigned int arg)
+static inline int dupfd(unsigned int fd, unsigned int arg)
{
- if (fd >= NR_OPEN || !current->files->fd[fd])
+ struct files_struct * files = current->files;
+
+ if (fd >= NR_OPEN || !files->fd[fd])
return -EBADF;
if (arg >= NR_OPEN)
return -EINVAL;
- while (arg < NR_OPEN)
- if (current->files->fd[arg])
- arg++;
- else
- break;
- if (arg >= NR_OPEN)
+ arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
+ if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
return -EMFILE;
- FD_CLR(arg, &current->files->close_on_exec);
- (current->files->fd[arg] = current->files->fd[fd])->f_count++;
+ FD_SET(arg, &files->open_fds);
+ FD_CLR(arg, &files->close_on_exec);
+ (files->fd[arg] = files->fd[fd])->f_count++;
return arg;
}
@@ -41,19 +39,9 @@ asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
return -EBADF;
if (newfd == oldfd)
return newfd;
- /*
- * errno's for dup2() are slightly different than for fcntl(F_DUPFD)
- * for historical reasons.
- */
- if (newfd > NR_OPEN) /* historical botch - should have been >= */
- return -EBADF; /* dupfd() would return -EINVAL */
-#if 1
- if (newfd == NR_OPEN)
- return -EBADF; /* dupfd() does return -EINVAL and that may
- * even be the standard! But that is too
- * weird for now.
- */
-#endif
+ if (newfd >= NR_OPEN)
+ return -EBADF; /* following POSIX.1 6.2.1 */
+
sys_close(newfd);
return dupfd(oldfd,newfd);
}
@@ -97,6 +85,10 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
filp->f_op->fasync)
filp->f_op->fasync(filp->f_inode, filp, 0);
+ /* required for SunOS emulation */
+ if (O_NONBLOCK != O_NDELAY)
+ if (arg & O_NDELAY)
+ arg |= O_NONBLOCK;
filp->f_flags &= ~(O_APPEND | O_NONBLOCK | FASYNC);
filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
FASYNC);