summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1997-11-20 07:15:39 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1997-11-20 07:15:39 +0000
commite8750b197ae8a8d3bdbfa4ce4d4293ccddb7dca6 (patch)
tree8c612ad9a1a9b3ba53dbb018efc126c0cb101412 /sys
parentb344d7b9ed372804095b1e0014f27e2d7cce22db (diff)
Fix for open(2) when O_TRUNC and O_??LOCK are used together. I
ran the fix by Kirk, who said it was an OK solution and pointed out two problems.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_syscalls.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index d444fea36e9..4069c76b453 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.31 1997/11/18 06:59:59 millert Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.32 1997/11/20 07:15:38 millert Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -838,9 +838,10 @@ sys_open(p, v, retval)
register struct filedesc *fdp = p->p_fd;
register struct file *fp;
register struct vnode *vp;
+ struct vattr vattr;
int flags, cmode;
struct file *nfp;
- int type, indx, error;
+ int type, indx, error, localtrunc = 0;
struct flock lf;
struct nameidata nd;
extern struct fileops vnops;
@@ -852,6 +853,10 @@ sys_open(p, v, retval)
cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
p->p_dupfd = -indx - 1; /* XXX check for fdopen */
+ if ((flags & O_TRUNC) && (flags & (O_EXLOCK | O_SHLOCK))) {
+ localtrunc = 1;
+ flags &= ~O_TRUNC; /* Must do truncate ourselves */
+ }
if ((error = vn_open(&nd, flags, cmode)) != 0) {
ffree(fp);
if ((error == ENODEV || error == ENXIO) &&
@@ -894,6 +899,18 @@ sys_open(p, v, retval)
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
fp->f_flag |= FHASLOCK;
}
+ if (localtrunc) {
+ VATTR_NULL(&vattr);
+ vattr.va_size = 0;
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
+ if (error) {
+ (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
+ ffree(fp);
+ fdp->fd_ofiles[indx] = NULL;
+ return (error);
+ }
+ }
VOP_UNLOCK(vp, 0, p);
*retval = indx;
return (0);