summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_extattr.c
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2000-07-04 03:34:11 +0000
committermckusick <mckusick@FreeBSD.org>2000-07-04 03:34:11 +0000
commit040e64cd9770955113ddffda73fff7b62dd5959b (patch)
tree4d2f06b02c643384c981cf2399da8d136ee8a568 /sys/kern/vfs_extattr.c
parent806786489f486969418422381048f277d86e0a20 (diff)
downloadFreeBSD-src-040e64cd9770955113ddffda73fff7b62dd5959b.zip
FreeBSD-src-040e64cd9770955113ddffda73fff7b62dd5959b.tar.gz
Move the truncation code out of vn_open and into the open system call
after the acquisition of any advisory locks. This fix corrects a case in which a process tries to open a file with a non-blocking exclusive lock. Even if it fails to get the lock it would still truncate the file even though its open failed. With this change, the truncation is done only after the lock is successfully acquired. Obtained from: BSD/OS
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r--sys/kern/vfs_extattr.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 37dc81d..65a297ca 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -968,9 +968,10 @@ open(p, uap)
syscallarg(int) mode;
} */ *uap;
{
- register struct filedesc *fdp = p->p_fd;
- register struct file *fp;
- register struct vnode *vp;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct vnode *vp;
+ struct vattr vat;
int cmode, flags, oflags;
struct file *nfp;
int type, indx, error;
@@ -988,7 +989,7 @@ open(p, uap)
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 */
- error = vn_open(&nd, flags, cmode);
+ error = vn_open(&nd, &flags, cmode);
if (error) {
ffree(fp);
if ((error == ENODEV || error == ENXIO) &&
@@ -1011,6 +1012,7 @@ open(p, uap)
fp->f_flag = flags & FMASK;
fp->f_ops = &vnops;
fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE);
+ VOP_UNLOCK(vp, 0, p);
if (flags & (O_EXLOCK | O_SHLOCK)) {
lf.l_whence = SEEK_SET;
lf.l_start = 0;
@@ -1022,22 +1024,30 @@ open(p, uap)
type = F_FLOCK;
if ((flags & FNONBLOCK) == 0)
type |= F_WAIT;
- VOP_UNLOCK(vp, 0, p);
- if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
- (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
- ffree(fp);
- fdp->fd_ofiles[indx] = NULL;
- return (error);
- }
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0)
+ goto bad;
fp->f_flag |= FHASLOCK;
}
+ if (flags & O_TRUNC) {
+ VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
+ VATTR_NULL(&vat);
+ vat.va_size = 0;
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
+ error = VOP_SETATTR(vp, &vat, p->p_ucred, p);
+ VOP_UNLOCK(vp, 0, p);
+ if (error)
+ goto bad;
+ }
/* assert that vn_open created a backing object if one is needed */
KASSERT(!vn_canvmio(vp) || vp->v_object != NULL,
("open: vmio vnode has no backing object after vn_open"));
- VOP_UNLOCK(vp, 0, p);
p->p_retval[0] = indx;
return (0);
+bad:
+ (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
+ ffree(fp);
+ fdp->fd_ofiles[indx] = NULL;
+ return (error);
}
#ifdef COMPAT_43
OpenPOWER on IntegriCloud