summaryrefslogtreecommitdiffstats
path: root/fs/fcntl.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-07-20 14:56:40 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-07-20 14:56:40 +0000
commite308faf24f68e262d92d294a01ddca7a17e76762 (patch)
tree22c47cb315811834861f013067878ff664e95abd /fs/fcntl.c
parent30c6397ce63178fcb3e7963ac247f0a03132aca9 (diff)
Sync with Linux 2.1.46.
Diffstat (limited to 'fs/fcntl.c')
-rw-r--r--fs/fcntl.c55
1 files changed, 31 insertions, 24 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 6418a5d83..57eef2530 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -67,6 +67,34 @@ asmlinkage int sys_dup(unsigned int fildes)
return ret;
}
+#define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC)
+
+static int setfl(struct file * filp, unsigned long arg)
+{
+ struct inode * inode = filp->f_dentry->d_inode;
+
+ /*
+ * In the case of an append-only file, O_APPEND
+ * cannot be cleared
+ */
+ if (!(arg & O_APPEND) && IS_APPEND(inode))
+ return -EPERM;
+
+ /* Did FASYNC state change? */
+ if ((arg ^ filp->f_flags) & FASYNC) {
+ if (filp->f_op->fasync)
+ filp->f_op->fasync(inode, filp, (arg & FASYNC) != 0);
+ }
+
+ /* required for strict SunOS emulation */
+ if (O_NONBLOCK != O_NDELAY)
+ if (arg & O_NDELAY)
+ arg |= O_NONBLOCK;
+
+ filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK);
+ return 0;
+}
+
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
@@ -95,28 +123,7 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
err = filp->f_flags;
break;
case F_SETFL:
- /*
- * In the case of an append-only file, O_APPEND
- * cannot be cleared
- */
- err = -EPERM;
- if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND))
- break;
- err = 0;
- if ((arg & FASYNC) && !(filp->f_flags & FASYNC) &&
- filp->f_op->fasync)
- filp->f_op->fasync(filp->f_inode, filp, 1);
- if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
- filp->f_op->fasync)
- filp->f_op->fasync(filp->f_inode, filp, 0);
- /* required for strict SunOS emulation */
- if (O_NONBLOCK != O_NDELAY)
- if (arg & O_NDELAY)
- arg |= O_NONBLOCK;
- filp->f_flags &= ~(O_APPEND | O_NONBLOCK |
- O_NDELAY | FASYNC);
- filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
- O_NDELAY | FASYNC);
+ err = setfl(filp, arg);
break;
case F_GETLK:
err = fcntl_getlk(fd, (struct flock *) arg);
@@ -186,12 +193,12 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
fasync_ok:
err = 0;
filp->f_owner = arg;
- if (S_ISSOCK (filp->f_inode->i_mode))
+ if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, F_SETOWN, arg);
break;
default:
/* sockets need a few special fcntls. */
- if (S_ISSOCK (filp->f_inode->i_mode))
+ if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, cmd, arg);
else
err = -EINVAL;