X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/1c15e88899094343f75aeba04122cd96a96b428e..af359dea2e5ab3e937b62107ecd6a51d78189ed7:/usr/src/sys/nfs/nfs_serv.c diff --git a/usr/src/sys/nfs/nfs_serv.c b/usr/src/sys/nfs/nfs_serv.c index a9d58ce110..a83dfe9b38 100644 --- a/usr/src/sys/nfs/nfs_serv.c +++ b/usr/src/sys/nfs/nfs_serv.c @@ -5,22 +5,35 @@ * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * - * Redistribution is only permitted until one year after the first shipment - * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and - * binary forms are permitted provided that: (1) source distributions retain - * this entire copyright notice and comment, and (2) distributions including - * binaries display the following acknowledgement: This product includes - * software developed by the University of California, Berkeley and its - * contributors'' in the documentation or other materials provided with the - * distribution and in all advertising materials mentioning features or use - * of this software. Neither the name of the University nor the names of - * its contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * @(#)nfs_serv.c 7.27 (Berkeley) 7/26/90 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfs_serv.c 7.40 (Berkeley) 5/15/91 */ /* @@ -42,14 +55,17 @@ */ #include "param.h" -#include "user.h" +#include "proc.h" #include "file.h" +#include "namei.h" #include "vnode.h" #include "mount.h" #include "mbuf.h" -#include "errno.h" + #include "../ufs/quota.h" #include "../ufs/inode.h" +#include "../ufs/dir.h" + #include "nfsv2.h" #include "nfs.h" #include "xdr_subs.h" @@ -69,13 +85,14 @@ nfstype nfs_type[9]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, /* * nfs getattr service */ -nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { register struct nfsv2_fattr *fp; struct vattr va; @@ -83,7 +100,7 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat) struct vnode *vp; nfsv2fh_t nfh; fhandle_t *fhp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -94,7 +111,7 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat) nfsm_srvmtofh(fhp); if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) nfsm_reply(0); - error = VOP_GETATTR(vp, vap, cred); + error = VOP_GETATTR(vp, vap, cred, p); vput(vp); nfsm_reply(NFSX_FATTR); nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); @@ -105,13 +122,14 @@ nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat) /* * nfs setattr service */ -nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { struct vattr va; register struct vattr *vap = &va; @@ -120,7 +138,7 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat) struct vnode *vp; nfsv2fh_t nfh; fhandle_t *fhp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -132,7 +150,7 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat) nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) nfsm_reply(0); - if (error = nfsrv_access(vp, VWRITE, cred)) + if (error = nfsrv_access(vp, VWRITE, cred, p)) goto out; VATTR_NULL(vap); /* @@ -163,11 +181,11 @@ nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat) vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec); if (sp->sa_mtime.tv_sec != nfs_xdrneg1) fxdr_time(&sp->sa_mtime, &vap->va_mtime); - if (error = VOP_SETATTR(vp, vap, cred)) { + if (error = VOP_SETATTR(vp, vap, cred, p)) { vput(vp); nfsm_reply(0); } - error = VOP_GETATTR(vp, vap, cred); + error = VOP_GETATTR(vp, vap, cred, p); out: vput(vp); nfsm_reply(NFSX_FATTR); @@ -179,22 +197,22 @@ out: /* * nfs lookup rpc */ -nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { register struct nfsv2_fattr *fp; - struct nameidata nami; - register struct nameidata *ndp = &nami; + struct nameidata nd; struct vnode *vp; nfsv2fh_t nfh; fhandle_t *fhp; register caddr_t cp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -203,22 +221,21 @@ nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat) long len; struct vattr va, *vap = &va; - ndinit(ndp); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); - ndp->ni_cred = cred; - ndp->ni_nameiop = LOOKUP | LOCKLEAF; - if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) + nd.ni_cred = cred; + nd.ni_nameiop = LOOKUP | LOCKLEAF; + if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) nfsm_reply(0); - vp = ndp->ni_vp; + vp = nd.ni_vp; bzero((caddr_t)fhp, sizeof(nfh)); fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { vput(vp); nfsm_reply(0); } - error = VOP_GETATTR(vp, vap, cred); + error = VOP_GETATTR(vp, vap, cred, p); vput(vp); nfsm_reply(NFSX_FH+NFSX_FATTR); nfsm_srvfhtom(fhp); @@ -230,18 +247,19 @@ nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat) /* * nfs readlink service */ -nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; register struct iovec *ivp = iv; register struct mbuf *mp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -283,6 +301,7 @@ nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat) uiop->uio_resid = len; uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; + uiop->uio_procp = (struct proc *)0; if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) { m_freem(mp3); nfsm_reply(0); @@ -302,8 +321,8 @@ out: tlen = nfsm_rndup(len); nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len); } - nfsm_build(p, u_long *, NFSX_UNSIGNED); - *p = txdr_unsigned(len); + nfsm_build(tl, u_long *, NFSX_UNSIGNED); + *tl = txdr_unsigned(len); mb->m_next = mp3; nfsm_srvdone; } @@ -311,19 +330,20 @@ out: /* * nfs read service */ -nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { register struct iovec *iv; struct iovec *iv2; register struct mbuf *m; register struct nfsv2_fattr *fp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -340,12 +360,12 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat) fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); - nfsm_disect(p, u_long *, NFSX_UNSIGNED); - off = fxdr_unsigned(off_t, *p); + nfsm_disect(tl, u_long *, NFSX_UNSIGNED); + off = fxdr_unsigned(off_t, *tl); nfsm_srvstrsiz(cnt, NFS_MAXDATA); if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) nfsm_reply(0); - if (error = nfsrv_access(vp, VREAD | VEXEC, cred)) { + if (error = nfsrv_access(vp, VREAD | VEXEC, cred, p)) { vput(vp); nfsm_reply(0); } @@ -386,6 +406,7 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat) uiop->uio_resid = cnt; uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; + uiop->uio_procp = (struct proc *)0; error = VOP_READ(vp, uiop, IO_NODELOCKED, cred); off = uiop->uio_offset; FREE((caddr_t)iv2, M_TEMP); @@ -394,24 +415,23 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat) vput(vp); nfsm_reply(0); } - if (error = VOP_GETATTR(vp, vap, cred)) + if (error = VOP_GETATTR(vp, vap, cred, p)) m_freem(m3); vput(vp); nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED); nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); nfsm_srvfillattr; - if (uiop->uio_resid > 0) { - len -= uiop->uio_resid; - if (len > 0) { - tlen = nfsm_rndup(len); + len -= uiop->uio_resid; + if (len > 0) { + tlen = nfsm_rndup(len); + if (cnt != tlen || tlen != len) nfsm_adj(m3, cnt-tlen, tlen-len); - } else { - m_freem(m3); - m3 = (struct mbuf *)0; - } + } else { + m_freem(m3); + m3 = (struct mbuf *)0; } - nfsm_build(p, u_long *, NFSX_UNSIGNED); - *p = txdr_unsigned(len); + nfsm_build(tl, u_long *, NFSX_UNSIGNED); + *tl = txdr_unsigned(len); mb->m_next = m3; nfsm_srvdone; } @@ -419,12 +439,13 @@ nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat) /* * nfs write service */ -nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { register struct iovec *ivp; register struct mbuf *mp; @@ -432,7 +453,7 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat) struct iovec iv[NFS_MAXIOVEC]; struct vattr va; register struct vattr *vap = &va; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -447,10 +468,10 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat) fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); - nfsm_disect(p, u_long *, 4*NFSX_UNSIGNED); - off = fxdr_unsigned(off_t, *++p); - p += 2; - len = fxdr_unsigned(long, *p); + nfsm_disect(tl, u_long *, 4*NFSX_UNSIGNED); + off = fxdr_unsigned(off_t, *++tl); + tl += 2; + len = fxdr_unsigned(long, *tl); if (len > NFS_MAXDATA || len <= 0) { error = EBADRPC; nfsm_reply(0); @@ -469,13 +490,14 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat) } if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) nfsm_reply(0); - if (error = nfsrv_access(vp, VWRITE, cred)) { + if (error = nfsrv_access(vp, VWRITE, cred, p)) { vput(vp); nfsm_reply(0); } uiop->uio_resid = 0; uiop->uio_rw = UIO_WRITE; uiop->uio_segflg = UIO_SYSSPACE; + uiop->uio_procp = (struct proc *)0; /* * Do up to NFS_MAXIOVEC mbufs of write each iteration of the * loop until done. @@ -518,7 +540,7 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat) } off = uiop->uio_offset; } - error = VOP_GETATTR(vp, vap, cred); + error = VOP_GETATTR(vp, vap, cred, p); vput(vp); nfsm_reply(NFSX_FATTR); nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR); @@ -530,20 +552,20 @@ nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat) * nfs create service * now does a truncate to 0 length via. setattr if it already exists */ -nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { register struct nfsv2_fattr *fp; struct vattr va; register struct vattr *vap = &va; - struct nameidata nami; - register struct nameidata *ndp = &nami; + struct nameidata nd; register caddr_t cp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; long rdev; @@ -555,69 +577,85 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat) fhandle_t *fhp; long len; - ndinit(ndp); + nd.ni_nameiop = 0; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); - ndp->ni_cred = cred; - ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF; - if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) + nd.ni_cred = cred; + nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART; + if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) nfsm_reply(0); VATTR_NULL(vap); - nfsm_disect(p, u_long *, NFSX_SATTR); + nfsm_disect(tl, u_long *, NFSX_SATTR); /* * Iff doesn't exist, create it * otherwise just truncate to 0 length * should I set the mode too ?? */ - if (ndp->ni_vp == NULL) { - vap->va_type = IFTOVT(fxdr_unsigned(u_long, *p)); + if (nd.ni_vp == NULL) { + vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl)); if (vap->va_type == VNON) vap->va_type = VREG; - vap->va_mode = nfstov_mode(*p); - rdev = fxdr_unsigned(long, *(p+3)); - if (vap->va_type == VREG) { - if (error = VOP_CREATE(ndp, vap)) + vap->va_mode = nfstov_mode(*tl); + rdev = fxdr_unsigned(long, *(tl+3)); + if (vap->va_type == VREG || vap->va_type == VSOCK) { + vrele(nd.ni_startdir); + if (error = VOP_CREATE(&nd, vap, p)) nfsm_reply(0); + FREE(nd.ni_pnbuf, M_NAMEI); } else if (vap->va_type == VCHR || vap->va_type == VBLK || vap->va_type == VFIFO) { if (vap->va_type == VCHR && rdev == 0xffffffff) vap->va_type = VFIFO; if (vap->va_type == VFIFO) { #ifndef FIFO - VOP_ABORTOP(ndp); - vput(ndp->ni_dvp); + VOP_ABORTOP(&nd); + vput(nd.ni_dvp); error = ENXIO; - nfsm_reply(0); + goto out; #endif /* FIFO */ } else if (error = suser(cred, (short *)0)) { - VOP_ABORTOP(ndp); - vput(ndp->ni_dvp); - nfsm_reply(0); + VOP_ABORTOP(&nd); + vput(nd.ni_dvp); + goto out; } else vap->va_rdev = (dev_t)rdev; - if (error = VOP_MKNOD(ndp, vap, cred)) + if (error = VOP_MKNOD(&nd, vap, cred, p)) { + vrele(nd.ni_startdir); + nfsm_reply(0); + } + nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART); + nd.ni_nameiop |= LOOKUP; + if (error = lookup(&nd, p)) { + free(nd.ni_pnbuf, M_NAMEI); nfsm_reply(0); - ndp->ni_nameiop = LOOKUP | LOCKLEAF | HASBUF; - if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) + } + FREE(nd.ni_pnbuf, M_NAMEI); + if (nd.ni_more) { + vrele(nd.ni_dvp); + vput(nd.ni_vp); + VOP_ABORTOP(&nd); + error = EINVAL; nfsm_reply(0); + } } else { - VOP_ABORTOP(ndp); - vput(ndp->ni_dvp); + VOP_ABORTOP(&nd); + vput(nd.ni_dvp); error = ENXIO; - nfsm_reply(0); + goto out; } - vp = ndp->ni_vp; + vp = nd.ni_vp; } else { - vp = ndp->ni_vp; - ndp->ni_vp = NULLVP; - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == vp) - vrele(ndp->ni_dvp); + vrele(nd.ni_startdir); + free(nd.ni_pnbuf, M_NAMEI); + vp = nd.ni_vp; + if (nd.ni_dvp == vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); + vput(nd.ni_dvp); + VOP_ABORTOP(&nd); vap->va_size = 0; - if (error = VOP_SETATTR(vp, vap, cred)) { + if (error = VOP_SETATTR(vp, vap, cred, p)) { vput(vp); nfsm_reply(0); } @@ -628,7 +666,7 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat) vput(vp); nfsm_reply(0); } - error = VOP_GETATTR(vp, vap, cred); + error = VOP_GETATTR(vp, vap, cred, p); vput(vp); nfsm_reply(NFSX_FH+NFSX_FATTR); nfsm_srvfhtom(fhp); @@ -636,29 +674,36 @@ nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat) nfsm_srvfillattr; return (error); nfsmout: - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == ndp->ni_vp) - vrele(ndp->ni_dvp); + if (nd.ni_nameiop) + vrele(nd.ni_startdir); + VOP_ABORTOP(&nd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); - if (ndp->ni_vp) - vput(ndp->ni_vp); + vput(nd.ni_dvp); + if (nd.ni_vp) + vput(nd.ni_vp); return (error); + +out: + vrele(nd.ni_startdir); + free(nd.ni_pnbuf, M_NAMEI); + nfsm_reply(0); } /* * nfs remove service */ -nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { - struct nameidata nami; - register struct nameidata *ndp = &nami; - register u_long *p; + struct nameidata nd; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -669,36 +714,35 @@ nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat) fhandle_t *fhp; long len; - ndinit(ndp); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); - ndp->ni_cred = cred; - ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; - if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) + nd.ni_cred = cred; + nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; + if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) nfsm_reply(0); - vp = ndp->ni_vp; + vp = nd.ni_vp; if (vp->v_type == VDIR && (error = suser(cred, (short *)0))) goto out; /* - * Don't unlink a mounted file. + * The root of a mounted filesystem cannot be deleted. */ if (vp->v_flag & VROOT) { error = EBUSY; goto out; } if (vp->v_flag & VTEXT) - xrele(vp); /* try once to free text */ + (void) vnode_pager_uncache(vp); out: if (!error) { - error = VOP_REMOVE(ndp); + error = VOP_REMOVE(&nd, p); } else { - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == vp) - vrele(ndp->ni_dvp); + VOP_ABORTOP(&nd); + if (nd.ni_dvp == vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); + vput(nd.ni_dvp); vput(vp); } nfsm_reply(0); @@ -708,31 +752,31 @@ out: /* * nfs rename service */ -nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { - register struct nameidata *ndp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; char *cp2; struct mbuf *mb, *mreq; - struct nameidata nami, tond; + struct nameidata fromnd, tond; struct vnode *fvp, *tvp, *tdvp; nfsv2fh_t fnfh, tnfh; fhandle_t *ffhp, *tfhp; long len, len2; int rootflg = 0; - ndp = &nami; - ndinit(ndp); ffhp = &fnfh.fh_generic; tfhp = &tnfh.fh_generic; + fromnd.ni_nameiop = 0; + tond.ni_nameiop = 0; nfsm_srvmtofh(ffhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); /* @@ -741,22 +785,21 @@ nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat) */ if (cred->cr_uid == 0) rootflg++; - ndp->ni_cred = cred; - ndp->ni_nameiop = DELETE | WANTPARENT; - if (error = nfs_namei(ndp, ffhp, len, &md, &dpos)) + fromnd.ni_cred = cred; + fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART; + if (error = nfs_namei(&fromnd, ffhp, len, &md, &dpos, p)) nfsm_reply(0); - fvp = ndp->ni_vp; + fvp = fromnd.ni_vp; nfsm_srvmtofh(tfhp); nfsm_strsiz(len2, NFS_MAXNAMLEN); if (rootflg) cred->cr_uid = 0; - ndinit(&tond); - crhold(cred); tond.ni_cred = cred; - tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE; - if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos)) { - VOP_ABORTOP(ndp); - vrele(ndp->ni_dvp); + tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE + | SAVESTART; + if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos, p)) { + VOP_ABORTOP(&fromnd); + vrele(fromnd.ni_dvp); vrele(fvp); goto out1; } @@ -775,15 +818,20 @@ nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat) error = EXDEV; goto out; } - if (fvp == tdvp || fvp == tvp) + if (fvp == tdvp) error = EINVAL; + /* + * If source is the same as the destination (that is the + * same vnode with the same name in the same directory), + * then there is nothing to do. + */ + if (fvp == tvp && fromnd.ni_dvp == tdvp && + fromnd.ni_namelen == tond.ni_namelen && + !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen)) + error = -1; out: if (!error) { - VREF(ndp->ni_cdir); - VREF(tond.ni_cdir); - error = VOP_RENAME(ndp, &tond); - vrele(ndp->ni_cdir); - vrele(tond.ni_cdir); + error = VOP_RENAME(&fromnd, &tond, p); } else { VOP_ABORTOP(&tond); if (tdvp == tvp) @@ -792,34 +840,46 @@ out: vput(tdvp); if (tvp) vput(tvp); - VOP_ABORTOP(ndp); - vrele(ndp->ni_dvp); + VOP_ABORTOP(&fromnd); + vrele(fromnd.ni_dvp); vrele(fvp); } + vrele(tond.ni_startdir); + FREE(tond.ni_pnbuf, M_NAMEI); out1: - crfree(cred); + vrele(fromnd.ni_startdir); + FREE(fromnd.ni_pnbuf, M_NAMEI); nfsm_reply(0); return (error); + nfsmout: - VOP_ABORTOP(ndp); - vrele(ndp->ni_dvp); - vrele(fvp); + if (tond.ni_nameiop) { + vrele(tond.ni_startdir); + FREE(tond.ni_pnbuf, M_NAMEI); + } + if (fromnd.ni_nameiop) { + vrele(fromnd.ni_startdir); + FREE(fromnd.ni_pnbuf, M_NAMEI); + VOP_ABORTOP(&fromnd); + vrele(fromnd.ni_dvp); + vrele(fvp); + } return (error); } /* * nfs link service */ -nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { - struct nameidata nami; - register struct nameidata *ndp = &nami; - register u_long *p; + struct nameidata nd; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -830,7 +890,6 @@ nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat) fhandle_t *fhp, *dfhp; long len; - ndinit(ndp); fhp = &nfh.fh_generic; dfhp = &dnfh.fh_generic; nfsm_srvmtofh(fhp); @@ -840,29 +899,29 @@ nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat) nfsm_reply(0); if (vp->v_type == VDIR && (error = suser(cred, NULL))) goto out1; - ndp->ni_cred = cred; - ndp->ni_nameiop = CREATE | LOCKPARENT; - if (error = nfs_namei(ndp, dfhp, len, &md, &dpos)) + nd.ni_cred = cred; + nd.ni_nameiop = CREATE | LOCKPARENT; + if (error = nfs_namei(&nd, dfhp, len, &md, &dpos, p)) goto out1; - xp = ndp->ni_vp; + xp = nd.ni_vp; if (xp != NULL) { error = EEXIST; goto out; } - xp = ndp->ni_dvp; + xp = nd.ni_dvp; if (vp->v_mount != xp->v_mount) error = EXDEV; out: if (!error) { - error = VOP_LINK(vp, ndp); + error = VOP_LINK(vp, &nd, p); } else { - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == ndp->ni_vp) - vrele(ndp->ni_dvp); + VOP_ABORTOP(&nd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); - if (ndp->ni_vp) - vrele(ndp->ni_vp); + vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); } out1: vrele(vp); @@ -873,19 +932,20 @@ out1: /* * nfs symbolic link service */ -nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { struct vattr va; - struct nameidata nami; - register struct nameidata *ndp = &nami; + struct nameidata nd; register struct vattr *vap = &va; - register u_long *p; + register u_long *tl; register long t1; + struct nfsv2_sattr *sp; caddr_t bpos; struct uio io; struct iovec iv; @@ -897,13 +957,12 @@ nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat) long len, len2; pathcp = (char *)0; - ndinit(ndp); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); - ndp->ni_cred = cred; - ndp->ni_nameiop = CREATE | LOCKPARENT; - if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) + nd.ni_cred = cred; + nd.ni_nameiop = CREATE | LOCKPARENT; + if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) goto out; nfsm_strsiz(len2, NFS_MAXPATHLEN); MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); @@ -915,34 +974,36 @@ nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat) io.uio_iovcnt = 1; io.uio_segflg = UIO_SYSSPACE; io.uio_rw = UIO_READ; + io.uio_procp = (struct proc *)0; nfsm_mtouio(&io, len2); + nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR); *(pathcp + len2) = '\0'; - if (ndp->ni_vp) { - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == ndp->ni_vp) - vrele(ndp->ni_dvp); + if (nd.ni_vp) { + VOP_ABORTOP(&nd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); - vrele(ndp->ni_vp); + vput(nd.ni_dvp); + vrele(nd.ni_vp); error = EEXIST; goto out; } VATTR_NULL(vap); - vap->va_mode = 0777; - error = VOP_SYMLINK(ndp, vap, pathcp); + vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode); + error = VOP_SYMLINK(&nd, vap, pathcp, p); out: if (pathcp) FREE(pathcp, M_TEMP); nfsm_reply(0); return (error); nfsmout: - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == ndp->ni_vp) - vrele(ndp->ni_dvp); + VOP_ABORTOP(&nd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); - if (ndp->ni_vp); - vrele(ndp->ni_vp); + vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); if (pathcp) FREE(pathcp, M_TEMP); return (error); @@ -951,20 +1012,20 @@ nfsmout: /* * nfs mkdir service */ -nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { struct vattr va; register struct vattr *vap = &va; register struct nfsv2_fattr *fp; - struct nameidata nami; - register struct nameidata *ndp = &nami; + struct nameidata nd; register caddr_t cp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -975,39 +1036,38 @@ nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat) fhandle_t *fhp; long len; - ndinit(ndp); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); - ndp->ni_cred = cred; - ndp->ni_nameiop = CREATE | LOCKPARENT; - if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) + nd.ni_cred = cred; + nd.ni_nameiop = CREATE | LOCKPARENT; + if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) nfsm_reply(0); - nfsm_disect(p, u_long *, NFSX_UNSIGNED); + nfsm_disect(tl, u_long *, NFSX_UNSIGNED); VATTR_NULL(vap); vap->va_type = VDIR; - vap->va_mode = nfstov_mode(*p++); - vp = ndp->ni_vp; + vap->va_mode = nfstov_mode(*tl++); + vp = nd.ni_vp; if (vp != NULL) { - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == vp) - vrele(ndp->ni_dvp); + VOP_ABORTOP(&nd); + if (nd.ni_dvp == vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); + vput(nd.ni_dvp); vrele(vp); error = EEXIST; nfsm_reply(0); } - if (error = VOP_MKDIR(ndp, vap)) + if (error = VOP_MKDIR(&nd, vap, p)) nfsm_reply(0); - vp = ndp->ni_vp; + vp = nd.ni_vp; bzero((caddr_t)fhp, sizeof(nfh)); fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { vput(vp); nfsm_reply(0); } - error = VOP_GETATTR(vp, vap, cred); + error = VOP_GETATTR(vp, vap, cred, p); vput(vp); nfsm_reply(NFSX_FH+NFSX_FATTR); nfsm_srvfhtom(fhp); @@ -1015,29 +1075,28 @@ nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat) nfsm_srvfillattr; return (error); nfsmout: - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == ndp->ni_vp) - vrele(ndp->ni_dvp); + VOP_ABORTOP(&nd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); - if (ndp->ni_vp) - vrele(ndp->ni_vp); + vput(nd.ni_dvp); + if (nd.ni_vp) + vrele(nd.ni_vp); return (error); } /* * nfs rmdir service */ -nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf *mrep, *md, **mrq; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { - struct nameidata nami; - register struct nameidata *ndp = &nami; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -1047,16 +1106,16 @@ nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat) nfsv2fh_t nfh; fhandle_t *fhp; long len; + struct nameidata nd; - ndinit(ndp); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); - ndp->ni_cred = cred; - ndp->ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; - if (error = nfs_namei(ndp, fhp, len, &md, &dpos)) + nd.ni_cred = cred; + nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF; + if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p)) nfsm_reply(0); - vp = ndp->ni_vp; + vp = nd.ni_vp; if (vp->v_type != VDIR) { error = ENOTDIR; goto out; @@ -1064,24 +1123,24 @@ nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat) /* * No rmdir "." please. */ - if (ndp->ni_dvp == vp) { + if (nd.ni_dvp == vp) { error = EINVAL; goto out; } /* - * Don't unlink a mounted file. + * The root of a mounted filesystem cannot be deleted. */ if (vp->v_flag & VROOT) error = EBUSY; out: if (!error) { - error = VOP_RMDIR(ndp); + error = VOP_RMDIR(&nd, p); } else { - VOP_ABORTOP(ndp); - if (ndp->ni_dvp == ndp->ni_vp) - vrele(ndp->ni_dvp); + VOP_ABORTOP(&nd); + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); else - vput(ndp->ni_dvp); + vput(nd.ni_dvp); vput(vp); } nfsm_reply(0); @@ -1091,7 +1150,7 @@ out: /* * nfs readdir service * - mallocs what it thinks is enough to read - * count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR + * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR * - calls VOP_READDIR() * - loops around building the reply * if the output generated exceeds count break out of loop @@ -1116,19 +1175,20 @@ out: * to including the status longwords that are not a part of the dir. * "entry" structures, but are in the rpc. */ -nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { register char *bp, *be; register struct mbuf *mp; register struct direct *dp; register caddr_t cp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -1149,18 +1209,18 @@ nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat) fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); - nfsm_disect(p, u_long *, 2*NFSX_UNSIGNED); - toff = fxdr_unsigned(off_t, *p++); - off = (toff & ~(DIRBLKSIZ-1)); - on = (toff & (DIRBLKSIZ-1)); - cnt = fxdr_unsigned(int, *p); - siz = ((cnt+DIRBLKSIZ-1) & ~(DIRBLKSIZ-1)); + nfsm_disect(tl, u_long *, 2*NFSX_UNSIGNED); + toff = fxdr_unsigned(off_t, *tl++); + off = (toff & ~(NFS_DIRBLKSIZ-1)); + on = (toff & (NFS_DIRBLKSIZ-1)); + cnt = fxdr_unsigned(int, *tl); + siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1)); if (cnt > NFS_MAXREADDIR) siz = NFS_MAXREADDIR; fullsiz = siz; if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) nfsm_reply(0); - if (error = nfsrv_access(vp, VEXEC, cred)) { + if (error = nfsrv_access(vp, VEXEC, cred, p)) { vput(vp); nfsm_reply(0); } @@ -1175,6 +1235,7 @@ again: io.uio_resid = fullsiz; io.uio_segflg = UIO_SYSSPACE; io.uio_rw = UIO_READ; + io.uio_procp = (struct proc *)0; error = VOP_READDIR(vp, &io, cred, &eofflag); off = io.uio_offset; if (error) { @@ -1192,9 +1253,9 @@ again: if (siz == 0) { vrele(vp); nfsm_reply(2*NFSX_UNSIGNED); - nfsm_build(p, u_long *, 2*NFSX_UNSIGNED); - *p++ = nfs_false; - *p = nfs_true; + nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); + *tl++ = nfs_false; + *tl = nfs_true; FREE((caddr_t)rbuf, M_TEMP); return (0); } @@ -1246,13 +1307,13 @@ again: /* Build the directory record xdr from the direct entry */ nfsm_clget; - *p = nfs_true; + *tl = nfs_true; bp += NFSX_UNSIGNED; nfsm_clget; - *p = txdr_unsigned(dp->d_ino); + *tl = txdr_unsigned(dp->d_ino); bp += NFSX_UNSIGNED; nfsm_clget; - *p = txdr_unsigned(nlen); + *tl = txdr_unsigned(nlen); bp += NFSX_UNSIGNED; /* And loop arround copying the name */ @@ -1277,7 +1338,7 @@ again: /* Finish off the record */ toff += dp->d_reclen; - *p = txdr_unsigned(toff); + *tl = txdr_unsigned(toff); bp += NFSX_UNSIGNED; } else toff += dp->d_reclen; @@ -1285,13 +1346,13 @@ again: dp = (struct direct *)cpos; } nfsm_clget; - *p = nfs_false; + *tl = nfs_false; bp += NFSX_UNSIGNED; nfsm_clget; if (eofflag) - *p = nfs_true; + *tl = nfs_true; else - *p = nfs_false; + *tl = nfs_false; bp += NFSX_UNSIGNED; if (bp < be) mp->m_len = bp-mtod(mp, caddr_t); @@ -1303,17 +1364,18 @@ again: /* * nfs statfs service */ -nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { register struct statfs *sf; register struct nfsv2_statfs *sfp; - register u_long *p; + register u_long *tl; register long t1; caddr_t bpos; int error = 0; @@ -1329,7 +1391,7 @@ nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat) if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) nfsm_reply(0); sf = &statfs; - error = VFS_STATFS(vp->v_mount, sf); + error = VFS_STATFS(vp->v_mount, sf, p); vput(vp); nfsm_reply(NFSX_STATFS); nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS); @@ -1345,13 +1407,14 @@ nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat) * Null operation, used by clients to ping server */ /* ARGSUSED */ -nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { caddr_t bpos; int error = 0; @@ -1366,13 +1429,14 @@ nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat) * No operation, used for obsolete procedures */ /* ARGSUSED */ -nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat) +nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat, p) struct mbuf **mrq; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; u_long xid; int *repstat; + struct proc *p; { caddr_t bpos; int error = 0; @@ -1393,10 +1457,11 @@ nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat) * this because it opens a security hole, but since the nfs server opens * a security hole the size of a barn door anyhow, what the heck. */ -nfsrv_access(vp, flags, cred) +nfsrv_access(vp, flags, cred, p) register struct vnode *vp; int flags; register struct ucred *cred; + struct proc *p; { struct vattr vattr; int error; @@ -1407,29 +1472,24 @@ nfsrv_access(vp, flags, cred) * unless the file is a socket or a block or character * device resident on the file system. */ - if ((vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) && - vp->v_type != VCHR && - vp->v_type != VBLK && - vp->v_type != VSOCK) + if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) { + switch (vp->v_type) { + case VREG: case VDIR: case VLNK: return (EROFS); + } + } /* * If there's shared text associated with * the inode, try to free it up once. If * we fail, we can't allow writing. */ - if (vp->v_flag & VTEXT) - xrele(vp); - if (vp->v_flag & VTEXT) + if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp)) return (ETXTBSY); - if (error = VOP_GETATTR(vp, &vattr, cred)) - return (error); - if (cred->cr_uid == vattr.va_uid) - return (0); - } else { - if (error = VOP_GETATTR(vp, &vattr, cred)) - return (error); - if (cred->cr_uid == vattr.va_uid) - return (0); } - return (VOP_ACCESS(vp, flags, cred)); + if (error = VOP_GETATTR(vp, &vattr, cred, p)) + return (error); + if ((error = VOP_ACCESS(vp, flags, cred, p)) && + cred->cr_uid != vattr.va_uid) + return (error); + return (0); }