Home | History | Annotate | Line # | Download | only in nfs
nfs_serv.c revision 1.5
      1 /*
      2  * Copyright (c) 1989 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * This code is derived from software contributed to Berkeley by
      6  * Rick Macklem at The University of Guelph.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by the University of
     19  *	California, Berkeley and its contributors.
     20  * 4. Neither the name of the University nor the names of its contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  *	from: @(#)nfs_serv.c	7.40 (Berkeley) 5/15/91
     37  *	$Id: nfs_serv.c,v 1.5 1993/07/16 00:51:55 cgd Exp $
     38  */
     39 
     40 /*
     41  * nfs version 2 server calls to vnode ops
     42  * - these routines generally have 3 phases
     43  *   1 - break down and validate rpc request in mbuf list
     44  *   2 - do the vnode ops for the request
     45  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
     46  *   3 - build the rpc reply in an mbuf list
     47  *   nb:
     48  *	- do not mix the phases, since the nfsm_?? macros can return failures
     49  *	  on a bad rpc or similar and do not do any vrele() or vput()'s
     50  *
     51  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
     52  *	error number iff error != 0 whereas
     53  *	returning an error from the server function implies a fatal error
     54  *	such as a badly constructed rpc request that should be dropped without
     55  *	a reply.
     56  */
     57 
     58 #include "param.h"
     59 #include "proc.h"
     60 #include "file.h"
     61 #include "namei.h"
     62 #include "vnode.h"
     63 #include "mount.h"
     64 #include "mbuf.h"
     65 
     66 #include "../ufs/quota.h"
     67 #include "../ufs/inode.h"
     68 #include "../ufs/dir.h"
     69 
     70 #include "nfsv2.h"
     71 #include "nfs.h"
     72 #include "xdr_subs.h"
     73 #include "nfsm_subs.h"
     74 
     75 /* Defs */
     76 #define	TRUE	1
     77 #define	FALSE	0
     78 
     79 /* Global vars */
     80 extern u_long nfs_procids[NFS_NPROCS];
     81 extern u_long nfs_xdrneg1;
     82 extern u_long nfs_false, nfs_true;
     83 nfstype nfs_type[9]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
     84 		      NFCHR, NFNON };
     85 
     86 int	nfsrv_null(),
     87 	nfsrv_getattr(),
     88 	nfsrv_setattr(),
     89 	nfsrv_lookup(),
     90 	nfsrv_readlink(),
     91 	nfsrv_read(),
     92 	nfsrv_write(),
     93 	nfsrv_create(),
     94 	nfsrv_remove(),
     95 	nfsrv_rename(),
     96 	nfsrv_link(),
     97 	nfsrv_symlink(),
     98 	nfsrv_mkdir(),
     99 	nfsrv_rmdir(),
    100 	nfsrv_readdir(),
    101 	nfsrv_statfs(),
    102 	nfsrv_noop();
    103 
    104 int (*nfsrv_procs[NFS_NPROCS])() = {
    105 	nfsrv_null,
    106 	nfsrv_getattr,
    107 	nfsrv_setattr,
    108 	nfsrv_noop,
    109 	nfsrv_lookup,
    110 	nfsrv_readlink,
    111 	nfsrv_read,
    112 	nfsrv_noop,
    113 	nfsrv_write,
    114 	nfsrv_create,
    115 	nfsrv_remove,
    116 	nfsrv_rename,
    117 	nfsrv_link,
    118 	nfsrv_symlink,
    119 	nfsrv_mkdir,
    120 	nfsrv_rmdir,
    121 	nfsrv_readdir,
    122 	nfsrv_statfs,
    123 };
    124 /*
    125  * nfs getattr service
    126  */
    127 nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
    128 	struct mbuf **mrq;
    129 	struct mbuf *mrep, *md;
    130 	caddr_t dpos;
    131 	struct ucred *cred;
    132 	u_long xid;
    133 	int *repstat;
    134 	struct proc *p;
    135 {
    136 	register struct nfsv2_fattr *fp;
    137 	struct vattr va;
    138 	register struct vattr *vap = &va;
    139 	struct vnode *vp;
    140 	nfsv2fh_t nfh;
    141 	fhandle_t *fhp;
    142 	register u_long *tl;
    143 	register long t1;
    144 	caddr_t bpos;
    145 	int error = 0;
    146 	char *cp2;
    147 	struct mbuf *mb, *mb2, *mreq;
    148 
    149 	fhp = &nfh.fh_generic;
    150 	nfsm_srvmtofh(fhp);
    151 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
    152 		nfsm_reply(0);
    153 	error = VOP_GETATTR(vp, vap, cred, p);
    154 	vput(vp);
    155 	nfsm_reply(NFSX_FATTR);
    156 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
    157 	nfsm_srvfillattr;
    158 	nfsm_srvdone;
    159 }
    160 
    161 /*
    162  * nfs setattr service
    163  */
    164 nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
    165 	struct mbuf **mrq;
    166 	struct mbuf *mrep, *md;
    167 	caddr_t dpos;
    168 	struct ucred *cred;
    169 	u_long xid;
    170 	int *repstat;
    171 	struct proc *p;
    172 {
    173 	struct vattr va;
    174 	register struct vattr *vap = &va;
    175 	register struct nfsv2_sattr *sp;
    176 	register struct nfsv2_fattr *fp;
    177 	struct vnode *vp;
    178 	nfsv2fh_t nfh;
    179 	fhandle_t *fhp;
    180 	register u_long *tl;
    181 	register long t1;
    182 	caddr_t bpos;
    183 	int error = 0;
    184 	char *cp2;
    185 	struct mbuf *mb, *mb2, *mreq;
    186 
    187 	fhp = &nfh.fh_generic;
    188 	nfsm_srvmtofh(fhp);
    189 	nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
    190 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
    191 		nfsm_reply(0);
    192 	if (error = nfsrv_access(vp, VWRITE, cred, p))
    193 		goto out;
    194 	VATTR_NULL(vap);
    195 	/*
    196 	 * Nah nah nah nah na nah
    197 	 * There is a bug in the Sun client that puts 0xffff in the mode
    198 	 * field of sattr when it should put in 0xffffffff. The u_short
    199 	 * doesn't sign extend.
    200 	 * --> check the low order 2 bytes for 0xffff
    201 	 */
    202 	if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
    203 		vap->va_mode = nfstov_mode(sp->sa_mode);
    204 	if (sp->sa_uid != nfs_xdrneg1)
    205 		vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
    206 	if (sp->sa_gid != nfs_xdrneg1)
    207 		vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
    208 	if (sp->sa_size != nfs_xdrneg1)
    209 		vap->va_size = fxdr_unsigned(u_long, sp->sa_size);
    210 	/*
    211 	 * The usec field of sa_atime is overloaded with the va_flags field
    212 	 * for 4.4BSD clients. Hopefully other clients always set both the
    213 	 * sec and usec fields to -1 when not setting the atime.
    214 	 *
    215 	 * jfw (at) ksr.com (6/2/93):  Suns certainly don't set the usec field to
    216 	 *                        -1 when *setting* the atime, resulting in
    217 	 *                        va_flags acquiring random contents.
    218 	 */
    219 #if 0 /* bad assumption, NFS is too fragile to extend. */
    220 	if (sp->sa_atime.tv_sec != nfs_xdrneg1) {
    221 		vap->va_atime.tv_sec = fxdr_unsigned(long, sp->sa_atime.tv_sec);
    222 		vap->va_atime.tv_usec = 0;
    223 	}
    224 	if (sp->sa_atime.tv_usec != nfs_xdrneg1)
    225 		vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec);
    226 #else
    227 	if (sp->sa_atime.tv_sec != nfs_xdrneg1)
    228 		fxdr_time(&sp->sa_atime, &vap->va_atime);
    229 #endif
    230 	if (sp->sa_mtime.tv_sec != nfs_xdrneg1)
    231 		fxdr_time(&sp->sa_mtime, &vap->va_mtime);
    232 	if (error = VOP_SETATTR(vp, vap, cred, p)) {
    233 		vput(vp);
    234 		nfsm_reply(0);
    235 	}
    236 	error = VOP_GETATTR(vp, vap, cred, p);
    237 out:
    238 	vput(vp);
    239 	nfsm_reply(NFSX_FATTR);
    240 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
    241 	nfsm_srvfillattr;
    242 	nfsm_srvdone;
    243 }
    244 
    245 /*
    246  * nfs lookup rpc
    247  */
    248 nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat, p)
    249 	struct mbuf **mrq;
    250 	struct mbuf *mrep, *md;
    251 	caddr_t dpos;
    252 	struct ucred *cred;
    253 	u_long xid;
    254 	int *repstat;
    255 	struct proc *p;
    256 {
    257 	register struct nfsv2_fattr *fp;
    258 	struct nameidata nd;
    259 	struct vnode *vp;
    260 	nfsv2fh_t nfh;
    261 	fhandle_t *fhp;
    262 	register caddr_t cp;
    263 	register u_long *tl;
    264 	register long t1;
    265 	caddr_t bpos;
    266 	int error = 0;
    267 	char *cp2;
    268 	struct mbuf *mb, *mb2, *mreq;
    269 	long len;
    270 	struct vattr va, *vap = &va;
    271 
    272 	fhp = &nfh.fh_generic;
    273 	nfsm_srvmtofh(fhp);
    274 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
    275 	nd.ni_cred = cred;
    276 	nd.ni_nameiop = LOOKUP | LOCKLEAF;
    277 	if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
    278 		nfsm_reply(0);
    279 	vp = nd.ni_vp;
    280 	bzero((caddr_t)fhp, sizeof(nfh));
    281 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
    282 	if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
    283 		vput(vp);
    284 		nfsm_reply(0);
    285 	}
    286 	error = VOP_GETATTR(vp, vap, cred, p);
    287 	vput(vp);
    288 	nfsm_reply(NFSX_FH+NFSX_FATTR);
    289 	nfsm_srvfhtom(fhp);
    290 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
    291 	nfsm_srvfillattr;
    292 	nfsm_srvdone;
    293 }
    294 
    295 /*
    296  * nfs readlink service
    297  */
    298 nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
    299 	struct mbuf **mrq;
    300 	struct mbuf *mrep, *md;
    301 	caddr_t dpos;
    302 	struct ucred *cred;
    303 	u_long xid;
    304 	int *repstat;
    305 	struct proc *p;
    306 {
    307 	struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
    308 	register struct iovec *ivp = iv;
    309 	register struct mbuf *mp;
    310 	register u_long *tl;
    311 	register long t1;
    312 	caddr_t bpos;
    313 	int error = 0;
    314 	char *cp2;
    315 	struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
    316 	struct vnode *vp;
    317 	nfsv2fh_t nfh;
    318 	fhandle_t *fhp;
    319 	struct uio io, *uiop = &io;
    320 	int i, tlen, len;
    321 
    322 	fhp = &nfh.fh_generic;
    323 	nfsm_srvmtofh(fhp);
    324 	len = 0;
    325 	i = 0;
    326 	while (len < NFS_MAXPATHLEN) {
    327 		MGET(mp, M_WAIT, MT_DATA);
    328 		MCLGET(mp, M_WAIT);
    329 		mp->m_len = NFSMSIZ(mp);
    330 		if (len == 0)
    331 			mp3 = mp2 = mp;
    332 		else {
    333 			mp2->m_next = mp;
    334 			mp2 = mp;
    335 		}
    336 		if ((len+mp->m_len) > NFS_MAXPATHLEN) {
    337 			mp->m_len = NFS_MAXPATHLEN-len;
    338 			len = NFS_MAXPATHLEN;
    339 		} else
    340 			len += mp->m_len;
    341 		ivp->iov_base = mtod(mp, caddr_t);
    342 		ivp->iov_len = mp->m_len;
    343 		i++;
    344 		ivp++;
    345 	}
    346 	uiop->uio_iov = iv;
    347 	uiop->uio_iovcnt = i;
    348 	uiop->uio_offset = 0;
    349 	uiop->uio_resid = len;
    350 	uiop->uio_rw = UIO_READ;
    351 	uiop->uio_segflg = UIO_SYSSPACE;
    352 	uiop->uio_procp = (struct proc *)0;
    353 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) {
    354 		m_freem(mp3);
    355 		nfsm_reply(0);
    356 	}
    357 	if (vp->v_type != VLNK) {
    358 		error = EINVAL;
    359 		goto out;
    360 	}
    361 	error = VOP_READLINK(vp, uiop, cred);
    362 out:
    363 	vput(vp);
    364 	if (error)
    365 		m_freem(mp3);
    366 	nfsm_reply(NFSX_UNSIGNED);
    367 	if (uiop->uio_resid > 0) {
    368 		len -= uiop->uio_resid;
    369 		tlen = nfsm_rndup(len);
    370 		nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
    371 	}
    372 	nfsm_build(tl, u_long *, NFSX_UNSIGNED);
    373 	*tl = txdr_unsigned(len);
    374 	mb->m_next = mp3;
    375 	nfsm_srvdone;
    376 }
    377 
    378 /*
    379  * nfs read service
    380  */
    381 nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat, p)
    382 	struct mbuf **mrq;
    383 	struct mbuf *mrep, *md;
    384 	caddr_t dpos;
    385 	struct ucred *cred;
    386 	u_long xid;
    387 	int *repstat;
    388 	struct proc *p;
    389 {
    390 	register struct iovec *iv;
    391 	struct iovec *iv2;
    392 	register struct mbuf *m;
    393 	register struct nfsv2_fattr *fp;
    394 	register u_long *tl;
    395 	register long t1;
    396 	caddr_t bpos;
    397 	int error = 0;
    398 	char *cp2;
    399 	struct mbuf *mb, *mb2, *mreq;
    400 	struct mbuf *m2, *m3;
    401 	struct vnode *vp;
    402 	nfsv2fh_t nfh;
    403 	fhandle_t *fhp;
    404 	struct uio io, *uiop = &io;
    405 	struct vattr va, *vap = &va;
    406 	int i, cnt, len, left, siz, tlen;
    407 	off_t off;
    408 
    409 	fhp = &nfh.fh_generic;
    410 	nfsm_srvmtofh(fhp);
    411 	nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
    412 	off = fxdr_unsigned(off_t, *tl);
    413 	nfsm_srvstrsiz(cnt, NFS_MAXDATA);
    414 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
    415 		nfsm_reply(0);
    416 	if ((error = nfsrv_access(vp, VREAD, cred, p)) &&
    417 		(error = nfsrv_access(vp, VEXEC, cred, p))) {
    418 		vput(vp);
    419 		nfsm_reply(0);
    420 	}
    421 	len = left = cnt;
    422 	/*
    423 	 * Generate the mbuf list with the uio_iov ref. to it.
    424 	 */
    425 	i = 0;
    426 	m3 = (struct mbuf *)0;
    427 #ifdef lint
    428 	m2 = (struct mbuf *)0;
    429 #endif /* lint */
    430 	MALLOC(iv, struct iovec *,
    431 	       ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec), M_TEMP,
    432 	       M_WAITOK);
    433 	iv2 = iv;
    434 	while (left > 0) {
    435 		MGET(m, M_WAIT, MT_DATA);
    436 		if (left > MINCLSIZE)
    437 			MCLGET(m, M_WAIT);
    438 		m->m_len = 0;
    439 		siz = min(M_TRAILINGSPACE(m), left);
    440 		m->m_len = siz;
    441 		iv->iov_base = mtod(m, caddr_t);
    442 		iv->iov_len = siz;
    443 		iv++;
    444 		i++;
    445 		left -= siz;
    446 		if (m3) {
    447 			m2->m_next = m;
    448 			m2 = m;
    449 		} else
    450 			m3 = m2 = m;
    451 	}
    452 	uiop->uio_iov = iv2;
    453 	uiop->uio_iovcnt = i;
    454 	uiop->uio_offset = off;
    455 	uiop->uio_resid = cnt;
    456 	uiop->uio_rw = UIO_READ;
    457 	uiop->uio_segflg = UIO_SYSSPACE;
    458 	uiop->uio_procp = (struct proc *)0;
    459 	error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
    460 	off = uiop->uio_offset;
    461 	FREE((caddr_t)iv2, M_TEMP);
    462 	if (error) {
    463 		m_freem(m3);
    464 		vput(vp);
    465 		nfsm_reply(0);
    466 	}
    467 	if (error = VOP_GETATTR(vp, vap, cred, p))
    468 		m_freem(m3);
    469 	vput(vp);
    470 	nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED);
    471 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
    472 	nfsm_srvfillattr;
    473 	len -= uiop->uio_resid;
    474 	if (len > 0) {
    475 		tlen = nfsm_rndup(len);
    476 		if (cnt != tlen || tlen != len)
    477 			nfsm_adj(m3, cnt-tlen, tlen-len);
    478 	} else {
    479 		m_freem(m3);
    480 		m3 = (struct mbuf *)0;
    481 	}
    482 	nfsm_build(tl, u_long *, NFSX_UNSIGNED);
    483 	*tl = txdr_unsigned(len);
    484 	mb->m_next = m3;
    485 	nfsm_srvdone;
    486 }
    487 
    488 /*
    489  * nfs write service
    490  */
    491 nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat, p)
    492 	struct mbuf *mrep, *md, **mrq;
    493 	caddr_t dpos;
    494 	struct ucred *cred;
    495 	u_long xid;
    496 	int *repstat;
    497 	struct proc *p;
    498 {
    499 	register struct iovec *ivp;
    500 	register struct mbuf *mp;
    501 	register struct nfsv2_fattr *fp;
    502 	struct iovec iv[NFS_MAXIOVEC];
    503 	struct vattr va;
    504 	register struct vattr *vap = &va;
    505 	register u_long *tl;
    506 	register long t1;
    507 	caddr_t bpos;
    508 	int error = 0;
    509 	char *cp2;
    510 	struct mbuf *mb, *mb2, *mreq;
    511 	struct vnode *vp;
    512 	nfsv2fh_t nfh;
    513 	fhandle_t *fhp;
    514 	struct uio io, *uiop = &io;
    515 	off_t off;
    516 	long siz, len, xfer;
    517 
    518 	fhp = &nfh.fh_generic;
    519 	nfsm_srvmtofh(fhp);
    520 	nfsm_disect(tl, u_long *, 4*NFSX_UNSIGNED);
    521 	off = fxdr_unsigned(off_t, *++tl);
    522 	tl += 2;
    523 	len = fxdr_unsigned(long, *tl);
    524 	if (len > NFS_MAXDATA || len <= 0) {
    525 		error = EBADRPC;
    526 		nfsm_reply(0);
    527 	}
    528 	if (dpos == (mtod(md, caddr_t)+md->m_len)) {
    529 		mp = md->m_next;
    530 		if (mp == NULL) {
    531 			error = EBADRPC;
    532 			nfsm_reply(0);
    533 		}
    534 	} else {
    535 		mp = md;
    536 		siz = dpos-mtod(mp, caddr_t);
    537 		mp->m_len -= siz;
    538 		NFSMADV(mp, siz);
    539 	}
    540 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
    541 		nfsm_reply(0);
    542 	if (error = nfsrv_access(vp, VWRITE, cred, p)) {
    543 		vput(vp);
    544 		nfsm_reply(0);
    545 	}
    546 	uiop->uio_resid = 0;
    547 	uiop->uio_rw = UIO_WRITE;
    548 	uiop->uio_segflg = UIO_SYSSPACE;
    549 	uiop->uio_procp = (struct proc *)0;
    550 	/*
    551 	 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the
    552 	 * loop until done.
    553 	 */
    554 	while (len > 0 && uiop->uio_resid == 0) {
    555 		ivp = iv;
    556 		siz = 0;
    557 		uiop->uio_iov = ivp;
    558 		uiop->uio_iovcnt = 0;
    559 		uiop->uio_offset = off;
    560 		while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) {
    561 			ivp->iov_base = mtod(mp, caddr_t);
    562 			if (len < mp->m_len)
    563 				ivp->iov_len = xfer = len;
    564 			else
    565 				ivp->iov_len = xfer = mp->m_len;
    566 #ifdef notdef
    567 			/* Not Yet .. */
    568 			if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0)
    569 				ivp->iov_op = NULL;	/* what should it be ?? */
    570 			else
    571 				ivp->iov_op = NULL;
    572 #endif
    573 			uiop->uio_iovcnt++;
    574 			ivp++;
    575 			len -= xfer;
    576 			siz += xfer;
    577 			mp = mp->m_next;
    578 		}
    579 		if (len > 0 && mp == NULL) {
    580 			error = EBADRPC;
    581 			vput(vp);
    582 			nfsm_reply(0);
    583 		}
    584 		uiop->uio_resid = siz;
    585 		if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED,
    586 			cred)) {
    587 			vput(vp);
    588 			nfsm_reply(0);
    589 		}
    590 		off = uiop->uio_offset;
    591 	}
    592 	error = VOP_GETATTR(vp, vap, cred, p);
    593 	vput(vp);
    594 	nfsm_reply(NFSX_FATTR);
    595 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
    596 	nfsm_srvfillattr;
    597 	nfsm_srvdone;
    598 }
    599 
    600 /*
    601  * nfs create service
    602  * if it already exists, just set length		* 28 Aug 92*
    603  * do NOT truncate unconditionally !
    604  */
    605 nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat, p)
    606 	struct mbuf *mrep, *md, **mrq;
    607 	caddr_t dpos;
    608 	struct ucred *cred;
    609 	u_long xid;
    610 	int *repstat;
    611 	struct proc *p;
    612 {
    613 	register struct nfsv2_fattr *fp;
    614 	struct vattr va;
    615 	register struct vattr *vap = &va;
    616 	struct nameidata nd;
    617 	register caddr_t cp;
    618 	register u_long *tl;
    619 	register long t1;
    620 	caddr_t bpos;
    621 	long rdev;
    622 	int error = 0;
    623 	char *cp2;
    624 	struct mbuf *mb, *mb2, *mreq;
    625 	struct vnode *vp;
    626 	nfsv2fh_t nfh;
    627 	fhandle_t *fhp;
    628 	long len;
    629 
    630 	nd.ni_nameiop = 0;
    631 	fhp = &nfh.fh_generic;
    632 	nfsm_srvmtofh(fhp);
    633 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
    634 	nd.ni_cred = cred;
    635 	nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART;
    636 	if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
    637 		nfsm_reply(0);
    638 	VATTR_NULL(vap);
    639 	nfsm_disect(tl, u_long *, NFSX_SATTR);
    640 	/*
    641 	 * If it doesn't exist, create it		* 28 Aug 92*
    642 	 * otherwise just set length from attributes
    643 	 *   should I set the mode too ??
    644 	 */
    645 	if (nd.ni_vp == NULL) {
    646 		vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl));
    647 		if (vap->va_type == VNON)
    648 			vap->va_type = VREG;
    649 		vap->va_mode = nfstov_mode(*tl);
    650 		rdev = fxdr_unsigned(long, *(tl+3));
    651 		if (vap->va_type == VREG || vap->va_type == VSOCK) {
    652 			vrele(nd.ni_startdir);
    653 			if (error = VOP_CREATE(&nd, vap, p))
    654 				nfsm_reply(0);
    655 			FREE(nd.ni_pnbuf, M_NAMEI);
    656 		} else if (vap->va_type == VCHR || vap->va_type == VBLK ||
    657 			vap->va_type == VFIFO) {
    658 			if (vap->va_type == VCHR && rdev == 0xffffffff)
    659 				vap->va_type = VFIFO;
    660 			if (vap->va_type == VFIFO) {
    661 #ifndef FIFO
    662 				VOP_ABORTOP(&nd);
    663 				vput(nd.ni_dvp);
    664 				error = ENXIO;
    665 				goto out;
    666 #endif /* FIFO */
    667 			} else if (error = suser(cred, (short *)0)) {
    668 				VOP_ABORTOP(&nd);
    669 				vput(nd.ni_dvp);
    670 				goto out;
    671 			} else
    672 				vap->va_rdev = (dev_t)rdev;
    673 			if (error = VOP_MKNOD(&nd, vap, cred, p)) {
    674 				vrele(nd.ni_startdir);
    675 				nfsm_reply(0);
    676 			}
    677 			nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART);
    678 			nd.ni_nameiop |= LOOKUP;
    679 			if (error = lookup(&nd, p)) {
    680 				free(nd.ni_pnbuf, M_NAMEI);
    681 				nfsm_reply(0);
    682 			}
    683 			FREE(nd.ni_pnbuf, M_NAMEI);
    684 			if (nd.ni_more) {
    685 				vrele(nd.ni_dvp);
    686 				vput(nd.ni_vp);
    687 				VOP_ABORTOP(&nd);
    688 				error = EINVAL;
    689 				nfsm_reply(0);
    690 			}
    691 		} else {
    692 			VOP_ABORTOP(&nd);
    693 			vput(nd.ni_dvp);
    694 			error = ENXIO;
    695 			goto out;
    696 		}
    697 		vp = nd.ni_vp;
    698 	} else {
    699 		vrele(nd.ni_startdir);
    700 		free(nd.ni_pnbuf, M_NAMEI);
    701 		vp = nd.ni_vp;
    702 		if (nd.ni_dvp == vp)
    703 			vrele(nd.ni_dvp);
    704 		else
    705 			vput(nd.ni_dvp);
    706 		VOP_ABORTOP(&nd);
    707 		vap->va_size = fxdr_unsigned(long, *(tl+3));	/* 28 Aug 92*/
    708 /* 08 Sep 92*/	if (vap->va_size != -1 && (error = VOP_SETATTR(vp, vap, cred, p))) {
    709 			vput(vp);
    710 			nfsm_reply(0);
    711 		}
    712 	}
    713 	bzero((caddr_t)fhp, sizeof(nfh));
    714 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
    715 	if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
    716 		vput(vp);
    717 		nfsm_reply(0);
    718 	}
    719 	error = VOP_GETATTR(vp, vap, cred, p);
    720 	vput(vp);
    721 	nfsm_reply(NFSX_FH+NFSX_FATTR);
    722 	nfsm_srvfhtom(fhp);
    723 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
    724 	nfsm_srvfillattr;
    725 	return (error);
    726 nfsmout:
    727 	if (nd.ni_nameiop)
    728 		vrele(nd.ni_startdir);
    729 	VOP_ABORTOP(&nd);
    730 	if (nd.ni_dvp == nd.ni_vp)
    731 		vrele(nd.ni_dvp);
    732 	else
    733 		vput(nd.ni_dvp);
    734 	if (nd.ni_vp)
    735 		vput(nd.ni_vp);
    736 	return (error);
    737 
    738 out:
    739 	vrele(nd.ni_startdir);
    740 	free(nd.ni_pnbuf, M_NAMEI);
    741 	nfsm_reply(0);
    742 }
    743 
    744 /*
    745  * nfs remove service
    746  */
    747 nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat, p)
    748 	struct mbuf *mrep, *md, **mrq;
    749 	caddr_t dpos;
    750 	struct ucred *cred;
    751 	u_long xid;
    752 	int *repstat;
    753 	struct proc *p;
    754 {
    755 	struct nameidata nd;
    756 	register u_long *tl;
    757 	register long t1;
    758 	caddr_t bpos;
    759 	int error = 0;
    760 	char *cp2;
    761 	struct mbuf *mb, *mreq;
    762 	struct vnode *vp;
    763 	nfsv2fh_t nfh;
    764 	fhandle_t *fhp;
    765 	long len;
    766 
    767 	fhp = &nfh.fh_generic;
    768 	nfsm_srvmtofh(fhp);
    769 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
    770 	nd.ni_cred = cred;
    771 	nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
    772 	if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
    773 		nfsm_reply(0);
    774 	vp = nd.ni_vp;
    775 	if (vp->v_type == VDIR &&
    776 		(error = suser(cred, (short *)0)))
    777 		goto out;
    778 	/*
    779 	 * The root of a mounted filesystem cannot be deleted.
    780 	 */
    781 	if (vp->v_flag & VROOT) {
    782 		error = EBUSY;
    783 		goto out;
    784 	}
    785 	if (vp->v_flag & VTEXT)
    786 		(void) vnode_pager_uncache(vp);
    787 out:
    788 	if (!error) {
    789 		error = VOP_REMOVE(&nd, p);
    790 	} else {
    791 		VOP_ABORTOP(&nd);
    792 		if (nd.ni_dvp == vp)
    793 			vrele(nd.ni_dvp);
    794 		else
    795 			vput(nd.ni_dvp);
    796 		vput(vp);
    797 	}
    798 	nfsm_reply(0);
    799 	nfsm_srvdone;
    800 }
    801 
    802 /*
    803  * nfs rename service
    804  */
    805 nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat, p)
    806 	struct mbuf *mrep, *md, **mrq;
    807 	caddr_t dpos;
    808 	struct ucred *cred;
    809 	u_long xid;
    810 	int *repstat;
    811 	struct proc *p;
    812 {
    813 	register u_long *tl;
    814 	register long t1;
    815 	caddr_t bpos;
    816 	int error = 0;
    817 	char *cp2;
    818 	struct mbuf *mb, *mreq;
    819 	struct nameidata fromnd, tond;
    820 	struct vnode *fvp, *tvp, *tdvp;
    821 	nfsv2fh_t fnfh, tnfh;
    822 	fhandle_t *ffhp, *tfhp;
    823 	long len, len2;
    824 	int rootflg = 0;
    825 
    826 	ffhp = &fnfh.fh_generic;
    827 	tfhp = &tnfh.fh_generic;
    828 	fromnd.ni_nameiop = 0;
    829 	tond.ni_nameiop = 0;
    830 	nfsm_srvmtofh(ffhp);
    831 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
    832 	/*
    833 	 * Remember if we are root so that we can reset cr_uid before
    834 	 * the second nfs_namei() call
    835 	 */
    836 	if (cred->cr_uid == 0)
    837 		rootflg++;
    838 	fromnd.ni_cred = cred;
    839 	fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
    840 	if (error = nfs_namei(&fromnd, ffhp, len, &md, &dpos, p))
    841 		nfsm_reply(0);
    842 	fvp = fromnd.ni_vp;
    843 	nfsm_srvmtofh(tfhp);
    844 	nfsm_strsiz(len2, NFS_MAXNAMLEN);
    845 	if (rootflg)
    846 		cred->cr_uid = 0;
    847 	tond.ni_cred = cred;
    848 	tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE
    849 		| SAVESTART;
    850 	if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos, p)) {
    851 		VOP_ABORTOP(&fromnd);
    852 		vrele(fromnd.ni_dvp);
    853 		vrele(fvp);
    854 		goto out1;
    855 	}
    856 	tdvp = tond.ni_dvp;
    857 	tvp = tond.ni_vp;
    858 	if (tvp != NULL) {
    859 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
    860 			error = EISDIR;
    861 			goto out;
    862 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
    863 			error = ENOTDIR;
    864 			goto out;
    865 		}
    866 	}
    867 	if (fvp->v_mount != tdvp->v_mount) {
    868 		error = EXDEV;
    869 		goto out;
    870 	}
    871 	if (fvp == tdvp)
    872 		error = EINVAL;
    873 	/*
    874 	 * If source is the same as the destination (that is the
    875 	 * same vnode with the same name in the same directory),
    876 	 * then there is nothing to do.
    877 	 */
    878 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
    879 	    fromnd.ni_namelen == tond.ni_namelen &&
    880 	    !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
    881 		error = -1;
    882 out:
    883 	if (!error) {
    884 		error = VOP_RENAME(&fromnd, &tond, p);
    885 	} else {
    886 		VOP_ABORTOP(&tond);
    887 		if (tdvp == tvp)
    888 			vrele(tdvp);
    889 		else
    890 			vput(tdvp);
    891 		if (tvp)
    892 			vput(tvp);
    893 		VOP_ABORTOP(&fromnd);
    894 		vrele(fromnd.ni_dvp);
    895 		vrele(fvp);
    896 	}
    897 	vrele(tond.ni_startdir);
    898 	FREE(tond.ni_pnbuf, M_NAMEI);
    899 out1:
    900 	vrele(fromnd.ni_startdir);
    901 	FREE(fromnd.ni_pnbuf, M_NAMEI);
    902 	nfsm_reply(0);
    903 	return (error);
    904 
    905 nfsmout:
    906 	if (tond.ni_nameiop) {
    907 		vrele(tond.ni_startdir);
    908 		FREE(tond.ni_pnbuf, M_NAMEI);
    909 	}
    910 	if (fromnd.ni_nameiop) {
    911 		vrele(fromnd.ni_startdir);
    912 		FREE(fromnd.ni_pnbuf, M_NAMEI);
    913 		VOP_ABORTOP(&fromnd);
    914 		vrele(fromnd.ni_dvp);
    915 		vrele(fvp);
    916 	}
    917 	return (error);
    918 }
    919 
    920 /*
    921  * nfs link service
    922  */
    923 nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat, p)
    924 	struct mbuf *mrep, *md, **mrq;
    925 	caddr_t dpos;
    926 	struct ucred *cred;
    927 	u_long xid;
    928 	int *repstat;
    929 	struct proc *p;
    930 {
    931 	struct nameidata nd;
    932 	register u_long *tl;
    933 	register long t1;
    934 	caddr_t bpos;
    935 	int error = 0;
    936 	char *cp2;
    937 	struct mbuf *mb, *mreq;
    938 	struct vnode *vp, *xp;
    939 	nfsv2fh_t nfh, dnfh;
    940 	fhandle_t *fhp, *dfhp;
    941 	long len;
    942 
    943 	fhp = &nfh.fh_generic;
    944 	dfhp = &dnfh.fh_generic;
    945 	nfsm_srvmtofh(fhp);
    946 	nfsm_srvmtofh(dfhp);
    947 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
    948 	if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred))
    949 		nfsm_reply(0);
    950 	if (vp->v_type == VDIR && (error = suser(cred, NULL)))
    951 		goto out1;
    952 	nd.ni_cred = cred;
    953 	nd.ni_nameiop = CREATE | LOCKPARENT;
    954 	if (error = nfs_namei(&nd, dfhp, len, &md, &dpos, p))
    955 		goto out1;
    956 	xp = nd.ni_vp;
    957 	if (xp != NULL) {
    958 		error = EEXIST;
    959 		goto out;
    960 	}
    961 	xp = nd.ni_dvp;
    962 	if (vp->v_mount != xp->v_mount)
    963 		error = EXDEV;
    964 out:
    965 	if (!error) {
    966 		error = VOP_LINK(vp, &nd, p);
    967 	} else {
    968 		VOP_ABORTOP(&nd);
    969 		if (nd.ni_dvp == nd.ni_vp)
    970 			vrele(nd.ni_dvp);
    971 		else
    972 			vput(nd.ni_dvp);
    973 		if (nd.ni_vp)
    974 			vrele(nd.ni_vp);
    975 	}
    976 out1:
    977 	vrele(vp);
    978 	nfsm_reply(0);
    979 	nfsm_srvdone;
    980 }
    981 
    982 /*
    983  * nfs symbolic link service
    984  */
    985 nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
    986 	struct mbuf *mrep, *md, **mrq;
    987 	caddr_t dpos;
    988 	struct ucred *cred;
    989 	u_long xid;
    990 	int *repstat;
    991 	struct proc *p;
    992 {
    993 	struct vattr va;
    994 	struct nameidata nd;
    995 	register struct vattr *vap = &va;
    996 	register u_long *tl;
    997 	register long t1;
    998 	struct nfsv2_sattr *sp;
    999 	caddr_t bpos;
   1000 	struct uio io;
   1001 	struct iovec iv;
   1002 	int error = 0;
   1003 	char *pathcp, *cp2;
   1004 	struct mbuf *mb, *mreq;
   1005 	nfsv2fh_t nfh;
   1006 	fhandle_t *fhp;
   1007 	long len, len2;
   1008 
   1009 	pathcp = (char *)0;
   1010 	fhp = &nfh.fh_generic;
   1011 	nfsm_srvmtofh(fhp);
   1012 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
   1013 	nd.ni_cred = cred;
   1014 	nd.ni_nameiop = CREATE | LOCKPARENT;
   1015 	if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
   1016 		goto out;
   1017 	nfsm_strsiz(len2, NFS_MAXPATHLEN);
   1018 	MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
   1019 	iv.iov_base = pathcp;
   1020 	iv.iov_len = len2;
   1021 	io.uio_resid = len2;
   1022 	io.uio_offset = 0;
   1023 	io.uio_iov = &iv;
   1024 	io.uio_iovcnt = 1;
   1025 	io.uio_segflg = UIO_SYSSPACE;
   1026 	io.uio_rw = UIO_READ;
   1027 	io.uio_procp = (struct proc *)0;
   1028 	nfsm_mtouio(&io, len2);
   1029 	nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
   1030 	*(pathcp + len2) = '\0';
   1031 	if (nd.ni_vp) {
   1032 		VOP_ABORTOP(&nd);
   1033 		if (nd.ni_dvp == nd.ni_vp)
   1034 			vrele(nd.ni_dvp);
   1035 		else
   1036 			vput(nd.ni_dvp);
   1037 		vrele(nd.ni_vp);
   1038 		error = EEXIST;
   1039 		goto out;
   1040 	}
   1041 	VATTR_NULL(vap);
   1042 	vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);
   1043 	error = VOP_SYMLINK(&nd, vap, pathcp, p);
   1044 out:
   1045 	if (pathcp)
   1046 		FREE(pathcp, M_TEMP);
   1047 	nfsm_reply(0);
   1048 	return (error);
   1049 nfsmout:
   1050 	VOP_ABORTOP(&nd);
   1051 	if (nd.ni_dvp == nd.ni_vp)
   1052 		vrele(nd.ni_dvp);
   1053 	else
   1054 		vput(nd.ni_dvp);
   1055 	if (nd.ni_vp)
   1056 		vrele(nd.ni_vp);
   1057 	if (pathcp)
   1058 		FREE(pathcp, M_TEMP);
   1059 	return (error);
   1060 }
   1061 
   1062 /*
   1063  * nfs mkdir service
   1064  */
   1065 nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
   1066 	struct mbuf *mrep, *md, **mrq;
   1067 	caddr_t dpos;
   1068 	struct ucred *cred;
   1069 	u_long xid;
   1070 	int *repstat;
   1071 	struct proc *p;
   1072 {
   1073 	struct vattr va;
   1074 	register struct vattr *vap = &va;
   1075 	register struct nfsv2_fattr *fp;
   1076 	struct nameidata nd;
   1077 	register caddr_t cp;
   1078 	register u_long *tl;
   1079 	register long t1;
   1080 	caddr_t bpos;
   1081 	int error = 0;
   1082 	char *cp2;
   1083 	struct mbuf *mb, *mb2, *mreq;
   1084 	struct vnode *vp;
   1085 	nfsv2fh_t nfh;
   1086 	fhandle_t *fhp;
   1087 	long len;
   1088 
   1089 	fhp = &nfh.fh_generic;
   1090 	nfsm_srvmtofh(fhp);
   1091 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
   1092 	nd.ni_cred = cred;
   1093 	nd.ni_nameiop = CREATE | LOCKPARENT;
   1094 	if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
   1095 		nfsm_reply(0);
   1096 	nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
   1097 	VATTR_NULL(vap);
   1098 	vap->va_type = VDIR;
   1099 	vap->va_mode = nfstov_mode(*tl++);
   1100 	vp = nd.ni_vp;
   1101 	if (vp != NULL) {
   1102 		VOP_ABORTOP(&nd);
   1103 		if (nd.ni_dvp == vp)
   1104 			vrele(nd.ni_dvp);
   1105 		else
   1106 			vput(nd.ni_dvp);
   1107 		vrele(vp);
   1108 		error = EEXIST;
   1109 		nfsm_reply(0);
   1110 	}
   1111 	if (error = VOP_MKDIR(&nd, vap, p))
   1112 		nfsm_reply(0);
   1113 	vp = nd.ni_vp;
   1114 	bzero((caddr_t)fhp, sizeof(nfh));
   1115 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
   1116 	if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
   1117 		vput(vp);
   1118 		nfsm_reply(0);
   1119 	}
   1120 	error = VOP_GETATTR(vp, vap, cred, p);
   1121 	vput(vp);
   1122 	nfsm_reply(NFSX_FH+NFSX_FATTR);
   1123 	nfsm_srvfhtom(fhp);
   1124 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
   1125 	nfsm_srvfillattr;
   1126 	return (error);
   1127 nfsmout:
   1128 	VOP_ABORTOP(&nd);
   1129 	if (nd.ni_dvp == nd.ni_vp)
   1130 		vrele(nd.ni_dvp);
   1131 	else
   1132 		vput(nd.ni_dvp);
   1133 	if (nd.ni_vp)
   1134 		vrele(nd.ni_vp);
   1135 	return (error);
   1136 }
   1137 
   1138 /*
   1139  * nfs rmdir service
   1140  */
   1141 nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
   1142 	struct mbuf *mrep, *md, **mrq;
   1143 	caddr_t dpos;
   1144 	struct ucred *cred;
   1145 	u_long xid;
   1146 	int *repstat;
   1147 	struct proc *p;
   1148 {
   1149 	register u_long *tl;
   1150 	register long t1;
   1151 	caddr_t bpos;
   1152 	int error = 0;
   1153 	char *cp2;
   1154 	struct mbuf *mb, *mreq;
   1155 	struct vnode *vp;
   1156 	nfsv2fh_t nfh;
   1157 	fhandle_t *fhp;
   1158 	long len;
   1159 	struct nameidata nd;
   1160 
   1161 	fhp = &nfh.fh_generic;
   1162 	nfsm_srvmtofh(fhp);
   1163 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
   1164 	nd.ni_cred = cred;
   1165 	nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
   1166 	if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
   1167 		nfsm_reply(0);
   1168 	vp = nd.ni_vp;
   1169 	if (vp->v_type != VDIR) {
   1170 		error = ENOTDIR;
   1171 		goto out;
   1172 	}
   1173 	/*
   1174 	 * No rmdir "." please.
   1175 	 */
   1176 	if (nd.ni_dvp == vp) {
   1177 		error = EINVAL;
   1178 		goto out;
   1179 	}
   1180 	/*
   1181 	 * The root of a mounted filesystem cannot be deleted.
   1182 	 */
   1183 	if (vp->v_flag & VROOT)
   1184 		error = EBUSY;
   1185 out:
   1186 	if (!error) {
   1187 		error = VOP_RMDIR(&nd, p);
   1188 	} else {
   1189 		VOP_ABORTOP(&nd);
   1190 		if (nd.ni_dvp == nd.ni_vp)
   1191 			vrele(nd.ni_dvp);
   1192 		else
   1193 			vput(nd.ni_dvp);
   1194 		vput(vp);
   1195 	}
   1196 	nfsm_reply(0);
   1197 	nfsm_srvdone;
   1198 }
   1199 
   1200 /*
   1201  * nfs readdir service
   1202  * - mallocs what it thinks is enough to read
   1203  *	count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
   1204  * - calls VOP_READDIR()
   1205  * - loops around building the reply
   1206  *	if the output generated exceeds count break out of loop
   1207  *	The nfsm_clget macro is used here so that the reply will be packed
   1208  *	tightly in mbuf clusters.
   1209  * - it only knows that it has encountered eof when the VOP_READDIR()
   1210  *	reads nothing
   1211  * - as such one readdir rpc will return eof false although you are there
   1212  *	and then the next will return eof
   1213  * - it trims out records with d_ino == 0
   1214  *	this doesn't matter for Unix clients, but they might confuse clients
   1215  *	for other os'.
   1216  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
   1217  *	than requested, but this may not apply to all filesystems. For
   1218  *	example, client NFS does not { although it is never remote mounted
   1219  *	anyhow }
   1220  * PS: The NFS protocol spec. does not clarify what the "count" byte
   1221  *	argument is a count of.. just name strings and file id's or the
   1222  *	entire reply rpc or ...
   1223  *	I tried just file name and id sizes and it confused the Sun client,
   1224  *	so I am using the full rpc size now. The "paranoia.." comment refers
   1225  *	to including the status longwords that are not a part of the dir.
   1226  *	"entry" structures, but are in the rpc.
   1227  */
   1228 nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
   1229 	struct mbuf **mrq;
   1230 	struct mbuf *mrep, *md;
   1231 	caddr_t dpos;
   1232 	struct ucred *cred;
   1233 	u_long xid;
   1234 	int *repstat;
   1235 	struct proc *p;
   1236 {
   1237 	register char *bp, *be;
   1238 	register struct mbuf *mp;
   1239 	register struct direct *dp;
   1240 	register caddr_t cp;
   1241 	register u_long *tl;
   1242 	register long t1;
   1243 	caddr_t bpos;
   1244 	int error = 0;
   1245 	char *cp2;
   1246 	struct mbuf *mb, *mb2, *mreq;
   1247 	char *cpos, *cend;
   1248 	int len, nlen, rem, xfer, tsiz, i;
   1249 	struct vnode *vp;
   1250 	struct mbuf *mp2, *mp3;
   1251 	nfsv2fh_t nfh;
   1252 	fhandle_t *fhp;
   1253 	struct uio io;
   1254 	struct iovec iv;
   1255 	int siz, cnt, fullsiz, eofflag;
   1256 	u_long on;
   1257 	char *rbuf;
   1258 	off_t off, toff;
   1259 
   1260 	fhp = &nfh.fh_generic;
   1261 	nfsm_srvmtofh(fhp);
   1262 	nfsm_disect(tl, u_long *, 2*NFSX_UNSIGNED);
   1263 	toff = fxdr_unsigned(off_t, *tl++);
   1264 	off = (toff & ~(NFS_DIRBLKSIZ-1));
   1265 	on = (toff & (NFS_DIRBLKSIZ-1));
   1266 	cnt = fxdr_unsigned(int, *tl);
   1267 	siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
   1268 	if (cnt > NFS_MAXREADDIR)
   1269 		siz = NFS_MAXREADDIR;
   1270 	fullsiz = siz;
   1271 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
   1272 		nfsm_reply(0);
   1273 	if (error = nfsrv_access(vp, VEXEC, cred, p)) {
   1274 		vput(vp);
   1275 		nfsm_reply(0);
   1276 	}
   1277 	VOP_UNLOCK(vp);
   1278 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
   1279 again:
   1280 	iv.iov_base = rbuf;
   1281 	iv.iov_len = fullsiz;
   1282 	io.uio_iov = &iv;
   1283 	io.uio_iovcnt = 1;
   1284 	io.uio_offset = off;
   1285 	io.uio_resid = fullsiz;
   1286 	io.uio_segflg = UIO_SYSSPACE;
   1287 	io.uio_rw = UIO_READ;
   1288 	io.uio_procp = (struct proc *)0;
   1289 	error = VOP_READDIR(vp, &io, cred, &eofflag);
   1290 	off = io.uio_offset;
   1291 	if (error) {
   1292 		vrele(vp);
   1293 		free((caddr_t)rbuf, M_TEMP);
   1294 		nfsm_reply(0);
   1295 	}
   1296 	if (io.uio_resid) {
   1297 		siz -= io.uio_resid;
   1298 
   1299 		/*
   1300 		 * If nothing read, return eof
   1301 		 * rpc reply
   1302 		 */
   1303 		if (siz == 0) {
   1304 			vrele(vp);
   1305 			nfsm_reply(2*NFSX_UNSIGNED);
   1306 			nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
   1307 			*tl++ = nfs_false;
   1308 			*tl = nfs_true;
   1309 			FREE((caddr_t)rbuf, M_TEMP);
   1310 			return (0);
   1311 		}
   1312 	}
   1313 
   1314 	/*
   1315 	 * Check for degenerate cases of nothing useful read.
   1316 	 * If so go try again
   1317 	 */
   1318 	cpos = rbuf + on;
   1319 	cend = rbuf + siz;
   1320 	dp = (struct direct *)cpos;
   1321 	while (cpos < cend && dp->d_ino == 0) {
   1322 		cpos += dp->d_reclen;
   1323 		dp = (struct direct *)cpos;
   1324 	}
   1325 	if (cpos >= cend) {
   1326 		toff = off;
   1327 		siz = fullsiz;
   1328 		on = 0;
   1329 		goto again;
   1330 	}
   1331 
   1332 	cpos = rbuf + on;
   1333 	cend = rbuf + siz;
   1334 	dp = (struct direct *)cpos;
   1335 	vrele(vp);
   1336 	len = 3*NFSX_UNSIGNED;	/* paranoia, probably can be 0 */
   1337 	bp = be = (caddr_t)0;
   1338 	mp3 = (struct mbuf *)0;
   1339 	nfsm_reply(siz);
   1340 
   1341 	/* Loop through the records and build reply */
   1342 	while (cpos < cend) {
   1343 		if (dp->d_ino != 0) {
   1344 			nlen = dp->d_namlen;
   1345 			rem = nfsm_rndup(nlen)-nlen;
   1346 
   1347 			/*
   1348 			 * As noted above, the NFS spec. is not clear about what
   1349 			 * should be included in "count" as totalled up here in
   1350 			 * "len".
   1351 			 */
   1352 			len += (4*NFSX_UNSIGNED+nlen+rem);
   1353 			if (len > cnt) {
   1354 				eofflag = 0;
   1355 				break;
   1356 			}
   1357 
   1358 			/* Build the directory record xdr from the direct entry */
   1359 			nfsm_clget;
   1360 			*tl = nfs_true;
   1361 			bp += NFSX_UNSIGNED;
   1362 			nfsm_clget;
   1363 			*tl = txdr_unsigned(dp->d_ino);
   1364 			bp += NFSX_UNSIGNED;
   1365 			nfsm_clget;
   1366 			*tl = txdr_unsigned(nlen);
   1367 			bp += NFSX_UNSIGNED;
   1368 
   1369 			/* And loop arround copying the name */
   1370 			xfer = nlen;
   1371 			cp = dp->d_name;
   1372 			while (xfer > 0) {
   1373 				nfsm_clget;
   1374 				if ((bp+xfer) > be)
   1375 					tsiz = be-bp;
   1376 				else
   1377 					tsiz = xfer;
   1378 				bcopy(cp, bp, tsiz);
   1379 				bp += tsiz;
   1380 				xfer -= tsiz;
   1381 				if (xfer > 0)
   1382 					cp += tsiz;
   1383 			}
   1384 			/* And null pad to a long boundary */
   1385 			for (i = 0; i < rem; i++)
   1386 				*bp++ = '\0';
   1387 			nfsm_clget;
   1388 
   1389 			/* Finish off the record */
   1390 			toff += dp->d_reclen;
   1391 			*tl = txdr_unsigned(toff);
   1392 			bp += NFSX_UNSIGNED;
   1393 		} else
   1394 			toff += dp->d_reclen;
   1395 		cpos += dp->d_reclen;
   1396 		dp = (struct direct *)cpos;
   1397 	}
   1398 	nfsm_clget;
   1399 	*tl = nfs_false;
   1400 	bp += NFSX_UNSIGNED;
   1401 	nfsm_clget;
   1402 	if (eofflag)
   1403 		*tl = nfs_true;
   1404 	else
   1405 		*tl = nfs_false;
   1406 	bp += NFSX_UNSIGNED;
   1407 	if (bp < be)
   1408 		mp->m_len = bp-mtod(mp, caddr_t);
   1409 	mb->m_next = mp3;
   1410 	FREE(rbuf, M_TEMP);
   1411 	nfsm_srvdone;
   1412 }
   1413 
   1414 /*
   1415  * nfs statfs service
   1416  */
   1417 nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat, p)
   1418 	struct mbuf **mrq;
   1419 	struct mbuf *mrep, *md;
   1420 	caddr_t dpos;
   1421 	struct ucred *cred;
   1422 	u_long xid;
   1423 	int *repstat;
   1424 	struct proc *p;
   1425 {
   1426 	register struct statfs *sf;
   1427 	register struct nfsv2_statfs *sfp;
   1428 	register u_long *tl;
   1429 	register long t1;
   1430 	caddr_t bpos;
   1431 	int error = 0;
   1432 	char *cp2;
   1433 	struct mbuf *mb, *mb2, *mreq;
   1434 	struct vnode *vp;
   1435 	nfsv2fh_t nfh;
   1436 	fhandle_t *fhp;
   1437 	struct statfs statfs;
   1438 
   1439 	fhp = &nfh.fh_generic;
   1440 	nfsm_srvmtofh(fhp);
   1441 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
   1442 		nfsm_reply(0);
   1443 	sf = &statfs;
   1444 	error = VFS_STATFS(vp->v_mount, sf, p);
   1445 	vput(vp);
   1446 	nfsm_reply(NFSX_STATFS);
   1447 	nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
   1448 	sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
   1449 	sfp->sf_bsize = txdr_unsigned(sf->f_fsize);
   1450 	sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
   1451 	sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
   1452 	sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
   1453 	nfsm_srvdone;
   1454 }
   1455 
   1456 /*
   1457  * Null operation, used by clients to ping server
   1458  */
   1459 /* ARGSUSED */
   1460 nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat, p)
   1461 	struct mbuf **mrq;
   1462 	struct mbuf *mrep, *md;
   1463 	caddr_t dpos;
   1464 	struct ucred *cred;
   1465 	u_long xid;
   1466 	int *repstat;
   1467 	struct proc *p;
   1468 {
   1469 	caddr_t bpos;
   1470 	int error = 0;
   1471 	struct mbuf *mb, *mreq;
   1472 
   1473 	error = VNOVAL;
   1474 	nfsm_reply(0);
   1475 	return (error);
   1476 }
   1477 
   1478 /*
   1479  * No operation, used for obsolete procedures
   1480  */
   1481 /* ARGSUSED */
   1482 nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat, p)
   1483 	struct mbuf **mrq;
   1484 	struct mbuf *mrep, *md;
   1485 	caddr_t dpos;
   1486 	struct ucred *cred;
   1487 	u_long xid;
   1488 	int *repstat;
   1489 	struct proc *p;
   1490 {
   1491 	caddr_t bpos;
   1492 	int error;					/* 08 Sep 92*/
   1493 	struct mbuf *mb, *mreq;
   1494 
   1495 	if (*repstat)					/* 08 Sep 92*/
   1496 		error = *repstat;
   1497 	else
   1498 		error = EPROCUNAVAIL;
   1499 	nfsm_reply(0);
   1500 	return (error);
   1501 }
   1502 
   1503 /*
   1504  * Perform access checking for vnodes obtained from file handles that would
   1505  * refer to files already opened by a Unix client. You cannot just use
   1506  * vn_writechk() and VOP_ACCESS() for two reasons.
   1507  * 1 - You must check for MNT_EXRDONLY as well as MNT_RDONLY for the write case
   1508  * 2 - The owner is to be given access irrespective of mode bits so that
   1509  *     processes that chmod after opening a file don't break. I don't like
   1510  *     this because it opens a security hole, but since the nfs server opens
   1511  *     a security hole the size of a barn door anyhow, what the heck.
   1512  */
   1513 nfsrv_access(vp, flags, cred, p)
   1514 	register struct vnode *vp;
   1515 	int flags;
   1516 	register struct ucred *cred;
   1517 	struct proc *p;
   1518 {
   1519 	struct vattr vattr;
   1520 	int error;
   1521 	if (flags & VWRITE) {
   1522 		/* Just vn_writechk() changed to check MNT_EXRDONLY */
   1523 		/*
   1524 		 * Disallow write attempts on read-only file systems;
   1525 		 * unless the file is a socket or a block or character
   1526 		 * device resident on the file system.
   1527 		 */
   1528 		if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) {
   1529 			switch (vp->v_type) {
   1530 			case VREG: case VDIR: case VLNK:
   1531 				return (EROFS);
   1532 			}
   1533 		}
   1534 		/*
   1535 		 * If there's shared text associated with
   1536 		 * the inode, try to free it up once.  If
   1537 		 * we fail, we can't allow writing.
   1538 		 */
   1539 		if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
   1540 			return (ETXTBSY);
   1541 	}
   1542 	if (error = VOP_GETATTR(vp, &vattr, cred, p))
   1543 		return (error);
   1544 	if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
   1545 	    cred->cr_uid != vattr.va_uid)
   1546 		return (error);
   1547 	return (0);
   1548 }
   1549