diff options
author | dean gaudet <dean@arctic.org> | 2006-02-03 03:04:30 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-03 08:32:07 -0800 |
commit | 7d95c8f27d9be65bf160f1edaf653d33dfceb58c (patch) | |
tree | 2e232ef2fccb1e6c81616bd9f3a56a0676549a8a | |
parent | 8b3e09e19932835fb77c63aaf3b1af6117e78871 (diff) |
[PATCH] fcntl F_SETFL and read-only IS_APPEND files
There is code in setfl() which attempts to preserve the O_APPEND flag on
IS_APPEND files... however IS_APPEND files could also be opened O_RDONLY
and in that case setfl() should not require O_APPEND...
coreutils 5.93 tail -f attempts to set O_NONBLOCK even on regular files...
unfortunately if you try this on an append-only log file the result is
this:
fcntl64(3, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE)
fcntl64(3, F_SETFL, O_RDONLY|O_NONBLOCK|O_LARGEFILE) = -1 EPERM (Operation not permitted)
I offer up the patch below as one way of fixing the problem... i've tested
it fixes the problem with tail -f but haven't really tested beyond that.
(I also reported the coreutils bug upstream... it shouldn't fail imho...
<https://savannah.gnu.org/bugs/index.php?func=detailitem&item_id=15473>)
Signed-off-by: dean gaudet <dean@arctic.org>
Cc: Al Viro <viro@ftp.linux.org.uk>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/fcntl.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index 5f96786d1c7..dc4a7007f4e 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -208,8 +208,11 @@ static int setfl(int fd, struct file * filp, unsigned long arg) struct inode * inode = filp->f_dentry->d_inode; int error = 0; - /* O_APPEND cannot be cleared if the file is marked as append-only */ - if (!(arg & O_APPEND) && IS_APPEND(inode)) + /* + * O_APPEND cannot be cleared if the file is marked as append-only + * and the file is open for write. + */ + if (((arg ^ filp->f_flags) & O_APPEND) && IS_APPEND(inode)) return -EPERM; /* O_NOATIME can only be set by the owner or superuser */ |