Home | History | Annotate | Line # | Download | only in nfs
nfs_serv.c revision 1.1.1.4
      1      1.1   cgd /*
      2  1.1.1.2  fvdl  * Copyright (c) 1989, 1993
      3  1.1.1.2  fvdl  *	The Regents of the University of California.  All rights reserved.
      4      1.1   cgd  *
      5      1.1   cgd  * This code is derived from software contributed to Berkeley by
      6      1.1   cgd  * Rick Macklem at The University of Guelph.
      7      1.1   cgd  *
      8      1.1   cgd  * Redistribution and use in source and binary forms, with or without
      9      1.1   cgd  * modification, are permitted provided that the following conditions
     10      1.1   cgd  * are met:
     11      1.1   cgd  * 1. Redistributions of source code must retain the above copyright
     12      1.1   cgd  *    notice, this list of conditions and the following disclaimer.
     13      1.1   cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1   cgd  *    notice, this list of conditions and the following disclaimer in the
     15      1.1   cgd  *    documentation and/or other materials provided with the distribution.
     16      1.1   cgd  * 3. All advertising materials mentioning features or use of this software
     17      1.1   cgd  *    must display the following acknowledgement:
     18      1.1   cgd  *	This product includes software developed by the University of
     19      1.1   cgd  *	California, Berkeley and its contributors.
     20      1.1   cgd  * 4. Neither the name of the University nor the names of its contributors
     21      1.1   cgd  *    may be used to endorse or promote products derived from this software
     22      1.1   cgd  *    without specific prior written permission.
     23      1.1   cgd  *
     24      1.1   cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25      1.1   cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26      1.1   cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27      1.1   cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28      1.1   cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29      1.1   cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30      1.1   cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31      1.1   cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32      1.1   cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33      1.1   cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34      1.1   cgd  * SUCH DAMAGE.
     35      1.1   cgd  *
     36  1.1.1.4  fvdl  *	@(#)nfs_serv.c	8.8 (Berkeley) 7/31/95
     37      1.1   cgd  */
     38      1.1   cgd 
     39      1.1   cgd /*
     40  1.1.1.3  fvdl  * nfs version 2 and 3 server calls to vnode ops
     41      1.1   cgd  * - these routines generally have 3 phases
     42      1.1   cgd  *   1 - break down and validate rpc request in mbuf list
     43      1.1   cgd  *   2 - do the vnode ops for the request
     44      1.1   cgd  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
     45      1.1   cgd  *   3 - build the rpc reply in an mbuf list
     46      1.1   cgd  *   nb:
     47      1.1   cgd  *	- do not mix the phases, since the nfsm_?? macros can return failures
     48      1.1   cgd  *	  on a bad rpc or similar and do not do any vrele() or vput()'s
     49      1.1   cgd  *
     50      1.1   cgd  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
     51      1.1   cgd  *	error number iff error != 0 whereas
     52      1.1   cgd  *	returning an error from the server function implies a fatal error
     53      1.1   cgd  *	such as a badly constructed rpc request that should be dropped without
     54      1.1   cgd  *	a reply.
     55  1.1.1.3  fvdl  *	For Version 3, nfsm_reply() does not return for the error case, since
     56  1.1.1.3  fvdl  *	most version 3 rpcs return more than the status for error cases.
     57      1.1   cgd  */
     58      1.1   cgd 
     59  1.1.1.2  fvdl #include <sys/param.h>
     60  1.1.1.2  fvdl #include <sys/systm.h>
     61  1.1.1.2  fvdl #include <sys/proc.h>
     62  1.1.1.2  fvdl #include <sys/file.h>
     63  1.1.1.2  fvdl #include <sys/namei.h>
     64  1.1.1.2  fvdl #include <sys/vnode.h>
     65  1.1.1.2  fvdl #include <sys/mount.h>
     66  1.1.1.3  fvdl #include <sys/socket.h>
     67  1.1.1.3  fvdl #include <sys/socketvar.h>
     68  1.1.1.2  fvdl #include <sys/mbuf.h>
     69  1.1.1.2  fvdl #include <sys/dirent.h>
     70  1.1.1.2  fvdl #include <sys/stat.h>
     71  1.1.1.3  fvdl #include <sys/kernel.h>
     72  1.1.1.3  fvdl #include <ufs/ufs/dir.h>
     73  1.1.1.2  fvdl 
     74  1.1.1.2  fvdl #include <vm/vm.h>
     75  1.1.1.2  fvdl 
     76  1.1.1.3  fvdl #include <nfs/nfsproto.h>
     77  1.1.1.2  fvdl #include <nfs/rpcv2.h>
     78  1.1.1.2  fvdl #include <nfs/nfs.h>
     79  1.1.1.2  fvdl #include <nfs/xdr_subs.h>
     80  1.1.1.2  fvdl #include <nfs/nfsm_subs.h>
     81  1.1.1.2  fvdl #include <nfs/nqnfs.h>
     82      1.1   cgd 
     83      1.1   cgd /* Global vars */
     84      1.1   cgd extern u_long nfs_xdrneg1;
     85      1.1   cgd extern u_long nfs_false, nfs_true;
     86  1.1.1.3  fvdl extern enum vtype nv3tov_type[8];
     87  1.1.1.3  fvdl extern struct nfsstats nfsstats;
     88  1.1.1.3  fvdl nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
     89      1.1   cgd 		      NFCHR, NFNON };
     90  1.1.1.3  fvdl nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
     91  1.1.1.3  fvdl 		      NFFIFO, NFNON };
     92  1.1.1.3  fvdl int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
     93      1.1   cgd 
     94      1.1   cgd /*
     95  1.1.1.3  fvdl  * nfs v3 access service
     96  1.1.1.2  fvdl  */
     97  1.1.1.3  fvdl int
     98  1.1.1.3  fvdl nfsrv3_access(nfsd, slp, procp, mrq)
     99  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
    100  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    101  1.1.1.3  fvdl 	struct proc *procp;
    102  1.1.1.3  fvdl 	struct mbuf **mrq;
    103  1.1.1.2  fvdl {
    104  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
    105  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
    106  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
    107  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
    108  1.1.1.2  fvdl 	struct vnode *vp;
    109  1.1.1.3  fvdl 	nfsfh_t nfh;
    110  1.1.1.2  fvdl 	fhandle_t *fhp;
    111  1.1.1.2  fvdl 	register u_long *tl;
    112  1.1.1.2  fvdl 	register long t1;
    113  1.1.1.2  fvdl 	caddr_t bpos;
    114  1.1.1.3  fvdl 	int error = 0, rdonly, cache, getret;
    115  1.1.1.2  fvdl 	char *cp2;
    116  1.1.1.3  fvdl 	struct mbuf *mb, *mreq, *mb2;
    117  1.1.1.3  fvdl 	struct vattr vattr, *vap = &vattr;
    118  1.1.1.3  fvdl 	u_long testmode, nfsmode;
    119  1.1.1.2  fvdl 	u_quad_t frev;
    120  1.1.1.2  fvdl 
    121  1.1.1.3  fvdl #ifndef nolint
    122  1.1.1.3  fvdl 	cache = 0;
    123  1.1.1.3  fvdl #endif
    124  1.1.1.2  fvdl 	fhp = &nfh.fh_generic;
    125  1.1.1.2  fvdl 	nfsm_srvmtofh(fhp);
    126  1.1.1.3  fvdl 	nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
    127  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
    128  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
    129  1.1.1.3  fvdl 		nfsm_reply(NFSX_UNSIGNED);
    130  1.1.1.3  fvdl 		nfsm_srvpostop_attr(1, (struct vattr *)0);
    131  1.1.1.3  fvdl 		return (0);
    132  1.1.1.3  fvdl 	}
    133  1.1.1.3  fvdl 	nfsmode = fxdr_unsigned(u_long, *tl);
    134  1.1.1.3  fvdl 	if ((nfsmode & NFSV3ACCESS_READ) &&
    135  1.1.1.3  fvdl 		nfsrv_access(vp, VREAD, cred, rdonly, procp))
    136  1.1.1.3  fvdl 		nfsmode &= ~NFSV3ACCESS_READ;
    137  1.1.1.3  fvdl 	if (vp->v_type == VDIR)
    138  1.1.1.3  fvdl 		testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
    139  1.1.1.3  fvdl 			NFSV3ACCESS_DELETE);
    140  1.1.1.3  fvdl 	else
    141  1.1.1.3  fvdl 		testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
    142  1.1.1.3  fvdl 	if ((nfsmode & testmode) &&
    143  1.1.1.3  fvdl 		nfsrv_access(vp, VWRITE, cred, rdonly, procp))
    144  1.1.1.3  fvdl 		nfsmode &= ~testmode;
    145  1.1.1.3  fvdl 	if (vp->v_type == VDIR)
    146  1.1.1.3  fvdl 		testmode = NFSV3ACCESS_LOOKUP;
    147  1.1.1.3  fvdl 	else
    148  1.1.1.3  fvdl 		testmode = NFSV3ACCESS_EXECUTE;
    149  1.1.1.3  fvdl 	if ((nfsmode & testmode) &&
    150  1.1.1.3  fvdl 		nfsrv_access(vp, VEXEC, cred, rdonly, procp))
    151  1.1.1.3  fvdl 		nfsmode &= ~testmode;
    152  1.1.1.3  fvdl 	getret = VOP_GETATTR(vp, vap, cred, procp);
    153  1.1.1.2  fvdl 	vput(vp);
    154  1.1.1.3  fvdl 	nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
    155  1.1.1.3  fvdl 	nfsm_srvpostop_attr(getret, vap);
    156  1.1.1.3  fvdl 	nfsm_build(tl, u_long *, NFSX_UNSIGNED);
    157  1.1.1.3  fvdl 	*tl = txdr_unsigned(nfsmode);
    158  1.1.1.2  fvdl 	nfsm_srvdone;
    159  1.1.1.2  fvdl }
    160  1.1.1.2  fvdl 
    161  1.1.1.2  fvdl /*
    162      1.1   cgd  * nfs getattr service
    163      1.1   cgd  */
    164  1.1.1.3  fvdl int
    165  1.1.1.3  fvdl nfsrv_getattr(nfsd, slp, procp, mrq)
    166  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
    167  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    168  1.1.1.3  fvdl 	struct proc *procp;
    169  1.1.1.3  fvdl 	struct mbuf **mrq;
    170      1.1   cgd {
    171  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
    172  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
    173  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
    174  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
    175  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
    176      1.1   cgd 	struct vattr va;
    177      1.1   cgd 	register struct vattr *vap = &va;
    178      1.1   cgd 	struct vnode *vp;
    179  1.1.1.3  fvdl 	nfsfh_t nfh;
    180      1.1   cgd 	fhandle_t *fhp;
    181      1.1   cgd 	register u_long *tl;
    182      1.1   cgd 	register long t1;
    183      1.1   cgd 	caddr_t bpos;
    184  1.1.1.2  fvdl 	int error = 0, rdonly, cache;
    185      1.1   cgd 	char *cp2;
    186      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
    187  1.1.1.2  fvdl 	u_quad_t frev;
    188      1.1   cgd 
    189      1.1   cgd 	fhp = &nfh.fh_generic;
    190      1.1   cgd 	nfsm_srvmtofh(fhp);
    191  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
    192  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
    193      1.1   cgd 		nfsm_reply(0);
    194  1.1.1.3  fvdl 		return (0);
    195  1.1.1.3  fvdl 	}
    196  1.1.1.3  fvdl 	nqsrv_getl(vp, ND_READ);
    197  1.1.1.3  fvdl 	error = VOP_GETATTR(vp, vap, cred, procp);
    198      1.1   cgd 	vput(vp);
    199  1.1.1.3  fvdl 	nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
    200  1.1.1.3  fvdl 	if (error)
    201  1.1.1.3  fvdl 		return (0);
    202  1.1.1.3  fvdl 	nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
    203  1.1.1.3  fvdl 	nfsm_srvfillattr(vap, fp);
    204      1.1   cgd 	nfsm_srvdone;
    205      1.1   cgd }
    206      1.1   cgd 
    207      1.1   cgd /*
    208      1.1   cgd  * nfs setattr service
    209      1.1   cgd  */
    210  1.1.1.3  fvdl int
    211  1.1.1.3  fvdl nfsrv_setattr(nfsd, slp, procp, mrq)
    212  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
    213  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    214  1.1.1.3  fvdl 	struct proc *procp;
    215  1.1.1.3  fvdl 	struct mbuf **mrq;
    216      1.1   cgd {
    217  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
    218  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
    219  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
    220  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
    221  1.1.1.3  fvdl 	struct vattr va, preat;
    222      1.1   cgd 	register struct vattr *vap = &va;
    223      1.1   cgd 	register struct nfsv2_sattr *sp;
    224  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
    225      1.1   cgd 	struct vnode *vp;
    226  1.1.1.3  fvdl 	nfsfh_t nfh;
    227      1.1   cgd 	fhandle_t *fhp;
    228      1.1   cgd 	register u_long *tl;
    229      1.1   cgd 	register long t1;
    230      1.1   cgd 	caddr_t bpos;
    231  1.1.1.3  fvdl 	int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
    232  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
    233      1.1   cgd 	char *cp2;
    234      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
    235  1.1.1.3  fvdl 	u_quad_t frev;
    236  1.1.1.3  fvdl 	struct timespec guard;
    237      1.1   cgd 
    238      1.1   cgd 	fhp = &nfh.fh_generic;
    239      1.1   cgd 	nfsm_srvmtofh(fhp);
    240      1.1   cgd 	VATTR_NULL(vap);
    241  1.1.1.3  fvdl 	if (v3) {
    242  1.1.1.3  fvdl 		nfsm_srvsattr(vap);
    243  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
    244  1.1.1.3  fvdl 		gcheck = fxdr_unsigned(int, *tl);
    245  1.1.1.3  fvdl 		if (gcheck) {
    246  1.1.1.3  fvdl 			nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
    247  1.1.1.3  fvdl 			fxdr_nfsv3time(tl, &guard);
    248  1.1.1.3  fvdl 		}
    249  1.1.1.3  fvdl 	} else {
    250  1.1.1.3  fvdl 		nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
    251  1.1.1.3  fvdl 		/*
    252  1.1.1.3  fvdl 		 * Nah nah nah nah na nah
    253  1.1.1.3  fvdl 		 * There is a bug in the Sun client that puts 0xffff in the mode
    254  1.1.1.3  fvdl 		 * field of sattr when it should put in 0xffffffff. The u_short
    255  1.1.1.3  fvdl 		 * doesn't sign extend.
    256  1.1.1.3  fvdl 		 * --> check the low order 2 bytes for 0xffff
    257  1.1.1.3  fvdl 		 */
    258  1.1.1.3  fvdl 		if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
    259  1.1.1.3  fvdl 			vap->va_mode = nfstov_mode(sp->sa_mode);
    260  1.1.1.3  fvdl 		if (sp->sa_uid != nfs_xdrneg1)
    261  1.1.1.3  fvdl 			vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
    262  1.1.1.3  fvdl 		if (sp->sa_gid != nfs_xdrneg1)
    263  1.1.1.3  fvdl 			vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
    264  1.1.1.3  fvdl 		if (sp->sa_size != nfs_xdrneg1)
    265  1.1.1.3  fvdl 			vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
    266  1.1.1.3  fvdl 		if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
    267  1.1.1.2  fvdl #ifdef notyet
    268  1.1.1.3  fvdl 			fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
    269  1.1.1.2  fvdl #else
    270  1.1.1.2  fvdl 			vap->va_atime.ts_sec =
    271  1.1.1.3  fvdl 				fxdr_unsigned(long, sp->sa_atime.nfsv2_sec);
    272  1.1.1.2  fvdl 			vap->va_atime.ts_nsec = 0;
    273  1.1.1.2  fvdl #endif
    274  1.1.1.2  fvdl 		}
    275  1.1.1.3  fvdl 		if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
    276  1.1.1.3  fvdl 			fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
    277  1.1.1.3  fvdl 
    278  1.1.1.3  fvdl 	}
    279  1.1.1.3  fvdl 
    280  1.1.1.3  fvdl 	/*
    281  1.1.1.3  fvdl 	 * Now that we have all the fields, lets do it.
    282  1.1.1.3  fvdl 	 */
    283  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
    284  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
    285  1.1.1.3  fvdl 		nfsm_reply(2 * NFSX_UNSIGNED);
    286  1.1.1.3  fvdl 		nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
    287  1.1.1.3  fvdl 		return (0);
    288  1.1.1.3  fvdl 	}
    289  1.1.1.3  fvdl 	nqsrv_getl(vp, ND_WRITE);
    290  1.1.1.3  fvdl 	if (v3) {
    291  1.1.1.3  fvdl 		error = preat_ret = VOP_GETATTR(vp, &preat, cred, procp);
    292  1.1.1.3  fvdl 		if (!error && gcheck &&
    293  1.1.1.3  fvdl 			(preat.va_ctime.ts_sec != guard.ts_sec ||
    294  1.1.1.3  fvdl 			 preat.va_ctime.ts_nsec != guard.ts_nsec))
    295  1.1.1.3  fvdl 			error = NFSERR_NOT_SYNC;
    296  1.1.1.3  fvdl 		if (error) {
    297  1.1.1.3  fvdl 			vput(vp);
    298  1.1.1.3  fvdl 			nfsm_reply(NFSX_WCCDATA(v3));
    299  1.1.1.3  fvdl 			nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
    300  1.1.1.3  fvdl 			return (0);
    301  1.1.1.3  fvdl 		}
    302  1.1.1.2  fvdl 	}
    303  1.1.1.2  fvdl 
    304      1.1   cgd 	/*
    305  1.1.1.2  fvdl 	 * If the size is being changed write acces is required, otherwise
    306  1.1.1.2  fvdl 	 * just check for a read only file system.
    307      1.1   cgd 	 */
    308  1.1.1.2  fvdl 	if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
    309  1.1.1.2  fvdl 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
    310  1.1.1.2  fvdl 			error = EROFS;
    311  1.1.1.2  fvdl 			goto out;
    312  1.1.1.2  fvdl 		}
    313  1.1.1.2  fvdl 	} else {
    314  1.1.1.2  fvdl 		if (vp->v_type == VDIR) {
    315  1.1.1.2  fvdl 			error = EISDIR;
    316  1.1.1.2  fvdl 			goto out;
    317  1.1.1.2  fvdl 		} else if (error = nfsrv_access(vp, VWRITE, cred, rdonly,
    318  1.1.1.3  fvdl 			procp))
    319  1.1.1.2  fvdl 			goto out;
    320  1.1.1.2  fvdl 	}
    321  1.1.1.3  fvdl 	error = VOP_SETATTR(vp, vap, cred, procp);
    322  1.1.1.3  fvdl 	postat_ret = VOP_GETATTR(vp, vap, cred, procp);
    323  1.1.1.3  fvdl 	if (!error)
    324  1.1.1.3  fvdl 		error = postat_ret;
    325      1.1   cgd out:
    326      1.1   cgd 	vput(vp);
    327  1.1.1.3  fvdl 	nfsm_reply(NFSX_WCCORFATTR(v3));
    328  1.1.1.3  fvdl 	if (v3) {
    329  1.1.1.3  fvdl 		nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
    330  1.1.1.3  fvdl 		return (0);
    331  1.1.1.3  fvdl 	} else {
    332  1.1.1.3  fvdl 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
    333  1.1.1.3  fvdl 		nfsm_srvfillattr(vap, fp);
    334  1.1.1.2  fvdl 	}
    335      1.1   cgd 	nfsm_srvdone;
    336      1.1   cgd }
    337      1.1   cgd 
    338      1.1   cgd /*
    339      1.1   cgd  * nfs lookup rpc
    340      1.1   cgd  */
    341  1.1.1.3  fvdl int
    342  1.1.1.3  fvdl nfsrv_lookup(nfsd, slp, procp, mrq)
    343  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
    344  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    345  1.1.1.3  fvdl 	struct proc *procp;
    346  1.1.1.3  fvdl 	struct mbuf **mrq;
    347      1.1   cgd {
    348  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
    349  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
    350  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
    351  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
    352  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
    353      1.1   cgd 	struct nameidata nd;
    354  1.1.1.3  fvdl 	struct vnode *vp, *dirp;
    355  1.1.1.3  fvdl 	nfsfh_t nfh;
    356      1.1   cgd 	fhandle_t *fhp;
    357      1.1   cgd 	register caddr_t cp;
    358      1.1   cgd 	register u_long *tl;
    359      1.1   cgd 	register long t1;
    360      1.1   cgd 	caddr_t bpos;
    361  1.1.1.3  fvdl 	int error = 0, cache, len, dirattr_ret = 1;
    362  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
    363      1.1   cgd 	char *cp2;
    364      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
    365  1.1.1.3  fvdl 	struct vattr va, dirattr, *vap = &va;
    366  1.1.1.3  fvdl 	u_quad_t frev;
    367      1.1   cgd 
    368      1.1   cgd 	fhp = &nfh.fh_generic;
    369      1.1   cgd 	nfsm_srvmtofh(fhp);
    370  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
    371  1.1.1.2  fvdl 	nd.ni_cnd.cn_cred = cred;
    372  1.1.1.2  fvdl 	nd.ni_cnd.cn_nameiop = LOOKUP;
    373  1.1.1.2  fvdl 	nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
    374  1.1.1.3  fvdl 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
    375  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
    376  1.1.1.3  fvdl 	if (dirp) {
    377  1.1.1.3  fvdl 		if (v3)
    378  1.1.1.3  fvdl 			dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred,
    379  1.1.1.3  fvdl 				procp);
    380  1.1.1.3  fvdl 		vrele(dirp);
    381  1.1.1.3  fvdl 	}
    382  1.1.1.3  fvdl 	if (error) {
    383  1.1.1.3  fvdl 		nfsm_reply(NFSX_POSTOPATTR(v3));
    384  1.1.1.3  fvdl 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
    385  1.1.1.3  fvdl 		return (0);
    386  1.1.1.3  fvdl 	}
    387  1.1.1.3  fvdl 	nqsrv_getl(nd.ni_startdir, ND_READ);
    388  1.1.1.2  fvdl 	vrele(nd.ni_startdir);
    389  1.1.1.2  fvdl 	FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
    390      1.1   cgd 	vp = nd.ni_vp;
    391      1.1   cgd 	bzero((caddr_t)fhp, sizeof(nfh));
    392      1.1   cgd 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
    393  1.1.1.3  fvdl 	error = VFS_VPTOFH(vp, &fhp->fh_fid);
    394  1.1.1.3  fvdl 	if (!error)
    395  1.1.1.3  fvdl 		error = VOP_GETATTR(vp, vap, cred, procp);
    396      1.1   cgd 	vput(vp);
    397  1.1.1.3  fvdl 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
    398  1.1.1.3  fvdl 	if (error) {
    399  1.1.1.3  fvdl 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
    400  1.1.1.3  fvdl 		return (0);
    401  1.1.1.3  fvdl 	}
    402  1.1.1.3  fvdl 	nfsm_srvfhtom(fhp, v3);
    403  1.1.1.3  fvdl 	if (v3) {
    404  1.1.1.3  fvdl 		nfsm_srvpostop_attr(0, vap);
    405  1.1.1.3  fvdl 		nfsm_srvpostop_attr(dirattr_ret, &dirattr);
    406  1.1.1.3  fvdl 	} else {
    407  1.1.1.3  fvdl 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
    408  1.1.1.3  fvdl 		nfsm_srvfillattr(vap, fp);
    409  1.1.1.2  fvdl 	}
    410      1.1   cgd 	nfsm_srvdone;
    411      1.1   cgd }
    412      1.1   cgd 
    413      1.1   cgd /*
    414      1.1   cgd  * nfs readlink service
    415      1.1   cgd  */
    416  1.1.1.3  fvdl int
    417  1.1.1.3  fvdl nfsrv_readlink(nfsd, slp, procp, mrq)
    418  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
    419  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    420  1.1.1.3  fvdl 	struct proc *procp;
    421  1.1.1.3  fvdl 	struct mbuf **mrq;
    422      1.1   cgd {
    423  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
    424  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
    425  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
    426  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
    427      1.1   cgd 	struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
    428      1.1   cgd 	register struct iovec *ivp = iv;
    429      1.1   cgd 	register struct mbuf *mp;
    430      1.1   cgd 	register u_long *tl;
    431      1.1   cgd 	register long t1;
    432      1.1   cgd 	caddr_t bpos;
    433  1.1.1.3  fvdl 	int error = 0, rdonly, cache, i, tlen, len, getret;
    434  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
    435      1.1   cgd 	char *cp2;
    436      1.1   cgd 	struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
    437      1.1   cgd 	struct vnode *vp;
    438  1.1.1.3  fvdl 	struct vattr attr;
    439  1.1.1.3  fvdl 	nfsfh_t nfh;
    440      1.1   cgd 	fhandle_t *fhp;
    441      1.1   cgd 	struct uio io, *uiop = &io;
    442  1.1.1.2  fvdl 	u_quad_t frev;
    443      1.1   cgd 
    444  1.1.1.3  fvdl #ifndef nolint
    445  1.1.1.3  fvdl 	mp2 = mp3 = (struct mbuf *)0;
    446  1.1.1.3  fvdl #endif
    447      1.1   cgd 	fhp = &nfh.fh_generic;
    448      1.1   cgd 	nfsm_srvmtofh(fhp);
    449      1.1   cgd 	len = 0;
    450      1.1   cgd 	i = 0;
    451      1.1   cgd 	while (len < NFS_MAXPATHLEN) {
    452      1.1   cgd 		MGET(mp, M_WAIT, MT_DATA);
    453      1.1   cgd 		MCLGET(mp, M_WAIT);
    454      1.1   cgd 		mp->m_len = NFSMSIZ(mp);
    455      1.1   cgd 		if (len == 0)
    456      1.1   cgd 			mp3 = mp2 = mp;
    457      1.1   cgd 		else {
    458      1.1   cgd 			mp2->m_next = mp;
    459      1.1   cgd 			mp2 = mp;
    460      1.1   cgd 		}
    461      1.1   cgd 		if ((len+mp->m_len) > NFS_MAXPATHLEN) {
    462      1.1   cgd 			mp->m_len = NFS_MAXPATHLEN-len;
    463      1.1   cgd 			len = NFS_MAXPATHLEN;
    464      1.1   cgd 		} else
    465      1.1   cgd 			len += mp->m_len;
    466      1.1   cgd 		ivp->iov_base = mtod(mp, caddr_t);
    467      1.1   cgd 		ivp->iov_len = mp->m_len;
    468      1.1   cgd 		i++;
    469      1.1   cgd 		ivp++;
    470      1.1   cgd 	}
    471      1.1   cgd 	uiop->uio_iov = iv;
    472      1.1   cgd 	uiop->uio_iovcnt = i;
    473      1.1   cgd 	uiop->uio_offset = 0;
    474      1.1   cgd 	uiop->uio_resid = len;
    475      1.1   cgd 	uiop->uio_rw = UIO_READ;
    476      1.1   cgd 	uiop->uio_segflg = UIO_SYSSPACE;
    477      1.1   cgd 	uiop->uio_procp = (struct proc *)0;
    478  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
    479  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
    480      1.1   cgd 		m_freem(mp3);
    481  1.1.1.3  fvdl 		nfsm_reply(2 * NFSX_UNSIGNED);
    482  1.1.1.3  fvdl 		nfsm_srvpostop_attr(1, (struct vattr *)0);
    483  1.1.1.3  fvdl 		return (0);
    484      1.1   cgd 	}
    485      1.1   cgd 	if (vp->v_type != VLNK) {
    486  1.1.1.3  fvdl 		if (v3)
    487  1.1.1.3  fvdl 			error = EINVAL;
    488  1.1.1.3  fvdl 		else
    489  1.1.1.3  fvdl 			error = ENXIO;
    490      1.1   cgd 		goto out;
    491      1.1   cgd 	}
    492  1.1.1.3  fvdl 	nqsrv_getl(vp, ND_READ);
    493      1.1   cgd 	error = VOP_READLINK(vp, uiop, cred);
    494      1.1   cgd out:
    495  1.1.1.3  fvdl 	getret = VOP_GETATTR(vp, &attr, cred, procp);
    496      1.1   cgd 	vput(vp);
    497      1.1   cgd 	if (error)
    498      1.1   cgd 		m_freem(mp3);
    499  1.1.1.3  fvdl 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
    500  1.1.1.3  fvdl 	if (v3) {
    501  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &attr);
    502  1.1.1.3  fvdl 		if (error)
    503  1.1.1.3  fvdl 			return (0);
    504  1.1.1.3  fvdl 	}
    505      1.1   cgd 	if (uiop->uio_resid > 0) {
    506      1.1   cgd 		len -= uiop->uio_resid;
    507      1.1   cgd 		tlen = nfsm_rndup(len);
    508      1.1   cgd 		nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
    509      1.1   cgd 	}
    510      1.1   cgd 	nfsm_build(tl, u_long *, NFSX_UNSIGNED);
    511      1.1   cgd 	*tl = txdr_unsigned(len);
    512      1.1   cgd 	mb->m_next = mp3;
    513      1.1   cgd 	nfsm_srvdone;
    514      1.1   cgd }
    515      1.1   cgd 
    516      1.1   cgd /*
    517      1.1   cgd  * nfs read service
    518      1.1   cgd  */
    519  1.1.1.3  fvdl int
    520  1.1.1.3  fvdl nfsrv_read(nfsd, slp, procp, mrq)
    521  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
    522  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    523  1.1.1.3  fvdl 	struct proc *procp;
    524  1.1.1.3  fvdl 	struct mbuf **mrq;
    525      1.1   cgd {
    526  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
    527  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
    528  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
    529  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
    530      1.1   cgd 	register struct iovec *iv;
    531      1.1   cgd 	struct iovec *iv2;
    532      1.1   cgd 	register struct mbuf *m;
    533  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
    534      1.1   cgd 	register u_long *tl;
    535      1.1   cgd 	register long t1;
    536  1.1.1.3  fvdl 	register int i;
    537      1.1   cgd 	caddr_t bpos;
    538  1.1.1.3  fvdl 	int error = 0, rdonly, cache, cnt, len, left, siz, tlen, getret;
    539  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
    540      1.1   cgd 	char *cp2;
    541      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
    542  1.1.1.2  fvdl 	struct mbuf *m2;
    543      1.1   cgd 	struct vnode *vp;
    544  1.1.1.3  fvdl 	nfsfh_t nfh;
    545      1.1   cgd 	fhandle_t *fhp;
    546      1.1   cgd 	struct uio io, *uiop = &io;
    547      1.1   cgd 	struct vattr va, *vap = &va;
    548      1.1   cgd 	off_t off;
    549  1.1.1.2  fvdl 	u_quad_t frev;
    550      1.1   cgd 
    551      1.1   cgd 	fhp = &nfh.fh_generic;
    552      1.1   cgd 	nfsm_srvmtofh(fhp);
    553  1.1.1.3  fvdl 	if (v3) {
    554  1.1.1.2  fvdl 		nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
    555  1.1.1.2  fvdl 		fxdr_hyper(tl, &off);
    556  1.1.1.3  fvdl 	} else {
    557  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
    558  1.1.1.3  fvdl 		off = (off_t)fxdr_unsigned(u_long, *tl);
    559  1.1.1.2  fvdl 	}
    560  1.1.1.3  fvdl 	nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
    561  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
    562  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
    563  1.1.1.3  fvdl 		nfsm_reply(2 * NFSX_UNSIGNED);
    564  1.1.1.3  fvdl 		nfsm_srvpostop_attr(1, (struct vattr *)0);
    565  1.1.1.3  fvdl 		return (0);
    566      1.1   cgd 	}
    567  1.1.1.3  fvdl 	if (vp->v_type != VREG) {
    568  1.1.1.3  fvdl 		if (v3)
    569  1.1.1.3  fvdl 			error = EINVAL;
    570  1.1.1.3  fvdl 		else
    571  1.1.1.3  fvdl 			error = (vp->v_type == VDIR) ? EISDIR : EACCES;
    572      1.1   cgd 	}
    573  1.1.1.3  fvdl 	if (!error) {
    574  1.1.1.3  fvdl 	    nqsrv_getl(vp, ND_READ);
    575  1.1.1.3  fvdl 	    if (error = nfsrv_access(vp, VREAD, cred, rdonly, procp))
    576  1.1.1.3  fvdl 		error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
    577  1.1.1.3  fvdl 	}
    578  1.1.1.3  fvdl 	getret = VOP_GETATTR(vp, vap, cred, procp);
    579  1.1.1.3  fvdl 	if (!error)
    580  1.1.1.3  fvdl 		error = getret;
    581  1.1.1.3  fvdl 	if (error) {
    582      1.1   cgd 		vput(vp);
    583  1.1.1.3  fvdl 		nfsm_reply(NFSX_POSTOPATTR(v3));
    584  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, vap);
    585  1.1.1.3  fvdl 		return (0);
    586      1.1   cgd 	}
    587  1.1.1.2  fvdl 	if (off >= vap->va_size)
    588  1.1.1.2  fvdl 		cnt = 0;
    589  1.1.1.3  fvdl 	else if ((off + reqlen) > vap->va_size)
    590  1.1.1.2  fvdl 		cnt = nfsm_rndup(vap->va_size - off);
    591  1.1.1.3  fvdl 	else
    592  1.1.1.3  fvdl 		cnt = reqlen;
    593  1.1.1.3  fvdl 	nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
    594  1.1.1.3  fvdl 	if (v3) {
    595  1.1.1.3  fvdl 		nfsm_build(tl, u_long *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
    596  1.1.1.3  fvdl 		*tl++ = nfs_true;
    597  1.1.1.3  fvdl 		fp = (struct nfs_fattr *)tl;
    598  1.1.1.3  fvdl 		tl += (NFSX_V3FATTR / sizeof (u_long));
    599  1.1.1.3  fvdl 	} else {
    600  1.1.1.3  fvdl 		nfsm_build(tl, u_long *, NFSX_V2FATTR + NFSX_UNSIGNED);
    601  1.1.1.3  fvdl 		fp = (struct nfs_fattr *)tl;
    602  1.1.1.3  fvdl 		tl += (NFSX_V2FATTR / sizeof (u_long));
    603  1.1.1.3  fvdl 	}
    604  1.1.1.2  fvdl 	len = left = cnt;
    605  1.1.1.2  fvdl 	if (cnt > 0) {
    606  1.1.1.2  fvdl 		/*
    607  1.1.1.2  fvdl 		 * Generate the mbuf list with the uio_iov ref. to it.
    608  1.1.1.2  fvdl 		 */
    609  1.1.1.2  fvdl 		i = 0;
    610  1.1.1.2  fvdl 		m = m2 = mb;
    611  1.1.1.2  fvdl 		while (left > 0) {
    612  1.1.1.2  fvdl 			siz = min(M_TRAILINGSPACE(m), left);
    613  1.1.1.2  fvdl 			if (siz > 0) {
    614  1.1.1.2  fvdl 				left -= siz;
    615  1.1.1.3  fvdl 				i++;
    616  1.1.1.2  fvdl 			}
    617  1.1.1.2  fvdl 			if (left > 0) {
    618  1.1.1.2  fvdl 				MGET(m, M_WAIT, MT_DATA);
    619  1.1.1.2  fvdl 				MCLGET(m, M_WAIT);
    620  1.1.1.2  fvdl 				m->m_len = 0;
    621  1.1.1.2  fvdl 				m2->m_next = m;
    622  1.1.1.2  fvdl 				m2 = m;
    623  1.1.1.2  fvdl 			}
    624  1.1.1.2  fvdl 		}
    625  1.1.1.3  fvdl 		MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
    626  1.1.1.3  fvdl 		       M_TEMP, M_WAITOK);
    627  1.1.1.3  fvdl 		uiop->uio_iov = iv2 = iv;
    628  1.1.1.3  fvdl 		m = mb;
    629  1.1.1.3  fvdl 		left = cnt;
    630  1.1.1.3  fvdl 		i = 0;
    631  1.1.1.3  fvdl 		while (left > 0) {
    632  1.1.1.3  fvdl 			if (m == NULL)
    633  1.1.1.3  fvdl 				panic("nfsrv_read iov");
    634  1.1.1.3  fvdl 			siz = min(M_TRAILINGSPACE(m), left);
    635  1.1.1.3  fvdl 			if (siz > 0) {
    636  1.1.1.3  fvdl 				iv->iov_base = mtod(m, caddr_t) + m->m_len;
    637  1.1.1.3  fvdl 				iv->iov_len = siz;
    638  1.1.1.3  fvdl 				m->m_len += siz;
    639  1.1.1.3  fvdl 				left -= siz;
    640  1.1.1.3  fvdl 				iv++;
    641  1.1.1.3  fvdl 				i++;
    642  1.1.1.3  fvdl 			}
    643  1.1.1.3  fvdl 			m = m->m_next;
    644  1.1.1.3  fvdl 		}
    645  1.1.1.2  fvdl 		uiop->uio_iovcnt = i;
    646  1.1.1.2  fvdl 		uiop->uio_offset = off;
    647  1.1.1.2  fvdl 		uiop->uio_resid = cnt;
    648  1.1.1.2  fvdl 		uiop->uio_rw = UIO_READ;
    649  1.1.1.2  fvdl 		uiop->uio_segflg = UIO_SYSSPACE;
    650  1.1.1.2  fvdl 		error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
    651  1.1.1.2  fvdl 		off = uiop->uio_offset;
    652  1.1.1.2  fvdl 		FREE((caddr_t)iv2, M_TEMP);
    653  1.1.1.3  fvdl 		if (error || (getret = VOP_GETATTR(vp, vap, cred, procp))) {
    654  1.1.1.3  fvdl 			if (!error)
    655  1.1.1.3  fvdl 				error = getret;
    656  1.1.1.2  fvdl 			m_freem(mreq);
    657  1.1.1.2  fvdl 			vput(vp);
    658  1.1.1.3  fvdl 			nfsm_reply(NFSX_POSTOPATTR(v3));
    659  1.1.1.3  fvdl 			nfsm_srvpostop_attr(getret, vap);
    660  1.1.1.3  fvdl 			return (0);
    661  1.1.1.2  fvdl 		}
    662  1.1.1.2  fvdl 	} else
    663  1.1.1.2  fvdl 		uiop->uio_resid = 0;
    664      1.1   cgd 	vput(vp);
    665  1.1.1.3  fvdl 	nfsm_srvfillattr(vap, fp);
    666      1.1   cgd 	len -= uiop->uio_resid;
    667  1.1.1.2  fvdl 	tlen = nfsm_rndup(len);
    668  1.1.1.2  fvdl 	if (cnt != tlen || tlen != len)
    669  1.1.1.3  fvdl 		nfsm_adj(mb, cnt - tlen, tlen - len);
    670  1.1.1.3  fvdl 	if (v3) {
    671  1.1.1.3  fvdl 		*tl++ = txdr_unsigned(len);
    672  1.1.1.3  fvdl 		if (len < reqlen)
    673  1.1.1.3  fvdl 			*tl++ = nfs_true;
    674  1.1.1.3  fvdl 		else
    675  1.1.1.3  fvdl 			*tl++ = nfs_false;
    676  1.1.1.3  fvdl 	}
    677      1.1   cgd 	*tl = txdr_unsigned(len);
    678      1.1   cgd 	nfsm_srvdone;
    679      1.1   cgd }
    680      1.1   cgd 
    681      1.1   cgd /*
    682      1.1   cgd  * nfs write service
    683      1.1   cgd  */
    684  1.1.1.3  fvdl int
    685  1.1.1.3  fvdl nfsrv_write(nfsd, slp, procp, mrq)
    686  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
    687  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    688  1.1.1.3  fvdl 	struct proc *procp;
    689  1.1.1.3  fvdl 	struct mbuf **mrq;
    690      1.1   cgd {
    691  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
    692  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
    693  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
    694  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
    695      1.1   cgd 	register struct iovec *ivp;
    696  1.1.1.3  fvdl 	register int i, cnt;
    697      1.1   cgd 	register struct mbuf *mp;
    698  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
    699  1.1.1.3  fvdl 	struct iovec *iv;
    700  1.1.1.3  fvdl 	struct vattr va, forat;
    701      1.1   cgd 	register struct vattr *vap = &va;
    702      1.1   cgd 	register u_long *tl;
    703      1.1   cgd 	register long t1;
    704      1.1   cgd 	caddr_t bpos;
    705  1.1.1.3  fvdl 	int error = 0, rdonly, cache, siz, len, xfer, forat_ret = 1;
    706  1.1.1.3  fvdl 	int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
    707  1.1.1.3  fvdl 	int stable = NFSV3WRITE_FILESYNC;
    708  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
    709      1.1   cgd 	char *cp2;
    710      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
    711      1.1   cgd 	struct vnode *vp;
    712  1.1.1.3  fvdl 	nfsfh_t nfh;
    713      1.1   cgd 	fhandle_t *fhp;
    714      1.1   cgd 	struct uio io, *uiop = &io;
    715      1.1   cgd 	off_t off;
    716  1.1.1.2  fvdl 	u_quad_t frev;
    717      1.1   cgd 
    718  1.1.1.3  fvdl 	if (mrep == NULL) {
    719  1.1.1.3  fvdl 		*mrq = NULL;
    720  1.1.1.3  fvdl 		return (0);
    721  1.1.1.3  fvdl 	}
    722      1.1   cgd 	fhp = &nfh.fh_generic;
    723      1.1   cgd 	nfsm_srvmtofh(fhp);
    724  1.1.1.3  fvdl 	if (v3) {
    725  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, 5 * NFSX_UNSIGNED);
    726  1.1.1.2  fvdl 		fxdr_hyper(tl, &off);
    727  1.1.1.3  fvdl 		tl += 3;
    728  1.1.1.3  fvdl 		stable = fxdr_unsigned(int, *tl++);
    729  1.1.1.3  fvdl 	} else {
    730  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);
    731  1.1.1.3  fvdl 		off = (off_t)fxdr_unsigned(u_long, *++tl);
    732  1.1.1.2  fvdl 		tl += 2;
    733      1.1   cgd 	}
    734  1.1.1.3  fvdl 	retlen = len = fxdr_unsigned(long, *tl);
    735  1.1.1.3  fvdl 	cnt = i = 0;
    736  1.1.1.3  fvdl 
    737  1.1.1.3  fvdl 	/*
    738  1.1.1.3  fvdl 	 * For NFS Version 2, it is not obvious what a write of zero length
    739  1.1.1.3  fvdl 	 * should do, but I might as well be consistent with Version 3,
    740  1.1.1.3  fvdl 	 * which is to return ok so long as there are no permission problems.
    741  1.1.1.3  fvdl 	 */
    742  1.1.1.3  fvdl 	if (len > 0) {
    743  1.1.1.3  fvdl 	    zeroing = 1;
    744  1.1.1.3  fvdl 	    mp = mrep;
    745  1.1.1.3  fvdl 	    while (mp) {
    746  1.1.1.3  fvdl 		if (mp == md) {
    747  1.1.1.3  fvdl 			zeroing = 0;
    748  1.1.1.3  fvdl 			adjust = dpos - mtod(mp, caddr_t);
    749  1.1.1.3  fvdl 			mp->m_len -= adjust;
    750  1.1.1.3  fvdl 			if (mp->m_len > 0 && adjust > 0)
    751  1.1.1.3  fvdl 				NFSMADV(mp, adjust);
    752      1.1   cgd 		}
    753  1.1.1.3  fvdl 		if (zeroing)
    754  1.1.1.3  fvdl 			mp->m_len = 0;
    755  1.1.1.3  fvdl 		else if (mp->m_len > 0) {
    756  1.1.1.3  fvdl 			i += mp->m_len;
    757  1.1.1.3  fvdl 			if (i > len) {
    758  1.1.1.3  fvdl 				mp->m_len -= (i - len);
    759  1.1.1.3  fvdl 				zeroing	= 1;
    760  1.1.1.3  fvdl 			}
    761  1.1.1.3  fvdl 			if (mp->m_len > 0)
    762  1.1.1.3  fvdl 				cnt++;
    763  1.1.1.3  fvdl 		}
    764  1.1.1.3  fvdl 		mp = mp->m_next;
    765  1.1.1.3  fvdl 	    }
    766      1.1   cgd 	}
    767  1.1.1.3  fvdl 	if (len > NFS_MAXDATA || len < 0 || i < len) {
    768  1.1.1.3  fvdl 		error = EIO;
    769  1.1.1.3  fvdl 		nfsm_reply(2 * NFSX_UNSIGNED);
    770  1.1.1.3  fvdl 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
    771  1.1.1.3  fvdl 		return (0);
    772  1.1.1.3  fvdl 	}
    773  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
    774  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
    775  1.1.1.3  fvdl 		nfsm_reply(2 * NFSX_UNSIGNED);
    776  1.1.1.3  fvdl 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
    777  1.1.1.3  fvdl 		return (0);
    778  1.1.1.3  fvdl 	}
    779  1.1.1.3  fvdl 	if (v3)
    780  1.1.1.3  fvdl 		forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
    781  1.1.1.2  fvdl 	if (vp->v_type != VREG) {
    782  1.1.1.3  fvdl 		if (v3)
    783  1.1.1.3  fvdl 			error = EINVAL;
    784  1.1.1.3  fvdl 		else
    785  1.1.1.3  fvdl 			error = (vp->v_type == VDIR) ? EISDIR : EACCES;
    786  1.1.1.3  fvdl 	}
    787  1.1.1.3  fvdl 	if (!error) {
    788  1.1.1.3  fvdl 		nqsrv_getl(vp, ND_WRITE);
    789  1.1.1.3  fvdl 		error = nfsrv_access(vp, VWRITE, cred, rdonly, procp);
    790  1.1.1.2  fvdl 	}
    791  1.1.1.3  fvdl 	if (error) {
    792      1.1   cgd 		vput(vp);
    793  1.1.1.3  fvdl 		nfsm_reply(NFSX_WCCDATA(v3));
    794  1.1.1.3  fvdl 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
    795  1.1.1.3  fvdl 		return (0);
    796      1.1   cgd 	}
    797  1.1.1.3  fvdl 
    798  1.1.1.3  fvdl 	if (len > 0) {
    799  1.1.1.3  fvdl 	    MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
    800  1.1.1.3  fvdl 		M_WAITOK);
    801  1.1.1.3  fvdl 	    uiop->uio_iov = iv = ivp;
    802  1.1.1.3  fvdl 	    uiop->uio_iovcnt = cnt;
    803  1.1.1.3  fvdl 	    mp = mrep;
    804  1.1.1.3  fvdl 	    while (mp) {
    805  1.1.1.3  fvdl 		if (mp->m_len > 0) {
    806  1.1.1.3  fvdl 			ivp->iov_base = mtod(mp, caddr_t);
    807  1.1.1.3  fvdl 			ivp->iov_len = mp->m_len;
    808  1.1.1.3  fvdl 			ivp++;
    809  1.1.1.3  fvdl 		}
    810  1.1.1.3  fvdl 		mp = mp->m_next;
    811  1.1.1.3  fvdl 	    }
    812  1.1.1.3  fvdl 
    813  1.1.1.3  fvdl 	    /*
    814  1.1.1.3  fvdl 	     * XXX
    815  1.1.1.3  fvdl 	     * The IO_METASYNC flag indicates that all metadata (and not just
    816  1.1.1.3  fvdl 	     * enough to ensure data integrity) mus be written to stable storage
    817  1.1.1.3  fvdl 	     * synchronously.
    818  1.1.1.3  fvdl 	     * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
    819  1.1.1.3  fvdl 	     */
    820  1.1.1.3  fvdl 	    if (stable == NFSV3WRITE_UNSTABLE)
    821  1.1.1.3  fvdl 		ioflags = IO_NODELOCKED;
    822  1.1.1.3  fvdl 	    else if (stable == NFSV3WRITE_DATASYNC)
    823  1.1.1.3  fvdl 		ioflags = (IO_SYNC | IO_NODELOCKED);
    824  1.1.1.3  fvdl 	    else
    825  1.1.1.3  fvdl 		ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
    826  1.1.1.3  fvdl 	    uiop->uio_resid = len;
    827  1.1.1.3  fvdl 	    uiop->uio_rw = UIO_WRITE;
    828  1.1.1.3  fvdl 	    uiop->uio_segflg = UIO_SYSSPACE;
    829  1.1.1.3  fvdl 	    uiop->uio_procp = (struct proc *)0;
    830  1.1.1.3  fvdl 	    uiop->uio_offset = off;
    831  1.1.1.3  fvdl 	    error = VOP_WRITE(vp, uiop, ioflags, cred);
    832  1.1.1.3  fvdl 	    nfsstats.srvvop_writes++;
    833  1.1.1.3  fvdl 	    FREE((caddr_t)iv, M_TEMP);
    834  1.1.1.3  fvdl 	}
    835  1.1.1.3  fvdl 	aftat_ret = VOP_GETATTR(vp, vap, cred, procp);
    836  1.1.1.3  fvdl 	vput(vp);
    837  1.1.1.3  fvdl 	if (!error)
    838  1.1.1.3  fvdl 		error = aftat_ret;
    839  1.1.1.3  fvdl 	nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
    840  1.1.1.3  fvdl 		2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
    841  1.1.1.3  fvdl 	if (v3) {
    842  1.1.1.3  fvdl 		nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
    843  1.1.1.3  fvdl 		if (error)
    844  1.1.1.3  fvdl 			return (0);
    845  1.1.1.3  fvdl 		nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
    846  1.1.1.3  fvdl 		*tl++ = txdr_unsigned(retlen);
    847  1.1.1.3  fvdl 		if (stable == NFSV3WRITE_UNSTABLE)
    848  1.1.1.3  fvdl 			*tl++ = txdr_unsigned(stable);
    849  1.1.1.3  fvdl 		else
    850  1.1.1.3  fvdl 			*tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
    851  1.1.1.3  fvdl 		/*
    852  1.1.1.3  fvdl 		 * Actually, there is no need to txdr these fields,
    853  1.1.1.3  fvdl 		 * but it may make the values more human readable,
    854  1.1.1.3  fvdl 		 * for debugging purposes.
    855  1.1.1.3  fvdl 		 */
    856  1.1.1.3  fvdl 		*tl++ = txdr_unsigned(boottime.tv_sec);
    857  1.1.1.3  fvdl 		*tl = txdr_unsigned(boottime.tv_usec);
    858  1.1.1.3  fvdl 	} else {
    859  1.1.1.3  fvdl 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
    860  1.1.1.3  fvdl 		nfsm_srvfillattr(vap, fp);
    861  1.1.1.3  fvdl 	}
    862  1.1.1.3  fvdl 	nfsm_srvdone;
    863  1.1.1.3  fvdl }
    864  1.1.1.3  fvdl 
    865  1.1.1.3  fvdl /*
    866  1.1.1.3  fvdl  * NFS write service with write gathering support. Called when
    867  1.1.1.3  fvdl  * nfsrvw_procrastinate > 0.
    868  1.1.1.3  fvdl  * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
    869  1.1.1.3  fvdl  * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
    870  1.1.1.3  fvdl  * Jan. 1994.
    871  1.1.1.3  fvdl  */
    872  1.1.1.3  fvdl int
    873  1.1.1.3  fvdl nfsrv_writegather(ndp, slp, procp, mrq)
    874  1.1.1.3  fvdl 	struct nfsrv_descript **ndp;
    875  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
    876  1.1.1.3  fvdl 	struct proc *procp;
    877  1.1.1.3  fvdl 	struct mbuf **mrq;
    878  1.1.1.3  fvdl {
    879  1.1.1.3  fvdl 	register struct iovec *ivp;
    880  1.1.1.3  fvdl 	register struct mbuf *mp;
    881  1.1.1.3  fvdl 	register struct nfsrv_descript *wp, *nfsd, *owp, *swp;
    882  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
    883  1.1.1.3  fvdl 	register int i;
    884  1.1.1.3  fvdl 	struct iovec *iov;
    885  1.1.1.3  fvdl 	struct nfsrvw_delayhash *wpp;
    886  1.1.1.3  fvdl 	struct ucred *cred;
    887  1.1.1.3  fvdl 	struct vattr va, forat;
    888  1.1.1.3  fvdl 	register u_long *tl;
    889  1.1.1.3  fvdl 	register long t1;
    890  1.1.1.3  fvdl 	caddr_t bpos, dpos;
    891  1.1.1.3  fvdl 	int error = 0, rdonly, cache, len, forat_ret = 1;
    892  1.1.1.3  fvdl 	int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
    893  1.1.1.3  fvdl 	char *cp2;
    894  1.1.1.3  fvdl 	struct mbuf *mb, *mb2, *mreq, *mrep, *md;
    895  1.1.1.3  fvdl 	struct vnode *vp;
    896  1.1.1.3  fvdl 	struct uio io, *uiop = &io;
    897  1.1.1.3  fvdl 	off_t off;
    898  1.1.1.3  fvdl 	u_quad_t frev, cur_usec;
    899  1.1.1.3  fvdl 
    900  1.1.1.3  fvdl #ifndef nolint
    901  1.1.1.3  fvdl 	i = 0;
    902  1.1.1.3  fvdl 	len = 0;
    903  1.1.1.3  fvdl #endif
    904  1.1.1.3  fvdl 	*mrq = NULL;
    905  1.1.1.3  fvdl 	if (*ndp) {
    906  1.1.1.3  fvdl 	    nfsd = *ndp;
    907  1.1.1.3  fvdl 	    *ndp = NULL;
    908  1.1.1.3  fvdl 	    mrep = nfsd->nd_mrep;
    909  1.1.1.3  fvdl 	    md = nfsd->nd_md;
    910  1.1.1.3  fvdl 	    dpos = nfsd->nd_dpos;
    911  1.1.1.3  fvdl 	    cred = &nfsd->nd_cr;
    912  1.1.1.3  fvdl 	    v3 = (nfsd->nd_flag & ND_NFSV3);
    913  1.1.1.3  fvdl 	    LIST_INIT(&nfsd->nd_coalesce);
    914  1.1.1.3  fvdl 	    nfsd->nd_mreq = NULL;
    915  1.1.1.3  fvdl 	    nfsd->nd_stable = NFSV3WRITE_FILESYNC;
    916  1.1.1.3  fvdl 	    cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
    917  1.1.1.3  fvdl 	    nfsd->nd_time = cur_usec + nfsrvw_procrastinate;
    918  1.1.1.3  fvdl 
    919  1.1.1.3  fvdl 	    /*
    920  1.1.1.3  fvdl 	     * Now, get the write header..
    921  1.1.1.3  fvdl 	     */
    922  1.1.1.3  fvdl 	    nfsm_srvmtofh(&nfsd->nd_fh);
    923  1.1.1.3  fvdl 	    if (v3) {
    924  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, 5 * NFSX_UNSIGNED);
    925  1.1.1.3  fvdl 		fxdr_hyper(tl, &nfsd->nd_off);
    926  1.1.1.3  fvdl 		tl += 3;
    927  1.1.1.3  fvdl 		nfsd->nd_stable = fxdr_unsigned(int, *tl++);
    928  1.1.1.3  fvdl 	    } else {
    929  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);
    930  1.1.1.3  fvdl 		nfsd->nd_off = (off_t)fxdr_unsigned(u_long, *++tl);
    931  1.1.1.3  fvdl 		tl += 2;
    932  1.1.1.3  fvdl 	    }
    933  1.1.1.3  fvdl 	    len = fxdr_unsigned(long, *tl);
    934  1.1.1.3  fvdl 	    nfsd->nd_len = len;
    935  1.1.1.3  fvdl 	    nfsd->nd_eoff = nfsd->nd_off + len;
    936  1.1.1.3  fvdl 
    937  1.1.1.3  fvdl 	    /*
    938  1.1.1.3  fvdl 	     * Trim the header out of the mbuf list and trim off any trailing
    939  1.1.1.3  fvdl 	     * junk so that the mbuf list has only the write data.
    940  1.1.1.3  fvdl 	     */
    941  1.1.1.3  fvdl 	    zeroing = 1;
    942  1.1.1.3  fvdl 	    i = 0;
    943  1.1.1.3  fvdl 	    mp = mrep;
    944  1.1.1.3  fvdl 	    while (mp) {
    945  1.1.1.3  fvdl 		if (mp == md) {
    946  1.1.1.3  fvdl 		    zeroing = 0;
    947  1.1.1.3  fvdl 		    adjust = dpos - mtod(mp, caddr_t);
    948  1.1.1.3  fvdl 		    mp->m_len -= adjust;
    949  1.1.1.3  fvdl 		    if (mp->m_len > 0 && adjust > 0)
    950  1.1.1.3  fvdl 			NFSMADV(mp, adjust);
    951  1.1.1.3  fvdl 		}
    952  1.1.1.3  fvdl 		if (zeroing)
    953  1.1.1.3  fvdl 		    mp->m_len = 0;
    954  1.1.1.3  fvdl 		else {
    955  1.1.1.3  fvdl 		    i += mp->m_len;
    956  1.1.1.3  fvdl 		    if (i > len) {
    957  1.1.1.3  fvdl 			mp->m_len -= (i - len);
    958  1.1.1.3  fvdl 			zeroing = 1;
    959  1.1.1.3  fvdl 		    }
    960  1.1.1.3  fvdl 		}
    961  1.1.1.3  fvdl 		mp = mp->m_next;
    962  1.1.1.3  fvdl 	    }
    963  1.1.1.3  fvdl 	    if (len > NFS_MAXDATA || len < 0  || i < len) {
    964  1.1.1.3  fvdl nfsmout:
    965  1.1.1.3  fvdl 		m_freem(mrep);
    966  1.1.1.3  fvdl 		error = EIO;
    967  1.1.1.3  fvdl 		nfsm_writereply(2 * NFSX_UNSIGNED, v3);
    968  1.1.1.3  fvdl 		if (v3)
    969  1.1.1.3  fvdl 		    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
    970  1.1.1.3  fvdl 		nfsd->nd_mreq = mreq;
    971  1.1.1.3  fvdl 		nfsd->nd_mrep = NULL;
    972  1.1.1.3  fvdl 		nfsd->nd_time = 0;
    973  1.1.1.3  fvdl 	    }
    974  1.1.1.3  fvdl 
    975  1.1.1.3  fvdl 	    /*
    976  1.1.1.3  fvdl 	     * Add this entry to the hash and time queues.
    977  1.1.1.3  fvdl 	     */
    978  1.1.1.3  fvdl 	    s = splsoftclock();
    979  1.1.1.3  fvdl 	    owp = NULL;
    980  1.1.1.3  fvdl 	    wp = slp->ns_tq.lh_first;
    981  1.1.1.3  fvdl 	    while (wp && wp->nd_time < nfsd->nd_time) {
    982  1.1.1.3  fvdl 		owp = wp;
    983  1.1.1.3  fvdl 		wp = wp->nd_tq.le_next;
    984  1.1.1.3  fvdl 	    }
    985  1.1.1.3  fvdl 	    if (owp) {
    986  1.1.1.3  fvdl 		LIST_INSERT_AFTER(owp, nfsd, nd_tq);
    987  1.1.1.3  fvdl 	    } else {
    988  1.1.1.3  fvdl 		LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
    989  1.1.1.3  fvdl 	    }
    990  1.1.1.3  fvdl 	    if (nfsd->nd_mrep) {
    991  1.1.1.3  fvdl 		wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
    992  1.1.1.3  fvdl 		owp = NULL;
    993  1.1.1.3  fvdl 		wp = wpp->lh_first;
    994  1.1.1.3  fvdl 		while (wp &&
    995  1.1.1.3  fvdl 		    bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
    996  1.1.1.3  fvdl 		    owp = wp;
    997  1.1.1.3  fvdl 		    wp = wp->nd_hash.le_next;
    998  1.1.1.3  fvdl 		}
    999  1.1.1.3  fvdl 		while (wp && wp->nd_off < nfsd->nd_off &&
   1000  1.1.1.3  fvdl 		    !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
   1001  1.1.1.3  fvdl 		    owp = wp;
   1002  1.1.1.3  fvdl 		    wp = wp->nd_hash.le_next;
   1003  1.1.1.3  fvdl 		}
   1004  1.1.1.3  fvdl 		if (owp) {
   1005  1.1.1.3  fvdl 		    LIST_INSERT_AFTER(owp, nfsd, nd_hash);
   1006  1.1.1.3  fvdl 
   1007  1.1.1.3  fvdl 		    /*
   1008  1.1.1.3  fvdl 		     * Search the hash list for overlapping entries and
   1009  1.1.1.3  fvdl 		     * coalesce.
   1010  1.1.1.3  fvdl 		     */
   1011  1.1.1.3  fvdl 		    for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
   1012  1.1.1.3  fvdl 			wp = nfsd->nd_hash.le_next;
   1013  1.1.1.3  fvdl 			if (NFSW_SAMECRED(owp, nfsd))
   1014  1.1.1.3  fvdl 			    nfsrvw_coalesce(owp, nfsd);
   1015  1.1.1.3  fvdl 		    }
   1016  1.1.1.3  fvdl 		} else {
   1017  1.1.1.3  fvdl 		    LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
   1018  1.1.1.3  fvdl 		}
   1019  1.1.1.3  fvdl 	    }
   1020  1.1.1.3  fvdl 	    splx(s);
   1021  1.1.1.3  fvdl 	}
   1022  1.1.1.3  fvdl 
   1023      1.1   cgd 	/*
   1024  1.1.1.3  fvdl 	 * Now, do VOP_WRITE()s for any one(s) that need to be done now
   1025  1.1.1.3  fvdl 	 * and generate the associated reply mbuf list(s).
   1026      1.1   cgd 	 */
   1027  1.1.1.3  fvdl loop1:
   1028  1.1.1.3  fvdl 	cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
   1029  1.1.1.3  fvdl 	s = splsoftclock();
   1030  1.1.1.3  fvdl 	for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = owp) {
   1031  1.1.1.3  fvdl 		owp = nfsd->nd_tq.le_next;
   1032  1.1.1.3  fvdl 		if (nfsd->nd_time > cur_usec)
   1033  1.1.1.3  fvdl 		    break;
   1034  1.1.1.3  fvdl 		if (nfsd->nd_mreq)
   1035  1.1.1.3  fvdl 		    continue;
   1036  1.1.1.3  fvdl 		LIST_REMOVE(nfsd, nd_tq);
   1037  1.1.1.3  fvdl 		LIST_REMOVE(nfsd, nd_hash);
   1038  1.1.1.3  fvdl 		splx(s);
   1039  1.1.1.3  fvdl 		mrep = nfsd->nd_mrep;
   1040  1.1.1.3  fvdl 		nfsd->nd_mrep = NULL;
   1041  1.1.1.3  fvdl 		cred = &nfsd->nd_cr;
   1042  1.1.1.3  fvdl 		v3 = (nfsd->nd_flag & ND_NFSV3);
   1043  1.1.1.3  fvdl 		forat_ret = aftat_ret = 1;
   1044  1.1.1.3  fvdl 		error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
   1045  1.1.1.3  fvdl 		    nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH));
   1046  1.1.1.3  fvdl 		if (!error) {
   1047  1.1.1.3  fvdl 		    if (v3)
   1048  1.1.1.3  fvdl 			forat_ret = VOP_GETATTR(vp, &forat, cred, procp);
   1049  1.1.1.3  fvdl 		    if (vp->v_type != VREG) {
   1050  1.1.1.3  fvdl 			if (v3)
   1051  1.1.1.3  fvdl 			    error = EINVAL;
   1052      1.1   cgd 			else
   1053  1.1.1.3  fvdl 			    error = (vp->v_type == VDIR) ? EISDIR : EACCES;
   1054  1.1.1.3  fvdl 		    }
   1055  1.1.1.3  fvdl 		} else
   1056  1.1.1.3  fvdl 		    vp = NULL;
   1057  1.1.1.3  fvdl 		if (!error) {
   1058  1.1.1.3  fvdl 		    nqsrv_getl(vp, ND_WRITE);
   1059  1.1.1.3  fvdl 		    error = nfsrv_access(vp, VWRITE, cred, rdonly, procp);
   1060      1.1   cgd 		}
   1061  1.1.1.3  fvdl 
   1062  1.1.1.3  fvdl 		if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
   1063  1.1.1.3  fvdl 		    ioflags = IO_NODELOCKED;
   1064  1.1.1.3  fvdl 		else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
   1065  1.1.1.3  fvdl 		    ioflags = (IO_SYNC | IO_NODELOCKED);
   1066  1.1.1.3  fvdl 		else
   1067  1.1.1.3  fvdl 		    ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
   1068  1.1.1.3  fvdl 		uiop->uio_rw = UIO_WRITE;
   1069  1.1.1.3  fvdl 		uiop->uio_segflg = UIO_SYSSPACE;
   1070  1.1.1.3  fvdl 		uiop->uio_procp = (struct proc *)0;
   1071  1.1.1.3  fvdl 		uiop->uio_offset = nfsd->nd_off;
   1072  1.1.1.3  fvdl 		uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
   1073  1.1.1.3  fvdl 		if (uiop->uio_resid > 0) {
   1074  1.1.1.3  fvdl 		    mp = mrep;
   1075  1.1.1.3  fvdl 		    i = 0;
   1076  1.1.1.3  fvdl 		    while (mp) {
   1077  1.1.1.3  fvdl 			if (mp->m_len > 0)
   1078  1.1.1.3  fvdl 			    i++;
   1079  1.1.1.3  fvdl 			mp = mp->m_next;
   1080  1.1.1.3  fvdl 		    }
   1081  1.1.1.3  fvdl 		    uiop->uio_iovcnt = i;
   1082  1.1.1.3  fvdl 		    MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
   1083  1.1.1.3  fvdl 			M_TEMP, M_WAITOK);
   1084  1.1.1.3  fvdl 		    uiop->uio_iov = ivp = iov;
   1085  1.1.1.3  fvdl 		    mp = mrep;
   1086  1.1.1.3  fvdl 		    while (mp) {
   1087  1.1.1.3  fvdl 			if (mp->m_len > 0) {
   1088  1.1.1.3  fvdl 			    ivp->iov_base = mtod(mp, caddr_t);
   1089  1.1.1.3  fvdl 			    ivp->iov_len = mp->m_len;
   1090  1.1.1.3  fvdl 			    ivp++;
   1091  1.1.1.3  fvdl 			}
   1092  1.1.1.3  fvdl 			mp = mp->m_next;
   1093  1.1.1.3  fvdl 		    }
   1094  1.1.1.3  fvdl 		    if (!error) {
   1095  1.1.1.3  fvdl 			error = VOP_WRITE(vp, uiop, ioflags, cred);
   1096  1.1.1.3  fvdl 			nfsstats.srvvop_writes++;
   1097  1.1.1.3  fvdl 		    }
   1098  1.1.1.3  fvdl 		    FREE((caddr_t)iov, M_TEMP);
   1099      1.1   cgd 		}
   1100  1.1.1.3  fvdl 		m_freem(mrep);
   1101  1.1.1.3  fvdl 		if (vp) {
   1102  1.1.1.3  fvdl 		    aftat_ret = VOP_GETATTR(vp, &va, cred, procp);
   1103  1.1.1.3  fvdl 		    vput(vp);
   1104      1.1   cgd 		}
   1105  1.1.1.3  fvdl 
   1106  1.1.1.3  fvdl 		/*
   1107  1.1.1.3  fvdl 		 * Loop around generating replies for all write rpcs that have
   1108  1.1.1.3  fvdl 		 * now been completed.
   1109  1.1.1.3  fvdl 		 */
   1110  1.1.1.3  fvdl 		swp = nfsd;
   1111  1.1.1.3  fvdl 		do {
   1112  1.1.1.3  fvdl 		    if (error) {
   1113  1.1.1.3  fvdl 			nfsm_writereply(NFSX_WCCDATA(v3), v3);
   1114  1.1.1.3  fvdl 			if (v3) {
   1115  1.1.1.3  fvdl 			    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
   1116  1.1.1.3  fvdl 			}
   1117  1.1.1.3  fvdl 		    } else {
   1118  1.1.1.3  fvdl 			nfsm_writereply(NFSX_PREOPATTR(v3) +
   1119  1.1.1.3  fvdl 			    NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
   1120  1.1.1.3  fvdl 			    NFSX_WRITEVERF(v3), v3);
   1121  1.1.1.3  fvdl 			if (v3) {
   1122  1.1.1.3  fvdl 			    nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
   1123  1.1.1.3  fvdl 			    nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
   1124  1.1.1.3  fvdl 			    *tl++ = txdr_unsigned(nfsd->nd_len);
   1125  1.1.1.3  fvdl 			    *tl++ = txdr_unsigned(swp->nd_stable);
   1126  1.1.1.3  fvdl 			    /*
   1127  1.1.1.3  fvdl 			     * Actually, there is no need to txdr these fields,
   1128  1.1.1.3  fvdl 			     * but it may make the values more human readable,
   1129  1.1.1.3  fvdl 			     * for debugging purposes.
   1130  1.1.1.3  fvdl 			     */
   1131  1.1.1.3  fvdl 			    *tl++ = txdr_unsigned(boottime.tv_sec);
   1132  1.1.1.3  fvdl 			    *tl = txdr_unsigned(boottime.tv_usec);
   1133  1.1.1.3  fvdl 			} else {
   1134  1.1.1.3  fvdl 			    nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
   1135  1.1.1.3  fvdl 			    nfsm_srvfillattr(&va, fp);
   1136  1.1.1.3  fvdl 			}
   1137  1.1.1.3  fvdl 		    }
   1138  1.1.1.3  fvdl 		    nfsd->nd_mreq = mreq;
   1139  1.1.1.3  fvdl 		    if (nfsd->nd_mrep)
   1140  1.1.1.3  fvdl 			panic("nfsrv_write: nd_mrep not free");
   1141  1.1.1.3  fvdl 
   1142  1.1.1.3  fvdl 		    /*
   1143  1.1.1.3  fvdl 		     * Done. Put it at the head of the timer queue so that
   1144  1.1.1.3  fvdl 		     * the final phase can return the reply.
   1145  1.1.1.3  fvdl 		     */
   1146  1.1.1.3  fvdl 		    s = splsoftclock();
   1147  1.1.1.3  fvdl 		    if (nfsd != swp) {
   1148  1.1.1.3  fvdl 			nfsd->nd_time = 0;
   1149  1.1.1.3  fvdl 			LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
   1150  1.1.1.3  fvdl 		    }
   1151  1.1.1.3  fvdl 		    nfsd = swp->nd_coalesce.lh_first;
   1152  1.1.1.3  fvdl 		    if (nfsd) {
   1153  1.1.1.3  fvdl 			LIST_REMOVE(nfsd, nd_tq);
   1154  1.1.1.3  fvdl 		    }
   1155  1.1.1.3  fvdl 		    splx(s);
   1156  1.1.1.3  fvdl 		} while (nfsd);
   1157  1.1.1.3  fvdl 		s = splsoftclock();
   1158  1.1.1.3  fvdl 		swp->nd_time = 0;
   1159  1.1.1.3  fvdl 		LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
   1160  1.1.1.3  fvdl 		splx(s);
   1161  1.1.1.3  fvdl 		goto loop1;
   1162      1.1   cgd 	}
   1163  1.1.1.3  fvdl 	splx(s);
   1164  1.1.1.3  fvdl 
   1165  1.1.1.3  fvdl 	/*
   1166  1.1.1.3  fvdl 	 * Search for a reply to return.
   1167  1.1.1.3  fvdl 	 */
   1168  1.1.1.3  fvdl 	s = splsoftclock();
   1169  1.1.1.3  fvdl 	for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = nfsd->nd_tq.le_next)
   1170  1.1.1.3  fvdl 		if (nfsd->nd_mreq) {
   1171  1.1.1.3  fvdl 		    LIST_REMOVE(nfsd, nd_tq);
   1172  1.1.1.3  fvdl 		    *mrq = nfsd->nd_mreq;
   1173  1.1.1.3  fvdl 		    *ndp = nfsd;
   1174  1.1.1.3  fvdl 		    break;
   1175  1.1.1.3  fvdl 		}
   1176  1.1.1.3  fvdl 	splx(s);
   1177  1.1.1.3  fvdl 	return (0);
   1178  1.1.1.3  fvdl }
   1179  1.1.1.3  fvdl 
   1180  1.1.1.3  fvdl /*
   1181  1.1.1.3  fvdl  * Coalesce the write request nfsd into owp. To do this we must:
   1182  1.1.1.3  fvdl  * - remove nfsd from the queues
   1183  1.1.1.3  fvdl  * - merge nfsd->nd_mrep into owp->nd_mrep
   1184  1.1.1.3  fvdl  * - update the nd_eoff and nd_stable for owp
   1185  1.1.1.3  fvdl  * - put nfsd on owp's nd_coalesce list
   1186  1.1.1.3  fvdl  * NB: Must be called at splsoftclock().
   1187  1.1.1.3  fvdl  */
   1188  1.1.1.3  fvdl void
   1189  1.1.1.3  fvdl nfsrvw_coalesce(owp, nfsd)
   1190  1.1.1.3  fvdl         register struct nfsrv_descript *owp;
   1191  1.1.1.3  fvdl         register struct nfsrv_descript *nfsd;
   1192  1.1.1.3  fvdl {
   1193  1.1.1.3  fvdl         register int overlap;
   1194  1.1.1.3  fvdl         register struct mbuf *mp;
   1195  1.1.1.3  fvdl 
   1196  1.1.1.3  fvdl         LIST_REMOVE(nfsd, nd_hash);
   1197  1.1.1.3  fvdl         LIST_REMOVE(nfsd, nd_tq);
   1198  1.1.1.3  fvdl         if (owp->nd_eoff < nfsd->nd_eoff) {
   1199  1.1.1.3  fvdl             overlap = owp->nd_eoff - nfsd->nd_off;
   1200  1.1.1.3  fvdl             if (overlap < 0)
   1201  1.1.1.3  fvdl                 panic("nfsrv_coalesce: bad off");
   1202  1.1.1.3  fvdl             if (overlap > 0)
   1203  1.1.1.3  fvdl                 m_adj(nfsd->nd_mrep, overlap);
   1204  1.1.1.3  fvdl             mp = owp->nd_mrep;
   1205  1.1.1.3  fvdl             while (mp->m_next)
   1206  1.1.1.3  fvdl                 mp = mp->m_next;
   1207  1.1.1.3  fvdl             mp->m_next = nfsd->nd_mrep;
   1208  1.1.1.3  fvdl             owp->nd_eoff = nfsd->nd_eoff;
   1209  1.1.1.3  fvdl         } else
   1210  1.1.1.3  fvdl             m_freem(nfsd->nd_mrep);
   1211  1.1.1.3  fvdl         nfsd->nd_mrep = NULL;
   1212  1.1.1.3  fvdl         if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
   1213  1.1.1.3  fvdl             owp->nd_stable = NFSV3WRITE_FILESYNC;
   1214  1.1.1.3  fvdl         else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
   1215  1.1.1.3  fvdl             owp->nd_stable == NFSV3WRITE_UNSTABLE)
   1216  1.1.1.3  fvdl             owp->nd_stable = NFSV3WRITE_DATASYNC;
   1217  1.1.1.3  fvdl         LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
   1218  1.1.1.3  fvdl }
   1219  1.1.1.3  fvdl 
   1220  1.1.1.3  fvdl /*
   1221  1.1.1.3  fvdl  * Sort the group list in increasing numerical order.
   1222  1.1.1.3  fvdl  * (Insertion sort by Chris Torek, who was grossed out by the bubble sort
   1223  1.1.1.3  fvdl  *  that used to be here.)
   1224  1.1.1.3  fvdl  */
   1225  1.1.1.3  fvdl void
   1226  1.1.1.3  fvdl nfsrvw_sort(list, num)
   1227  1.1.1.3  fvdl         register gid_t *list;
   1228  1.1.1.3  fvdl         register int num;
   1229  1.1.1.3  fvdl {
   1230  1.1.1.3  fvdl 	register int i, j;
   1231  1.1.1.3  fvdl 	gid_t v;
   1232  1.1.1.3  fvdl 
   1233  1.1.1.3  fvdl 	/* Insertion sort. */
   1234  1.1.1.3  fvdl 	for (i = 1; i < num; i++) {
   1235  1.1.1.3  fvdl 		v = list[i];
   1236  1.1.1.3  fvdl 		/* find correct slot for value v, moving others up */
   1237  1.1.1.3  fvdl 		for (j = i; --j >= 0 && v < list[j];)
   1238  1.1.1.3  fvdl 			list[j + 1] = list[j];
   1239  1.1.1.3  fvdl 		list[j + 1] = v;
   1240  1.1.1.2  fvdl 	}
   1241  1.1.1.3  fvdl }
   1242  1.1.1.3  fvdl 
   1243  1.1.1.3  fvdl /*
   1244  1.1.1.3  fvdl  * copy credentials making sure that the result can be compared with bcmp().
   1245  1.1.1.3  fvdl  */
   1246  1.1.1.3  fvdl void
   1247  1.1.1.3  fvdl nfsrv_setcred(incred, outcred)
   1248  1.1.1.3  fvdl 	register struct ucred *incred, *outcred;
   1249  1.1.1.3  fvdl {
   1250  1.1.1.3  fvdl 	register int i;
   1251  1.1.1.3  fvdl 
   1252  1.1.1.3  fvdl 	bzero((caddr_t)outcred, sizeof (struct ucred));
   1253  1.1.1.3  fvdl 	outcred->cr_ref = 1;
   1254  1.1.1.3  fvdl 	outcred->cr_uid = incred->cr_uid;
   1255  1.1.1.3  fvdl 	outcred->cr_ngroups = incred->cr_ngroups;
   1256  1.1.1.3  fvdl 	for (i = 0; i < incred->cr_ngroups; i++)
   1257  1.1.1.3  fvdl 		outcred->cr_groups[i] = incred->cr_groups[i];
   1258  1.1.1.3  fvdl 	nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups);
   1259      1.1   cgd }
   1260      1.1   cgd 
   1261      1.1   cgd /*
   1262      1.1   cgd  * nfs create service
   1263      1.1   cgd  * now does a truncate to 0 length via. setattr if it already exists
   1264      1.1   cgd  */
   1265  1.1.1.3  fvdl int
   1266  1.1.1.3  fvdl nfsrv_create(nfsd, slp, procp, mrq)
   1267  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   1268  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   1269  1.1.1.3  fvdl 	struct proc *procp;
   1270  1.1.1.3  fvdl 	struct mbuf **mrq;
   1271      1.1   cgd {
   1272  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   1273  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   1274  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   1275  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   1276  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
   1277  1.1.1.3  fvdl 	struct vattr va, dirfor, diraft;
   1278      1.1   cgd 	register struct vattr *vap = &va;
   1279  1.1.1.2  fvdl 	register struct nfsv2_sattr *sp;
   1280  1.1.1.2  fvdl 	register u_long *tl;
   1281      1.1   cgd 	struct nameidata nd;
   1282      1.1   cgd 	register caddr_t cp;
   1283      1.1   cgd 	register long t1;
   1284      1.1   cgd 	caddr_t bpos;
   1285  1.1.1.3  fvdl 	int error = 0, rdev, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
   1286  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
   1287      1.1   cgd 	char *cp2;
   1288      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
   1289  1.1.1.3  fvdl 	struct vnode *vp, *dirp = (struct vnode *)0;
   1290  1.1.1.3  fvdl 	nfsfh_t nfh;
   1291      1.1   cgd 	fhandle_t *fhp;
   1292  1.1.1.3  fvdl 	u_quad_t frev, tempsize;
   1293  1.1.1.3  fvdl 	u_char cverf[NFSX_V3CREATEVERF];
   1294      1.1   cgd 
   1295  1.1.1.3  fvdl #ifndef nolint
   1296  1.1.1.3  fvdl 	rdev = 0;
   1297  1.1.1.3  fvdl #endif
   1298  1.1.1.2  fvdl 	nd.ni_cnd.cn_nameiop = 0;
   1299      1.1   cgd 	fhp = &nfh.fh_generic;
   1300      1.1   cgd 	nfsm_srvmtofh(fhp);
   1301  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   1302  1.1.1.2  fvdl 	nd.ni_cnd.cn_cred = cred;
   1303  1.1.1.2  fvdl 	nd.ni_cnd.cn_nameiop = CREATE;
   1304  1.1.1.2  fvdl 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
   1305  1.1.1.3  fvdl 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
   1306  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   1307  1.1.1.3  fvdl 	if (dirp) {
   1308  1.1.1.3  fvdl 		if (v3)
   1309  1.1.1.3  fvdl 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
   1310  1.1.1.3  fvdl 				procp);
   1311  1.1.1.3  fvdl 		else {
   1312  1.1.1.3  fvdl 			vrele(dirp);
   1313  1.1.1.3  fvdl 			dirp = (struct vnode *)0;
   1314  1.1.1.3  fvdl 		}
   1315  1.1.1.3  fvdl 	}
   1316  1.1.1.3  fvdl 	if (error) {
   1317  1.1.1.3  fvdl 		nfsm_reply(NFSX_WCCDATA(v3));
   1318  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   1319  1.1.1.3  fvdl 		if (dirp)
   1320  1.1.1.3  fvdl 			vrele(dirp);
   1321  1.1.1.3  fvdl 		return (0);
   1322  1.1.1.3  fvdl 	}
   1323      1.1   cgd 	VATTR_NULL(vap);
   1324  1.1.1.3  fvdl 	if (v3) {
   1325  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
   1326  1.1.1.3  fvdl 		how = fxdr_unsigned(int, *tl);
   1327  1.1.1.3  fvdl 		switch (how) {
   1328  1.1.1.3  fvdl 		case NFSV3CREATE_GUARDED:
   1329  1.1.1.3  fvdl 			if (nd.ni_vp) {
   1330  1.1.1.3  fvdl 				error = EEXIST;
   1331  1.1.1.3  fvdl 				break;
   1332  1.1.1.3  fvdl 			}
   1333  1.1.1.3  fvdl 		case NFSV3CREATE_UNCHECKED:
   1334  1.1.1.3  fvdl 			nfsm_srvsattr(vap);
   1335  1.1.1.3  fvdl 			break;
   1336  1.1.1.3  fvdl 		case NFSV3CREATE_EXCLUSIVE:
   1337  1.1.1.3  fvdl 			nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
   1338  1.1.1.3  fvdl 			bcopy(cp, cverf, NFSX_V3CREATEVERF);
   1339  1.1.1.3  fvdl 			exclusive_flag = 1;
   1340  1.1.1.3  fvdl 			if (nd.ni_vp == NULL)
   1341  1.1.1.3  fvdl 				vap->va_mode = 0;
   1342  1.1.1.3  fvdl 			break;
   1343  1.1.1.3  fvdl 		};
   1344  1.1.1.3  fvdl 		vap->va_type = VREG;
   1345  1.1.1.3  fvdl 	} else {
   1346  1.1.1.3  fvdl 		nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
   1347  1.1.1.3  fvdl 		vap->va_type = IFTOVT(fxdr_unsigned(u_long, sp->sa_mode));
   1348  1.1.1.3  fvdl 		if (vap->va_type == VNON)
   1349  1.1.1.3  fvdl 			vap->va_type = VREG;
   1350  1.1.1.3  fvdl 		vap->va_mode = nfstov_mode(sp->sa_mode);
   1351  1.1.1.3  fvdl 		switch (vap->va_type) {
   1352  1.1.1.3  fvdl 		case VREG:
   1353  1.1.1.3  fvdl 			tsize = fxdr_unsigned(long, sp->sa_size);
   1354  1.1.1.3  fvdl 			if (tsize != -1)
   1355  1.1.1.3  fvdl 				vap->va_size = (u_quad_t)tsize;
   1356  1.1.1.3  fvdl 			break;
   1357  1.1.1.3  fvdl 		case VCHR:
   1358  1.1.1.3  fvdl 		case VBLK:
   1359  1.1.1.3  fvdl 		case VFIFO:
   1360  1.1.1.3  fvdl 			rdev = fxdr_unsigned(long, sp->sa_size);
   1361  1.1.1.3  fvdl 			break;
   1362  1.1.1.3  fvdl 		};
   1363  1.1.1.3  fvdl 	}
   1364  1.1.1.3  fvdl 
   1365      1.1   cgd 	/*
   1366      1.1   cgd 	 * Iff doesn't exist, create it
   1367      1.1   cgd 	 * otherwise just truncate to 0 length
   1368      1.1   cgd 	 *   should I set the mode too ??
   1369      1.1   cgd 	 */
   1370      1.1   cgd 	if (nd.ni_vp == NULL) {
   1371      1.1   cgd 		if (vap->va_type == VREG || vap->va_type == VSOCK) {
   1372      1.1   cgd 			vrele(nd.ni_startdir);
   1373  1.1.1.3  fvdl 			nqsrv_getl(nd.ni_dvp, ND_WRITE);
   1374  1.1.1.3  fvdl 			error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
   1375  1.1.1.3  fvdl 			if (!error) {
   1376  1.1.1.3  fvdl 				FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1377  1.1.1.3  fvdl 				if (exclusive_flag) {
   1378  1.1.1.3  fvdl 					exclusive_flag = 0;
   1379  1.1.1.3  fvdl 					VATTR_NULL(vap);
   1380  1.1.1.3  fvdl 					bcopy(cverf, (caddr_t)&vap->va_atime,
   1381  1.1.1.3  fvdl 						NFSX_V3CREATEVERF);
   1382  1.1.1.3  fvdl 					error = VOP_SETATTR(nd.ni_vp, vap, cred,
   1383  1.1.1.3  fvdl 						procp);
   1384  1.1.1.3  fvdl 				}
   1385  1.1.1.3  fvdl 			}
   1386      1.1   cgd 		} else if (vap->va_type == VCHR || vap->va_type == VBLK ||
   1387      1.1   cgd 			vap->va_type == VFIFO) {
   1388      1.1   cgd 			if (vap->va_type == VCHR && rdev == 0xffffffff)
   1389      1.1   cgd 				vap->va_type = VFIFO;
   1390  1.1.1.3  fvdl 			if (error = suser(cred, (u_short *)0)) {
   1391  1.1.1.3  fvdl 				vrele(nd.ni_startdir);
   1392  1.1.1.3  fvdl 				free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1393  1.1.1.2  fvdl 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1394      1.1   cgd 				vput(nd.ni_dvp);
   1395  1.1.1.3  fvdl 				nfsm_reply(0);
   1396  1.1.1.3  fvdl 				return (error);
   1397      1.1   cgd 			} else
   1398      1.1   cgd 				vap->va_rdev = (dev_t)rdev;
   1399  1.1.1.3  fvdl 			nqsrv_getl(nd.ni_dvp, ND_WRITE);
   1400  1.1.1.2  fvdl 			if (error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) {
   1401      1.1   cgd 				vrele(nd.ni_startdir);
   1402      1.1   cgd 				nfsm_reply(0);
   1403      1.1   cgd 			}
   1404  1.1.1.2  fvdl 			nd.ni_cnd.cn_nameiop = LOOKUP;
   1405  1.1.1.2  fvdl 			nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
   1406  1.1.1.3  fvdl 			nd.ni_cnd.cn_proc = procp;
   1407  1.1.1.3  fvdl 			nd.ni_cnd.cn_cred = cred;
   1408  1.1.1.2  fvdl 			if (error = lookup(&nd)) {
   1409  1.1.1.2  fvdl 				free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1410      1.1   cgd 				nfsm_reply(0);
   1411      1.1   cgd 			}
   1412  1.1.1.2  fvdl 			FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1413  1.1.1.2  fvdl 			if (nd.ni_cnd.cn_flags & ISSYMLINK) {
   1414      1.1   cgd 				vrele(nd.ni_dvp);
   1415      1.1   cgd 				vput(nd.ni_vp);
   1416  1.1.1.2  fvdl 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1417      1.1   cgd 				error = EINVAL;
   1418      1.1   cgd 				nfsm_reply(0);
   1419      1.1   cgd 			}
   1420      1.1   cgd 		} else {
   1421  1.1.1.3  fvdl 			vrele(nd.ni_startdir);
   1422  1.1.1.3  fvdl 			free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1423  1.1.1.2  fvdl 			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1424      1.1   cgd 			vput(nd.ni_dvp);
   1425      1.1   cgd 			error = ENXIO;
   1426      1.1   cgd 		}
   1427      1.1   cgd 		vp = nd.ni_vp;
   1428      1.1   cgd 	} else {
   1429      1.1   cgd 		vrele(nd.ni_startdir);
   1430  1.1.1.2  fvdl 		free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1431      1.1   cgd 		vp = nd.ni_vp;
   1432      1.1   cgd 		if (nd.ni_dvp == vp)
   1433      1.1   cgd 			vrele(nd.ni_dvp);
   1434      1.1   cgd 		else
   1435      1.1   cgd 			vput(nd.ni_dvp);
   1436  1.1.1.2  fvdl 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1437  1.1.1.2  fvdl 		if (vap->va_size != -1) {
   1438  1.1.1.3  fvdl 			error = nfsrv_access(vp, VWRITE, cred,
   1439  1.1.1.3  fvdl 			    (nd.ni_cnd.cn_flags & RDONLY), procp);
   1440  1.1.1.3  fvdl 			if (!error) {
   1441  1.1.1.3  fvdl 				nqsrv_getl(vp, ND_WRITE);
   1442  1.1.1.3  fvdl 				tempsize = vap->va_size;
   1443  1.1.1.3  fvdl 				VATTR_NULL(vap);
   1444  1.1.1.3  fvdl 				vap->va_size = tempsize;
   1445  1.1.1.3  fvdl 				error = VOP_SETATTR(vp, vap, cred,
   1446  1.1.1.3  fvdl 					 procp);
   1447  1.1.1.2  fvdl 			}
   1448  1.1.1.3  fvdl 			if (error)
   1449  1.1.1.2  fvdl 				vput(vp);
   1450      1.1   cgd 		}
   1451      1.1   cgd 	}
   1452  1.1.1.3  fvdl 	if (!error) {
   1453  1.1.1.3  fvdl 		bzero((caddr_t)fhp, sizeof(nfh));
   1454  1.1.1.3  fvdl 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
   1455  1.1.1.3  fvdl 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
   1456  1.1.1.3  fvdl 		if (!error)
   1457  1.1.1.3  fvdl 			error = VOP_GETATTR(vp, vap, cred, procp);
   1458      1.1   cgd 		vput(vp);
   1459      1.1   cgd 	}
   1460  1.1.1.3  fvdl 	if (v3) {
   1461  1.1.1.3  fvdl 		if (exclusive_flag && !error &&
   1462  1.1.1.3  fvdl 			bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
   1463  1.1.1.3  fvdl 			error = EEXIST;
   1464  1.1.1.3  fvdl 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
   1465  1.1.1.3  fvdl 		vrele(dirp);
   1466  1.1.1.3  fvdl 	}
   1467  1.1.1.3  fvdl 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
   1468  1.1.1.3  fvdl 	if (v3) {
   1469  1.1.1.3  fvdl 		if (!error) {
   1470  1.1.1.3  fvdl 			nfsm_srvpostop_fh(fhp);
   1471  1.1.1.3  fvdl 			nfsm_srvpostop_attr(0, vap);
   1472  1.1.1.3  fvdl 		}
   1473  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   1474  1.1.1.3  fvdl 	} else {
   1475  1.1.1.3  fvdl 		nfsm_srvfhtom(fhp, v3);
   1476  1.1.1.3  fvdl 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
   1477  1.1.1.3  fvdl 		nfsm_srvfillattr(vap, fp);
   1478  1.1.1.3  fvdl 	}
   1479  1.1.1.3  fvdl 	return (0);
   1480      1.1   cgd nfsmout:
   1481  1.1.1.3  fvdl 	if (dirp)
   1482  1.1.1.3  fvdl 		vrele(dirp);
   1483  1.1.1.3  fvdl 	if (nd.ni_cnd.cn_nameiop) {
   1484      1.1   cgd 		vrele(nd.ni_startdir);
   1485  1.1.1.3  fvdl 		free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1486  1.1.1.3  fvdl 	}
   1487  1.1.1.2  fvdl 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1488      1.1   cgd 	if (nd.ni_dvp == nd.ni_vp)
   1489      1.1   cgd 		vrele(nd.ni_dvp);
   1490      1.1   cgd 	else
   1491      1.1   cgd 		vput(nd.ni_dvp);
   1492      1.1   cgd 	if (nd.ni_vp)
   1493      1.1   cgd 		vput(nd.ni_vp);
   1494      1.1   cgd 	return (error);
   1495      1.1   cgd }
   1496      1.1   cgd 
   1497      1.1   cgd /*
   1498  1.1.1.3  fvdl  * nfs v3 mknod service
   1499      1.1   cgd  */
   1500  1.1.1.3  fvdl int
   1501  1.1.1.3  fvdl nfsrv_mknod(nfsd, slp, procp, mrq)
   1502  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   1503  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   1504  1.1.1.3  fvdl 	struct proc *procp;
   1505  1.1.1.3  fvdl 	struct mbuf **mrq;
   1506      1.1   cgd {
   1507  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   1508  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   1509  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   1510  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   1511  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
   1512  1.1.1.3  fvdl 	struct vattr va, dirfor, diraft;
   1513  1.1.1.3  fvdl 	register struct vattr *vap = &va;
   1514      1.1   cgd 	register u_long *tl;
   1515  1.1.1.3  fvdl 	struct nameidata nd;
   1516  1.1.1.3  fvdl 	register caddr_t cp;
   1517      1.1   cgd 	register long t1;
   1518      1.1   cgd 	caddr_t bpos;
   1519  1.1.1.3  fvdl 	int error = 0, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
   1520  1.1.1.3  fvdl 	u_long major, minor;
   1521  1.1.1.3  fvdl 	enum vtype vtyp;
   1522      1.1   cgd 	char *cp2;
   1523  1.1.1.3  fvdl 	struct mbuf *mb, *mb2, *mreq;
   1524  1.1.1.3  fvdl 	struct vnode *vp, *dirp = (struct vnode *)0;
   1525  1.1.1.3  fvdl 	nfsfh_t nfh;
   1526      1.1   cgd 	fhandle_t *fhp;
   1527  1.1.1.2  fvdl 	u_quad_t frev;
   1528      1.1   cgd 
   1529  1.1.1.3  fvdl 	nd.ni_cnd.cn_nameiop = 0;
   1530      1.1   cgd 	fhp = &nfh.fh_generic;
   1531      1.1   cgd 	nfsm_srvmtofh(fhp);
   1532  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   1533  1.1.1.2  fvdl 	nd.ni_cnd.cn_cred = cred;
   1534  1.1.1.3  fvdl 	nd.ni_cnd.cn_nameiop = CREATE;
   1535  1.1.1.3  fvdl 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
   1536  1.1.1.3  fvdl 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
   1537  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   1538  1.1.1.3  fvdl 	if (dirp)
   1539  1.1.1.3  fvdl 		dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, procp);
   1540  1.1.1.3  fvdl 	if (error) {
   1541  1.1.1.3  fvdl 		nfsm_reply(NFSX_WCCDATA(1));
   1542  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   1543  1.1.1.3  fvdl 		if (dirp)
   1544  1.1.1.3  fvdl 			vrele(dirp);
   1545  1.1.1.3  fvdl 		return (0);
   1546  1.1.1.3  fvdl 	}
   1547  1.1.1.3  fvdl 	nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
   1548  1.1.1.3  fvdl 	vtyp = nfsv3tov_type(*tl);
   1549  1.1.1.3  fvdl 	if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
   1550  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   1551  1.1.1.3  fvdl 		free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1552  1.1.1.3  fvdl 		error = NFSERR_BADTYPE;
   1553  1.1.1.3  fvdl 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1554  1.1.1.3  fvdl 		vput(nd.ni_dvp);
   1555      1.1   cgd 		goto out;
   1556  1.1.1.3  fvdl 	}
   1557  1.1.1.3  fvdl 	VATTR_NULL(vap);
   1558  1.1.1.3  fvdl 	nfsm_srvsattr(vap);
   1559  1.1.1.3  fvdl 	if (vtyp == VCHR || vtyp == VBLK) {
   1560  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
   1561  1.1.1.3  fvdl 		major = fxdr_unsigned(u_long, *tl++);
   1562  1.1.1.3  fvdl 		minor = fxdr_unsigned(u_long, *tl);
   1563  1.1.1.3  fvdl 		vap->va_rdev = makedev(major, minor);
   1564  1.1.1.3  fvdl 	}
   1565  1.1.1.3  fvdl 
   1566      1.1   cgd 	/*
   1567  1.1.1.3  fvdl 	 * Iff doesn't exist, create it.
   1568      1.1   cgd 	 */
   1569  1.1.1.3  fvdl 	if (nd.ni_vp) {
   1570  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   1571  1.1.1.3  fvdl 		free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1572  1.1.1.3  fvdl 		error = EEXIST;
   1573  1.1.1.3  fvdl 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1574  1.1.1.3  fvdl 		vput(nd.ni_dvp);
   1575      1.1   cgd 		goto out;
   1576      1.1   cgd 	}
   1577  1.1.1.3  fvdl 	vap->va_type = vtyp;
   1578  1.1.1.3  fvdl 	if (vtyp == VSOCK) {
   1579  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   1580  1.1.1.3  fvdl 		nqsrv_getl(nd.ni_dvp, ND_WRITE);
   1581  1.1.1.3  fvdl 		error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
   1582  1.1.1.3  fvdl 		if (!error)
   1583  1.1.1.3  fvdl 			FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1584      1.1   cgd 	} else {
   1585  1.1.1.3  fvdl 		if (error = suser(cred, (u_short *)0)) {
   1586  1.1.1.3  fvdl 			vrele(nd.ni_startdir);
   1587  1.1.1.3  fvdl 			free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1588  1.1.1.3  fvdl 			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1589      1.1   cgd 			vput(nd.ni_dvp);
   1590  1.1.1.3  fvdl 			goto out;
   1591  1.1.1.3  fvdl 		}
   1592  1.1.1.3  fvdl 		nqsrv_getl(nd.ni_dvp, ND_WRITE);
   1593  1.1.1.3  fvdl 		if (error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) {
   1594  1.1.1.3  fvdl 			vrele(nd.ni_startdir);
   1595  1.1.1.3  fvdl 			goto out;
   1596  1.1.1.3  fvdl 		}
   1597  1.1.1.3  fvdl 		nd.ni_cnd.cn_nameiop = LOOKUP;
   1598  1.1.1.3  fvdl 		nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
   1599  1.1.1.3  fvdl 		nd.ni_cnd.cn_proc = procp;
   1600  1.1.1.3  fvdl 		nd.ni_cnd.cn_cred = procp->p_ucred;
   1601  1.1.1.3  fvdl 		error = lookup(&nd);
   1602  1.1.1.3  fvdl 		FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1603  1.1.1.3  fvdl 		if (error)
   1604  1.1.1.3  fvdl 			goto out;
   1605  1.1.1.3  fvdl 		if (nd.ni_cnd.cn_flags & ISSYMLINK) {
   1606  1.1.1.3  fvdl 			vrele(nd.ni_dvp);
   1607  1.1.1.3  fvdl 			vput(nd.ni_vp);
   1608  1.1.1.3  fvdl 			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1609  1.1.1.3  fvdl 			error = EINVAL;
   1610  1.1.1.3  fvdl 		}
   1611  1.1.1.3  fvdl 	}
   1612  1.1.1.3  fvdl out:
   1613  1.1.1.3  fvdl 	vp = nd.ni_vp;
   1614  1.1.1.3  fvdl 	if (!error) {
   1615  1.1.1.3  fvdl 		bzero((caddr_t)fhp, sizeof(nfh));
   1616  1.1.1.3  fvdl 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
   1617  1.1.1.3  fvdl 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
   1618  1.1.1.3  fvdl 		if (!error)
   1619  1.1.1.3  fvdl 			error = VOP_GETATTR(vp, vap, cred, procp);
   1620      1.1   cgd 		vput(vp);
   1621      1.1   cgd 	}
   1622  1.1.1.3  fvdl 	diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
   1623  1.1.1.3  fvdl 	vrele(dirp);
   1624  1.1.1.3  fvdl 	nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
   1625  1.1.1.3  fvdl 	if (!error) {
   1626  1.1.1.3  fvdl 		nfsm_srvpostop_fh(fhp);
   1627  1.1.1.3  fvdl 		nfsm_srvpostop_attr(0, vap);
   1628  1.1.1.3  fvdl 	}
   1629  1.1.1.3  fvdl 	nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   1630  1.1.1.3  fvdl 	return (0);
   1631  1.1.1.3  fvdl nfsmout:
   1632  1.1.1.3  fvdl 	if (dirp)
   1633  1.1.1.3  fvdl 		vrele(dirp);
   1634  1.1.1.3  fvdl 	if (nd.ni_cnd.cn_nameiop) {
   1635  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   1636  1.1.1.3  fvdl 		free((caddr_t)nd.ni_cnd.cn_pnbuf, M_NAMEI);
   1637  1.1.1.3  fvdl 	}
   1638  1.1.1.3  fvdl 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1639  1.1.1.3  fvdl 	if (nd.ni_dvp == nd.ni_vp)
   1640  1.1.1.3  fvdl 		vrele(nd.ni_dvp);
   1641  1.1.1.3  fvdl 	else
   1642  1.1.1.3  fvdl 		vput(nd.ni_dvp);
   1643  1.1.1.3  fvdl 	if (nd.ni_vp)
   1644  1.1.1.3  fvdl 		vput(nd.ni_vp);
   1645  1.1.1.3  fvdl 	return (error);
   1646  1.1.1.3  fvdl }
   1647  1.1.1.3  fvdl 
   1648  1.1.1.3  fvdl /*
   1649  1.1.1.3  fvdl  * nfs remove service
   1650  1.1.1.3  fvdl  */
   1651  1.1.1.3  fvdl int
   1652  1.1.1.3  fvdl nfsrv_remove(nfsd, slp, procp, mrq)
   1653  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   1654  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   1655  1.1.1.3  fvdl 	struct proc *procp;
   1656  1.1.1.3  fvdl 	struct mbuf **mrq;
   1657  1.1.1.3  fvdl {
   1658  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   1659  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   1660  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   1661  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   1662  1.1.1.3  fvdl 	struct nameidata nd;
   1663  1.1.1.3  fvdl 	register u_long *tl;
   1664  1.1.1.3  fvdl 	register long t1;
   1665  1.1.1.3  fvdl 	caddr_t bpos;
   1666  1.1.1.3  fvdl 	int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
   1667  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
   1668  1.1.1.3  fvdl 	char *cp2;
   1669  1.1.1.3  fvdl 	struct mbuf *mb, *mreq, *mb2;
   1670  1.1.1.3  fvdl 	struct vnode *vp, *dirp;
   1671  1.1.1.3  fvdl 	struct vattr dirfor, diraft;
   1672  1.1.1.3  fvdl 	nfsfh_t nfh;
   1673  1.1.1.3  fvdl 	fhandle_t *fhp;
   1674  1.1.1.3  fvdl 	u_quad_t frev;
   1675  1.1.1.3  fvdl 
   1676  1.1.1.3  fvdl #ifndef nolint
   1677  1.1.1.3  fvdl 	vp = (struct vnode *)0;
   1678  1.1.1.3  fvdl #endif
   1679  1.1.1.3  fvdl 	fhp = &nfh.fh_generic;
   1680  1.1.1.3  fvdl 	nfsm_srvmtofh(fhp);
   1681  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   1682  1.1.1.3  fvdl 	nd.ni_cnd.cn_cred = cred;
   1683  1.1.1.3  fvdl 	nd.ni_cnd.cn_nameiop = DELETE;
   1684  1.1.1.3  fvdl 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
   1685  1.1.1.3  fvdl 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
   1686  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   1687  1.1.1.3  fvdl 	if (dirp) {
   1688  1.1.1.3  fvdl 		if (v3)
   1689  1.1.1.3  fvdl 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
   1690  1.1.1.3  fvdl 				procp);
   1691  1.1.1.3  fvdl 		else
   1692  1.1.1.3  fvdl 			vrele(dirp);
   1693  1.1.1.3  fvdl 	}
   1694  1.1.1.3  fvdl 	if (!error) {
   1695  1.1.1.3  fvdl 		vp = nd.ni_vp;
   1696  1.1.1.3  fvdl 		if (vp->v_type == VDIR &&
   1697  1.1.1.3  fvdl 			(error = suser(cred, (u_short *)0)))
   1698  1.1.1.3  fvdl 			goto out;
   1699  1.1.1.3  fvdl 		/*
   1700  1.1.1.3  fvdl 		 * The root of a mounted filesystem cannot be deleted.
   1701  1.1.1.3  fvdl 		 */
   1702  1.1.1.3  fvdl 		if (vp->v_flag & VROOT) {
   1703  1.1.1.3  fvdl 			error = EBUSY;
   1704  1.1.1.3  fvdl 			goto out;
   1705  1.1.1.3  fvdl 		}
   1706  1.1.1.3  fvdl 		if (vp->v_flag & VTEXT)
   1707  1.1.1.3  fvdl 			(void) vnode_pager_uncache(vp);
   1708  1.1.1.3  fvdl out:
   1709  1.1.1.3  fvdl 		if (!error) {
   1710  1.1.1.3  fvdl 			nqsrv_getl(nd.ni_dvp, ND_WRITE);
   1711  1.1.1.3  fvdl 			nqsrv_getl(vp, ND_WRITE);
   1712  1.1.1.3  fvdl 			error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
   1713  1.1.1.3  fvdl 		} else {
   1714  1.1.1.3  fvdl 			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   1715  1.1.1.3  fvdl 			if (nd.ni_dvp == vp)
   1716  1.1.1.3  fvdl 				vrele(nd.ni_dvp);
   1717  1.1.1.3  fvdl 			else
   1718  1.1.1.3  fvdl 				vput(nd.ni_dvp);
   1719  1.1.1.3  fvdl 			vput(vp);
   1720  1.1.1.3  fvdl 		}
   1721  1.1.1.3  fvdl 	}
   1722  1.1.1.3  fvdl 	if (dirp && v3) {
   1723  1.1.1.3  fvdl 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
   1724  1.1.1.3  fvdl 		vrele(dirp);
   1725  1.1.1.3  fvdl 	}
   1726  1.1.1.3  fvdl 	nfsm_reply(NFSX_WCCDATA(v3));
   1727  1.1.1.3  fvdl 	if (v3) {
   1728  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   1729  1.1.1.3  fvdl 		return (0);
   1730  1.1.1.3  fvdl 	}
   1731      1.1   cgd 	nfsm_srvdone;
   1732      1.1   cgd }
   1733      1.1   cgd 
   1734      1.1   cgd /*
   1735      1.1   cgd  * nfs rename service
   1736      1.1   cgd  */
   1737  1.1.1.3  fvdl int
   1738  1.1.1.3  fvdl nfsrv_rename(nfsd, slp, procp, mrq)
   1739  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   1740  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   1741  1.1.1.3  fvdl 	struct proc *procp;
   1742  1.1.1.3  fvdl 	struct mbuf **mrq;
   1743      1.1   cgd {
   1744  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   1745  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   1746  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   1747  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   1748      1.1   cgd 	register u_long *tl;
   1749      1.1   cgd 	register long t1;
   1750      1.1   cgd 	caddr_t bpos;
   1751  1.1.1.3  fvdl 	int error = 0, cache, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
   1752  1.1.1.3  fvdl 	int tdirfor_ret = 1, tdiraft_ret = 1;
   1753  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
   1754      1.1   cgd 	char *cp2;
   1755  1.1.1.3  fvdl 	struct mbuf *mb, *mreq, *mb2;
   1756      1.1   cgd 	struct nameidata fromnd, tond;
   1757  1.1.1.3  fvdl 	struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
   1758  1.1.1.3  fvdl 	struct vnode *tdirp = (struct vnode *)0;
   1759  1.1.1.3  fvdl 	struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
   1760  1.1.1.3  fvdl 	nfsfh_t fnfh, tnfh;
   1761      1.1   cgd 	fhandle_t *ffhp, *tfhp;
   1762  1.1.1.2  fvdl 	u_quad_t frev;
   1763  1.1.1.2  fvdl 	uid_t saved_uid;
   1764      1.1   cgd 
   1765  1.1.1.3  fvdl #ifndef nolint
   1766  1.1.1.3  fvdl 	fvp = (struct vnode *)0;
   1767  1.1.1.3  fvdl #endif
   1768      1.1   cgd 	ffhp = &fnfh.fh_generic;
   1769      1.1   cgd 	tfhp = &tnfh.fh_generic;
   1770  1.1.1.2  fvdl 	fromnd.ni_cnd.cn_nameiop = 0;
   1771  1.1.1.2  fvdl 	tond.ni_cnd.cn_nameiop = 0;
   1772      1.1   cgd 	nfsm_srvmtofh(ffhp);
   1773  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   1774      1.1   cgd 	/*
   1775  1.1.1.2  fvdl 	 * Remember our original uid so that we can reset cr_uid before
   1776  1.1.1.2  fvdl 	 * the second nfs_namei() call, in case it is remapped.
   1777      1.1   cgd 	 */
   1778  1.1.1.2  fvdl 	saved_uid = cred->cr_uid;
   1779  1.1.1.2  fvdl 	fromnd.ni_cnd.cn_cred = cred;
   1780  1.1.1.2  fvdl 	fromnd.ni_cnd.cn_nameiop = DELETE;
   1781  1.1.1.2  fvdl 	fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
   1782  1.1.1.3  fvdl 	error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
   1783  1.1.1.3  fvdl 		&dpos, &fdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   1784  1.1.1.3  fvdl 	if (fdirp) {
   1785  1.1.1.3  fvdl 		if (v3)
   1786  1.1.1.3  fvdl 			fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred,
   1787  1.1.1.3  fvdl 				procp);
   1788  1.1.1.3  fvdl 		else {
   1789  1.1.1.3  fvdl 			vrele(fdirp);
   1790  1.1.1.3  fvdl 			fdirp = (struct vnode *)0;
   1791  1.1.1.3  fvdl 		}
   1792  1.1.1.3  fvdl 	}
   1793  1.1.1.3  fvdl 	if (error) {
   1794  1.1.1.3  fvdl 		nfsm_reply(2 * NFSX_WCCDATA(v3));
   1795  1.1.1.3  fvdl 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
   1796  1.1.1.3  fvdl 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
   1797  1.1.1.3  fvdl 		if (fdirp)
   1798  1.1.1.3  fvdl 			vrele(fdirp);
   1799  1.1.1.3  fvdl 		return (0);
   1800  1.1.1.3  fvdl 	}
   1801      1.1   cgd 	fvp = fromnd.ni_vp;
   1802      1.1   cgd 	nfsm_srvmtofh(tfhp);
   1803      1.1   cgd 	nfsm_strsiz(len2, NFS_MAXNAMLEN);
   1804  1.1.1.2  fvdl 	cred->cr_uid = saved_uid;
   1805  1.1.1.2  fvdl 	tond.ni_cnd.cn_cred = cred;
   1806  1.1.1.2  fvdl 	tond.ni_cnd.cn_nameiop = RENAME;
   1807  1.1.1.2  fvdl 	tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
   1808  1.1.1.3  fvdl 	error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
   1809  1.1.1.3  fvdl 		&dpos, &tdirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   1810  1.1.1.3  fvdl 	if (tdirp) {
   1811  1.1.1.3  fvdl 		if (v3)
   1812  1.1.1.3  fvdl 			tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred,
   1813  1.1.1.3  fvdl 				procp);
   1814  1.1.1.3  fvdl 		else {
   1815  1.1.1.3  fvdl 			vrele(tdirp);
   1816  1.1.1.3  fvdl 			tdirp = (struct vnode *)0;
   1817  1.1.1.3  fvdl 		}
   1818  1.1.1.3  fvdl 	}
   1819  1.1.1.3  fvdl 	if (error) {
   1820  1.1.1.2  fvdl 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   1821      1.1   cgd 		vrele(fromnd.ni_dvp);
   1822      1.1   cgd 		vrele(fvp);
   1823      1.1   cgd 		goto out1;
   1824      1.1   cgd 	}
   1825      1.1   cgd 	tdvp = tond.ni_dvp;
   1826      1.1   cgd 	tvp = tond.ni_vp;
   1827      1.1   cgd 	if (tvp != NULL) {
   1828      1.1   cgd 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
   1829  1.1.1.3  fvdl 			if (v3)
   1830  1.1.1.3  fvdl 				error = EEXIST;
   1831  1.1.1.3  fvdl 			else
   1832  1.1.1.3  fvdl 				error = EISDIR;
   1833      1.1   cgd 			goto out;
   1834      1.1   cgd 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
   1835  1.1.1.3  fvdl 			if (v3)
   1836  1.1.1.3  fvdl 				error = EEXIST;
   1837  1.1.1.3  fvdl 			else
   1838  1.1.1.3  fvdl 				error = ENOTDIR;
   1839      1.1   cgd 			goto out;
   1840      1.1   cgd 		}
   1841  1.1.1.2  fvdl 		if (tvp->v_type == VDIR && tvp->v_mountedhere) {
   1842  1.1.1.3  fvdl 			if (v3)
   1843  1.1.1.3  fvdl 				error = EXDEV;
   1844  1.1.1.3  fvdl 			else
   1845  1.1.1.3  fvdl 				error = ENOTEMPTY;
   1846  1.1.1.2  fvdl 			goto out;
   1847  1.1.1.2  fvdl 		}
   1848  1.1.1.2  fvdl 	}
   1849  1.1.1.2  fvdl 	if (fvp->v_type == VDIR && fvp->v_mountedhere) {
   1850  1.1.1.3  fvdl 		if (v3)
   1851  1.1.1.3  fvdl 			error = EXDEV;
   1852  1.1.1.3  fvdl 		else
   1853  1.1.1.3  fvdl 			error = ENOTEMPTY;
   1854  1.1.1.2  fvdl 		goto out;
   1855      1.1   cgd 	}
   1856      1.1   cgd 	if (fvp->v_mount != tdvp->v_mount) {
   1857  1.1.1.3  fvdl 		if (v3)
   1858  1.1.1.3  fvdl 			error = EXDEV;
   1859  1.1.1.3  fvdl 		else
   1860  1.1.1.3  fvdl 			error = ENOTEMPTY;
   1861      1.1   cgd 		goto out;
   1862      1.1   cgd 	}
   1863      1.1   cgd 	if (fvp == tdvp)
   1864  1.1.1.3  fvdl 		if (v3)
   1865  1.1.1.3  fvdl 			error = EINVAL;
   1866  1.1.1.3  fvdl 		else
   1867  1.1.1.3  fvdl 			error = ENOTEMPTY;
   1868      1.1   cgd 	/*
   1869      1.1   cgd 	 * If source is the same as the destination (that is the
   1870      1.1   cgd 	 * same vnode with the same name in the same directory),
   1871      1.1   cgd 	 * then there is nothing to do.
   1872      1.1   cgd 	 */
   1873      1.1   cgd 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
   1874  1.1.1.2  fvdl 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
   1875  1.1.1.2  fvdl 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
   1876  1.1.1.2  fvdl 	      fromnd.ni_cnd.cn_namelen))
   1877      1.1   cgd 		error = -1;
   1878      1.1   cgd out:
   1879      1.1   cgd 	if (!error) {
   1880  1.1.1.3  fvdl 		nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
   1881  1.1.1.3  fvdl 		nqsrv_getl(tdvp, ND_WRITE);
   1882  1.1.1.2  fvdl 		if (tvp)
   1883  1.1.1.3  fvdl 			nqsrv_getl(tvp, ND_WRITE);
   1884  1.1.1.2  fvdl 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
   1885  1.1.1.2  fvdl 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
   1886      1.1   cgd 	} else {
   1887  1.1.1.2  fvdl 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
   1888      1.1   cgd 		if (tdvp == tvp)
   1889      1.1   cgd 			vrele(tdvp);
   1890      1.1   cgd 		else
   1891      1.1   cgd 			vput(tdvp);
   1892      1.1   cgd 		if (tvp)
   1893      1.1   cgd 			vput(tvp);
   1894  1.1.1.2  fvdl 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   1895      1.1   cgd 		vrele(fromnd.ni_dvp);
   1896      1.1   cgd 		vrele(fvp);
   1897  1.1.1.3  fvdl 		if (error == -1)
   1898  1.1.1.3  fvdl 			error = 0;
   1899      1.1   cgd 	}
   1900      1.1   cgd 	vrele(tond.ni_startdir);
   1901  1.1.1.2  fvdl 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
   1902      1.1   cgd out1:
   1903  1.1.1.3  fvdl 	if (fdirp) {
   1904  1.1.1.3  fvdl 		fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, procp);
   1905  1.1.1.3  fvdl 		vrele(fdirp);
   1906  1.1.1.3  fvdl 	}
   1907  1.1.1.3  fvdl 	if (tdirp) {
   1908  1.1.1.3  fvdl 		tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, procp);
   1909  1.1.1.3  fvdl 		vrele(tdirp);
   1910  1.1.1.3  fvdl 	}
   1911      1.1   cgd 	vrele(fromnd.ni_startdir);
   1912  1.1.1.2  fvdl 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
   1913  1.1.1.3  fvdl 	nfsm_reply(2 * NFSX_WCCDATA(v3));
   1914  1.1.1.3  fvdl 	if (v3) {
   1915  1.1.1.3  fvdl 		nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
   1916  1.1.1.3  fvdl 		nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
   1917  1.1.1.3  fvdl 	}
   1918  1.1.1.3  fvdl 	return (0);
   1919      1.1   cgd 
   1920      1.1   cgd nfsmout:
   1921  1.1.1.3  fvdl 	if (fdirp)
   1922  1.1.1.3  fvdl 		vrele(fdirp);
   1923  1.1.1.3  fvdl 	if (tdirp)
   1924  1.1.1.3  fvdl 		vrele(tdirp);
   1925  1.1.1.3  fvdl 	if (tond.ni_cnd.cn_nameiop) {
   1926      1.1   cgd 		vrele(tond.ni_startdir);
   1927  1.1.1.2  fvdl 		FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
   1928      1.1   cgd 	}
   1929  1.1.1.3  fvdl 	if (fromnd.ni_cnd.cn_nameiop) {
   1930      1.1   cgd 		vrele(fromnd.ni_startdir);
   1931  1.1.1.2  fvdl 		FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
   1932  1.1.1.2  fvdl 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
   1933      1.1   cgd 		vrele(fromnd.ni_dvp);
   1934      1.1   cgd 		vrele(fvp);
   1935      1.1   cgd 	}
   1936      1.1   cgd 	return (error);
   1937      1.1   cgd }
   1938      1.1   cgd 
   1939      1.1   cgd /*
   1940      1.1   cgd  * nfs link service
   1941      1.1   cgd  */
   1942  1.1.1.3  fvdl int
   1943  1.1.1.3  fvdl nfsrv_link(nfsd, slp, procp, mrq)
   1944  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   1945  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   1946  1.1.1.3  fvdl 	struct proc *procp;
   1947  1.1.1.3  fvdl 	struct mbuf **mrq;
   1948      1.1   cgd {
   1949  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   1950  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   1951  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   1952  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   1953      1.1   cgd 	struct nameidata nd;
   1954      1.1   cgd 	register u_long *tl;
   1955      1.1   cgd 	register long t1;
   1956      1.1   cgd 	caddr_t bpos;
   1957  1.1.1.3  fvdl 	int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
   1958  1.1.1.3  fvdl 	int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
   1959      1.1   cgd 	char *cp2;
   1960  1.1.1.3  fvdl 	struct mbuf *mb, *mreq, *mb2;
   1961  1.1.1.3  fvdl 	struct vnode *vp, *xp, *dirp = (struct vnode *)0;
   1962  1.1.1.3  fvdl 	struct vattr dirfor, diraft, at;
   1963  1.1.1.3  fvdl 	nfsfh_t nfh, dnfh;
   1964      1.1   cgd 	fhandle_t *fhp, *dfhp;
   1965  1.1.1.2  fvdl 	u_quad_t frev;
   1966      1.1   cgd 
   1967      1.1   cgd 	fhp = &nfh.fh_generic;
   1968      1.1   cgd 	dfhp = &dnfh.fh_generic;
   1969      1.1   cgd 	nfsm_srvmtofh(fhp);
   1970      1.1   cgd 	nfsm_srvmtofh(dfhp);
   1971  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   1972  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
   1973  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
   1974  1.1.1.3  fvdl 		nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
   1975  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   1976  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   1977  1.1.1.3  fvdl 		return (0);
   1978  1.1.1.3  fvdl 	}
   1979  1.1.1.2  fvdl 	if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)))
   1980      1.1   cgd 		goto out1;
   1981  1.1.1.2  fvdl 	nd.ni_cnd.cn_cred = cred;
   1982  1.1.1.2  fvdl 	nd.ni_cnd.cn_nameiop = CREATE;
   1983  1.1.1.2  fvdl 	nd.ni_cnd.cn_flags = LOCKPARENT;
   1984  1.1.1.3  fvdl 	error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
   1985  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   1986  1.1.1.3  fvdl 	if (dirp) {
   1987  1.1.1.3  fvdl 		if (v3)
   1988  1.1.1.3  fvdl 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
   1989  1.1.1.3  fvdl 				procp);
   1990  1.1.1.3  fvdl 		else {
   1991  1.1.1.3  fvdl 			vrele(dirp);
   1992  1.1.1.3  fvdl 			dirp = (struct vnode *)0;
   1993  1.1.1.3  fvdl 		}
   1994  1.1.1.3  fvdl 	}
   1995  1.1.1.3  fvdl 	if (error)
   1996      1.1   cgd 		goto out1;
   1997      1.1   cgd 	xp = nd.ni_vp;
   1998      1.1   cgd 	if (xp != NULL) {
   1999      1.1   cgd 		error = EEXIST;
   2000      1.1   cgd 		goto out;
   2001      1.1   cgd 	}
   2002      1.1   cgd 	xp = nd.ni_dvp;
   2003      1.1   cgd 	if (vp->v_mount != xp->v_mount)
   2004      1.1   cgd 		error = EXDEV;
   2005      1.1   cgd out:
   2006      1.1   cgd 	if (!error) {
   2007  1.1.1.3  fvdl 		nqsrv_getl(vp, ND_WRITE);
   2008  1.1.1.3  fvdl 		nqsrv_getl(xp, ND_WRITE);
   2009  1.1.1.4  fvdl 		error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
   2010      1.1   cgd 	} else {
   2011  1.1.1.2  fvdl 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2012      1.1   cgd 		if (nd.ni_dvp == nd.ni_vp)
   2013      1.1   cgd 			vrele(nd.ni_dvp);
   2014      1.1   cgd 		else
   2015      1.1   cgd 			vput(nd.ni_dvp);
   2016      1.1   cgd 		if (nd.ni_vp)
   2017      1.1   cgd 			vrele(nd.ni_vp);
   2018      1.1   cgd 	}
   2019      1.1   cgd out1:
   2020  1.1.1.3  fvdl 	if (v3)
   2021  1.1.1.3  fvdl 		getret = VOP_GETATTR(vp, &at, cred, procp);
   2022  1.1.1.3  fvdl 	if (dirp) {
   2023  1.1.1.3  fvdl 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
   2024  1.1.1.3  fvdl 		vrele(dirp);
   2025  1.1.1.3  fvdl 	}
   2026      1.1   cgd 	vrele(vp);
   2027  1.1.1.3  fvdl 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
   2028  1.1.1.3  fvdl 	if (v3) {
   2029  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2030  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   2031  1.1.1.3  fvdl 		return (0);
   2032  1.1.1.3  fvdl 	}
   2033      1.1   cgd 	nfsm_srvdone;
   2034      1.1   cgd }
   2035      1.1   cgd 
   2036      1.1   cgd /*
   2037      1.1   cgd  * nfs symbolic link service
   2038      1.1   cgd  */
   2039  1.1.1.3  fvdl int
   2040  1.1.1.3  fvdl nfsrv_symlink(nfsd, slp, procp, mrq)
   2041  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   2042  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   2043  1.1.1.3  fvdl 	struct proc *procp;
   2044  1.1.1.3  fvdl 	struct mbuf **mrq;
   2045      1.1   cgd {
   2046  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   2047  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   2048  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   2049  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   2050  1.1.1.3  fvdl 	struct vattr va, dirfor, diraft;
   2051      1.1   cgd 	struct nameidata nd;
   2052      1.1   cgd 	register struct vattr *vap = &va;
   2053      1.1   cgd 	register u_long *tl;
   2054      1.1   cgd 	register long t1;
   2055      1.1   cgd 	struct nfsv2_sattr *sp;
   2056  1.1.1.3  fvdl 	char *bpos, *cp, *pathcp = (char *)0, *cp2;
   2057      1.1   cgd 	struct uio io;
   2058      1.1   cgd 	struct iovec iv;
   2059  1.1.1.3  fvdl 	int error = 0, cache, len, len2, dirfor_ret = 1, diraft_ret = 1;
   2060  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
   2061  1.1.1.3  fvdl 	struct mbuf *mb, *mreq, *mb2;
   2062  1.1.1.3  fvdl 	struct vnode *dirp = (struct vnode *)0;
   2063  1.1.1.3  fvdl 	nfsfh_t nfh;
   2064      1.1   cgd 	fhandle_t *fhp;
   2065  1.1.1.2  fvdl 	u_quad_t frev;
   2066      1.1   cgd 
   2067  1.1.1.3  fvdl 	nd.ni_cnd.cn_nameiop = 0;
   2068      1.1   cgd 	fhp = &nfh.fh_generic;
   2069      1.1   cgd 	nfsm_srvmtofh(fhp);
   2070  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   2071  1.1.1.2  fvdl 	nd.ni_cnd.cn_cred = cred;
   2072  1.1.1.2  fvdl 	nd.ni_cnd.cn_nameiop = CREATE;
   2073  1.1.1.3  fvdl 	nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
   2074  1.1.1.3  fvdl 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
   2075  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   2076  1.1.1.3  fvdl 	if (dirp) {
   2077  1.1.1.3  fvdl 		if (v3)
   2078  1.1.1.3  fvdl 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
   2079  1.1.1.3  fvdl 				procp);
   2080  1.1.1.3  fvdl 		else {
   2081  1.1.1.3  fvdl 			vrele(dirp);
   2082  1.1.1.3  fvdl 			dirp = (struct vnode *)0;
   2083  1.1.1.3  fvdl 		}
   2084  1.1.1.3  fvdl 	}
   2085  1.1.1.3  fvdl 	if (error)
   2086      1.1   cgd 		goto out;
   2087  1.1.1.3  fvdl 	VATTR_NULL(vap);
   2088  1.1.1.3  fvdl 	if (v3)
   2089  1.1.1.3  fvdl 		nfsm_srvsattr(vap);
   2090      1.1   cgd 	nfsm_strsiz(len2, NFS_MAXPATHLEN);
   2091      1.1   cgd 	MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
   2092      1.1   cgd 	iv.iov_base = pathcp;
   2093      1.1   cgd 	iv.iov_len = len2;
   2094      1.1   cgd 	io.uio_resid = len2;
   2095      1.1   cgd 	io.uio_offset = 0;
   2096      1.1   cgd 	io.uio_iov = &iv;
   2097      1.1   cgd 	io.uio_iovcnt = 1;
   2098      1.1   cgd 	io.uio_segflg = UIO_SYSSPACE;
   2099      1.1   cgd 	io.uio_rw = UIO_READ;
   2100      1.1   cgd 	io.uio_procp = (struct proc *)0;
   2101      1.1   cgd 	nfsm_mtouio(&io, len2);
   2102  1.1.1.3  fvdl 	if (!v3) {
   2103  1.1.1.3  fvdl 		nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
   2104  1.1.1.3  fvdl 		vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);
   2105  1.1.1.3  fvdl 	}
   2106      1.1   cgd 	*(pathcp + len2) = '\0';
   2107      1.1   cgd 	if (nd.ni_vp) {
   2108  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   2109  1.1.1.3  fvdl 		free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   2110  1.1.1.2  fvdl 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2111      1.1   cgd 		if (nd.ni_dvp == nd.ni_vp)
   2112      1.1   cgd 			vrele(nd.ni_dvp);
   2113      1.1   cgd 		else
   2114      1.1   cgd 			vput(nd.ni_dvp);
   2115      1.1   cgd 		vrele(nd.ni_vp);
   2116      1.1   cgd 		error = EEXIST;
   2117      1.1   cgd 		goto out;
   2118      1.1   cgd 	}
   2119  1.1.1.3  fvdl 	nqsrv_getl(nd.ni_dvp, ND_WRITE);
   2120  1.1.1.2  fvdl 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
   2121  1.1.1.3  fvdl 	if (error)
   2122  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   2123  1.1.1.3  fvdl 	else {
   2124  1.1.1.3  fvdl 	    if (v3) {
   2125  1.1.1.3  fvdl 		nd.ni_cnd.cn_nameiop = LOOKUP;
   2126  1.1.1.3  fvdl 		nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART | FOLLOW);
   2127  1.1.1.3  fvdl 		nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
   2128  1.1.1.3  fvdl 		nd.ni_cnd.cn_proc = procp;
   2129  1.1.1.3  fvdl 		nd.ni_cnd.cn_cred = cred;
   2130  1.1.1.3  fvdl 		error = lookup(&nd);
   2131  1.1.1.3  fvdl 		if (!error) {
   2132  1.1.1.3  fvdl 			bzero((caddr_t)fhp, sizeof(nfh));
   2133  1.1.1.3  fvdl 			fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
   2134  1.1.1.3  fvdl 			error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
   2135  1.1.1.3  fvdl 			if (!error)
   2136  1.1.1.3  fvdl 				error = VOP_GETATTR(nd.ni_vp, vap, cred,
   2137  1.1.1.3  fvdl 					procp);
   2138  1.1.1.3  fvdl 			vput(nd.ni_vp);
   2139  1.1.1.3  fvdl 		}
   2140  1.1.1.3  fvdl 	    } else
   2141  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   2142  1.1.1.3  fvdl 	    FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   2143  1.1.1.3  fvdl 	}
   2144      1.1   cgd out:
   2145      1.1   cgd 	if (pathcp)
   2146      1.1   cgd 		FREE(pathcp, M_TEMP);
   2147  1.1.1.3  fvdl 	if (dirp) {
   2148  1.1.1.3  fvdl 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
   2149  1.1.1.3  fvdl 		vrele(dirp);
   2150  1.1.1.3  fvdl 	}
   2151  1.1.1.3  fvdl 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
   2152  1.1.1.3  fvdl 	if (v3) {
   2153  1.1.1.3  fvdl 		if (!error) {
   2154  1.1.1.3  fvdl 			nfsm_srvpostop_fh(fhp);
   2155  1.1.1.3  fvdl 			nfsm_srvpostop_attr(0, vap);
   2156  1.1.1.3  fvdl 		}
   2157  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   2158  1.1.1.3  fvdl 	}
   2159  1.1.1.3  fvdl 	return (0);
   2160      1.1   cgd nfsmout:
   2161  1.1.1.3  fvdl 	if (nd.ni_cnd.cn_nameiop) {
   2162  1.1.1.3  fvdl 		vrele(nd.ni_startdir);
   2163  1.1.1.3  fvdl 		free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
   2164  1.1.1.3  fvdl 	}
   2165  1.1.1.3  fvdl 	if (dirp)
   2166  1.1.1.3  fvdl 		vrele(dirp);
   2167  1.1.1.2  fvdl 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2168      1.1   cgd 	if (nd.ni_dvp == nd.ni_vp)
   2169      1.1   cgd 		vrele(nd.ni_dvp);
   2170      1.1   cgd 	else
   2171      1.1   cgd 		vput(nd.ni_dvp);
   2172      1.1   cgd 	if (nd.ni_vp)
   2173      1.1   cgd 		vrele(nd.ni_vp);
   2174      1.1   cgd 	if (pathcp)
   2175      1.1   cgd 		FREE(pathcp, M_TEMP);
   2176      1.1   cgd 	return (error);
   2177      1.1   cgd }
   2178      1.1   cgd 
   2179      1.1   cgd /*
   2180      1.1   cgd  * nfs mkdir service
   2181      1.1   cgd  */
   2182  1.1.1.3  fvdl int
   2183  1.1.1.3  fvdl nfsrv_mkdir(nfsd, slp, procp, mrq)
   2184  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   2185  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   2186  1.1.1.3  fvdl 	struct proc *procp;
   2187  1.1.1.3  fvdl 	struct mbuf **mrq;
   2188      1.1   cgd {
   2189  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   2190  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   2191  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   2192  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   2193  1.1.1.3  fvdl 	struct vattr va, dirfor, diraft;
   2194      1.1   cgd 	register struct vattr *vap = &va;
   2195  1.1.1.3  fvdl 	register struct nfs_fattr *fp;
   2196      1.1   cgd 	struct nameidata nd;
   2197      1.1   cgd 	register caddr_t cp;
   2198      1.1   cgd 	register u_long *tl;
   2199      1.1   cgd 	register long t1;
   2200      1.1   cgd 	caddr_t bpos;
   2201  1.1.1.3  fvdl 	int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
   2202  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
   2203      1.1   cgd 	char *cp2;
   2204      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
   2205  1.1.1.3  fvdl 	struct vnode *vp, *dirp = (struct vnode *)0;
   2206  1.1.1.3  fvdl 	nfsfh_t nfh;
   2207      1.1   cgd 	fhandle_t *fhp;
   2208  1.1.1.2  fvdl 	u_quad_t frev;
   2209      1.1   cgd 
   2210      1.1   cgd 	fhp = &nfh.fh_generic;
   2211      1.1   cgd 	nfsm_srvmtofh(fhp);
   2212  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   2213  1.1.1.2  fvdl 	nd.ni_cnd.cn_cred = cred;
   2214  1.1.1.2  fvdl 	nd.ni_cnd.cn_nameiop = CREATE;
   2215  1.1.1.2  fvdl 	nd.ni_cnd.cn_flags = LOCKPARENT;
   2216  1.1.1.3  fvdl 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
   2217  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   2218  1.1.1.3  fvdl 	if (dirp) {
   2219  1.1.1.3  fvdl 		if (v3)
   2220  1.1.1.3  fvdl 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
   2221  1.1.1.3  fvdl 				procp);
   2222  1.1.1.3  fvdl 		else {
   2223  1.1.1.3  fvdl 			vrele(dirp);
   2224  1.1.1.3  fvdl 			dirp = (struct vnode *)0;
   2225  1.1.1.3  fvdl 		}
   2226  1.1.1.3  fvdl 	}
   2227  1.1.1.3  fvdl 	if (error) {
   2228  1.1.1.3  fvdl 		nfsm_reply(NFSX_WCCDATA(v3));
   2229  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   2230  1.1.1.3  fvdl 		if (dirp)
   2231  1.1.1.3  fvdl 			vrele(dirp);
   2232  1.1.1.3  fvdl 		return (0);
   2233  1.1.1.3  fvdl 	}
   2234      1.1   cgd 	VATTR_NULL(vap);
   2235  1.1.1.3  fvdl 	if (v3) {
   2236  1.1.1.3  fvdl 		nfsm_srvsattr(vap);
   2237  1.1.1.3  fvdl 	} else {
   2238  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
   2239  1.1.1.3  fvdl 		vap->va_mode = nfstov_mode(*tl++);
   2240  1.1.1.3  fvdl 	}
   2241      1.1   cgd 	vap->va_type = VDIR;
   2242      1.1   cgd 	vp = nd.ni_vp;
   2243      1.1   cgd 	if (vp != NULL) {
   2244  1.1.1.2  fvdl 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2245      1.1   cgd 		if (nd.ni_dvp == vp)
   2246      1.1   cgd 			vrele(nd.ni_dvp);
   2247      1.1   cgd 		else
   2248      1.1   cgd 			vput(nd.ni_dvp);
   2249      1.1   cgd 		vrele(vp);
   2250      1.1   cgd 		error = EEXIST;
   2251  1.1.1.3  fvdl 		goto out;
   2252      1.1   cgd 	}
   2253  1.1.1.3  fvdl 	nqsrv_getl(nd.ni_dvp, ND_WRITE);
   2254  1.1.1.3  fvdl 	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
   2255  1.1.1.3  fvdl 	if (!error) {
   2256  1.1.1.3  fvdl 		vp = nd.ni_vp;
   2257  1.1.1.3  fvdl 		bzero((caddr_t)fhp, sizeof(nfh));
   2258  1.1.1.3  fvdl 		fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
   2259  1.1.1.3  fvdl 		error = VFS_VPTOFH(vp, &fhp->fh_fid);
   2260  1.1.1.3  fvdl 		if (!error)
   2261  1.1.1.3  fvdl 			error = VOP_GETATTR(vp, vap, cred, procp);
   2262      1.1   cgd 		vput(vp);
   2263      1.1   cgd 	}
   2264  1.1.1.3  fvdl out:
   2265  1.1.1.3  fvdl 	if (dirp) {
   2266  1.1.1.3  fvdl 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
   2267  1.1.1.3  fvdl 		vrele(dirp);
   2268  1.1.1.3  fvdl 	}
   2269  1.1.1.3  fvdl 	nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
   2270  1.1.1.3  fvdl 	if (v3) {
   2271  1.1.1.3  fvdl 		if (!error) {
   2272  1.1.1.3  fvdl 			nfsm_srvpostop_fh(fhp);
   2273  1.1.1.3  fvdl 			nfsm_srvpostop_attr(0, vap);
   2274  1.1.1.3  fvdl 		}
   2275  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   2276  1.1.1.3  fvdl 	} else {
   2277  1.1.1.3  fvdl 		nfsm_srvfhtom(fhp, v3);
   2278  1.1.1.3  fvdl 		nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
   2279  1.1.1.3  fvdl 		nfsm_srvfillattr(vap, fp);
   2280  1.1.1.3  fvdl 	}
   2281  1.1.1.3  fvdl 	return (0);
   2282      1.1   cgd nfsmout:
   2283  1.1.1.3  fvdl 	if (dirp)
   2284  1.1.1.3  fvdl 		vrele(dirp);
   2285  1.1.1.2  fvdl 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2286      1.1   cgd 	if (nd.ni_dvp == nd.ni_vp)
   2287      1.1   cgd 		vrele(nd.ni_dvp);
   2288      1.1   cgd 	else
   2289      1.1   cgd 		vput(nd.ni_dvp);
   2290      1.1   cgd 	if (nd.ni_vp)
   2291      1.1   cgd 		vrele(nd.ni_vp);
   2292      1.1   cgd 	return (error);
   2293      1.1   cgd }
   2294      1.1   cgd 
   2295      1.1   cgd /*
   2296      1.1   cgd  * nfs rmdir service
   2297      1.1   cgd  */
   2298  1.1.1.3  fvdl int
   2299  1.1.1.3  fvdl nfsrv_rmdir(nfsd, slp, procp, mrq)
   2300  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   2301  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   2302  1.1.1.3  fvdl 	struct proc *procp;
   2303  1.1.1.3  fvdl 	struct mbuf **mrq;
   2304      1.1   cgd {
   2305  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   2306  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   2307  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   2308  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   2309      1.1   cgd 	register u_long *tl;
   2310      1.1   cgd 	register long t1;
   2311      1.1   cgd 	caddr_t bpos;
   2312  1.1.1.3  fvdl 	int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
   2313  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
   2314      1.1   cgd 	char *cp2;
   2315  1.1.1.3  fvdl 	struct mbuf *mb, *mreq, *mb2;
   2316  1.1.1.3  fvdl 	struct vnode *vp, *dirp = (struct vnode *)0;
   2317  1.1.1.3  fvdl 	struct vattr dirfor, diraft;
   2318  1.1.1.3  fvdl 	nfsfh_t nfh;
   2319      1.1   cgd 	fhandle_t *fhp;
   2320      1.1   cgd 	struct nameidata nd;
   2321  1.1.1.2  fvdl 	u_quad_t frev;
   2322      1.1   cgd 
   2323      1.1   cgd 	fhp = &nfh.fh_generic;
   2324      1.1   cgd 	nfsm_srvmtofh(fhp);
   2325  1.1.1.3  fvdl 	nfsm_srvnamesiz(len);
   2326  1.1.1.2  fvdl 	nd.ni_cnd.cn_cred = cred;
   2327  1.1.1.2  fvdl 	nd.ni_cnd.cn_nameiop = DELETE;
   2328  1.1.1.2  fvdl 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
   2329  1.1.1.3  fvdl 	error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
   2330  1.1.1.3  fvdl 		&dirp, procp, (nfsd->nd_flag & ND_KERBAUTH));
   2331  1.1.1.3  fvdl 	if (dirp) {
   2332  1.1.1.3  fvdl 		if (v3)
   2333  1.1.1.3  fvdl 			dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred,
   2334  1.1.1.3  fvdl 				procp);
   2335  1.1.1.3  fvdl 		else {
   2336  1.1.1.3  fvdl 			vrele(dirp);
   2337  1.1.1.3  fvdl 			dirp = (struct vnode *)0;
   2338  1.1.1.3  fvdl 		}
   2339  1.1.1.3  fvdl 	}
   2340  1.1.1.3  fvdl 	if (error) {
   2341  1.1.1.3  fvdl 		nfsm_reply(NFSX_WCCDATA(v3));
   2342  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   2343  1.1.1.3  fvdl 		if (dirp)
   2344  1.1.1.3  fvdl 			vrele(dirp);
   2345  1.1.1.3  fvdl 		return (0);
   2346  1.1.1.3  fvdl 	}
   2347      1.1   cgd 	vp = nd.ni_vp;
   2348      1.1   cgd 	if (vp->v_type != VDIR) {
   2349      1.1   cgd 		error = ENOTDIR;
   2350      1.1   cgd 		goto out;
   2351      1.1   cgd 	}
   2352      1.1   cgd 	/*
   2353      1.1   cgd 	 * No rmdir "." please.
   2354      1.1   cgd 	 */
   2355      1.1   cgd 	if (nd.ni_dvp == vp) {
   2356      1.1   cgd 		error = EINVAL;
   2357      1.1   cgd 		goto out;
   2358      1.1   cgd 	}
   2359      1.1   cgd 	/*
   2360      1.1   cgd 	 * The root of a mounted filesystem cannot be deleted.
   2361      1.1   cgd 	 */
   2362      1.1   cgd 	if (vp->v_flag & VROOT)
   2363      1.1   cgd 		error = EBUSY;
   2364      1.1   cgd out:
   2365      1.1   cgd 	if (!error) {
   2366  1.1.1.3  fvdl 		nqsrv_getl(nd.ni_dvp, ND_WRITE);
   2367  1.1.1.3  fvdl 		nqsrv_getl(vp, ND_WRITE);
   2368  1.1.1.2  fvdl 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
   2369      1.1   cgd 	} else {
   2370  1.1.1.2  fvdl 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
   2371      1.1   cgd 		if (nd.ni_dvp == nd.ni_vp)
   2372      1.1   cgd 			vrele(nd.ni_dvp);
   2373      1.1   cgd 		else
   2374      1.1   cgd 			vput(nd.ni_dvp);
   2375      1.1   cgd 		vput(vp);
   2376      1.1   cgd 	}
   2377  1.1.1.3  fvdl 	if (dirp) {
   2378  1.1.1.3  fvdl 		diraft_ret = VOP_GETATTR(dirp, &diraft, cred, procp);
   2379  1.1.1.3  fvdl 		vrele(dirp);
   2380  1.1.1.3  fvdl 	}
   2381  1.1.1.3  fvdl 	nfsm_reply(NFSX_WCCDATA(v3));
   2382  1.1.1.3  fvdl 	if (v3) {
   2383  1.1.1.3  fvdl 		nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
   2384  1.1.1.3  fvdl 		return (0);
   2385  1.1.1.3  fvdl 	}
   2386      1.1   cgd 	nfsm_srvdone;
   2387      1.1   cgd }
   2388      1.1   cgd 
   2389      1.1   cgd /*
   2390      1.1   cgd  * nfs readdir service
   2391      1.1   cgd  * - mallocs what it thinks is enough to read
   2392      1.1   cgd  *	count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
   2393      1.1   cgd  * - calls VOP_READDIR()
   2394      1.1   cgd  * - loops around building the reply
   2395      1.1   cgd  *	if the output generated exceeds count break out of loop
   2396      1.1   cgd  *	The nfsm_clget macro is used here so that the reply will be packed
   2397      1.1   cgd  *	tightly in mbuf clusters.
   2398      1.1   cgd  * - it only knows that it has encountered eof when the VOP_READDIR()
   2399      1.1   cgd  *	reads nothing
   2400      1.1   cgd  * - as such one readdir rpc will return eof false although you are there
   2401      1.1   cgd  *	and then the next will return eof
   2402  1.1.1.2  fvdl  * - it trims out records with d_fileno == 0
   2403      1.1   cgd  *	this doesn't matter for Unix clients, but they might confuse clients
   2404      1.1   cgd  *	for other os'.
   2405      1.1   cgd  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
   2406      1.1   cgd  *	than requested, but this may not apply to all filesystems. For
   2407      1.1   cgd  *	example, client NFS does not { although it is never remote mounted
   2408      1.1   cgd  *	anyhow }
   2409  1.1.1.3  fvdl  *     The alternate call nfsrv_readdirplus() does lookups as well.
   2410      1.1   cgd  * PS: The NFS protocol spec. does not clarify what the "count" byte
   2411      1.1   cgd  *	argument is a count of.. just name strings and file id's or the
   2412      1.1   cgd  *	entire reply rpc or ...
   2413      1.1   cgd  *	I tried just file name and id sizes and it confused the Sun client,
   2414      1.1   cgd  *	so I am using the full rpc size now. The "paranoia.." comment refers
   2415      1.1   cgd  *	to including the status longwords that are not a part of the dir.
   2416      1.1   cgd  *	"entry" structures, but are in the rpc.
   2417      1.1   cgd  */
   2418  1.1.1.2  fvdl struct flrep {
   2419  1.1.1.3  fvdl 	nfsuint64	fl_off;
   2420  1.1.1.3  fvdl 	u_long		fl_postopok;
   2421  1.1.1.3  fvdl 	u_long		fl_fattr[NFSX_V3FATTR / sizeof (u_long)];
   2422  1.1.1.3  fvdl 	u_long		fl_fhok;
   2423  1.1.1.3  fvdl 	u_long		fl_fhsize;
   2424  1.1.1.3  fvdl 	u_long		fl_nfh[NFSX_V3FH / sizeof (u_long)];
   2425  1.1.1.2  fvdl };
   2426  1.1.1.2  fvdl 
   2427  1.1.1.3  fvdl int
   2428  1.1.1.3  fvdl nfsrv_readdir(nfsd, slp, procp, mrq)
   2429  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   2430  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   2431  1.1.1.3  fvdl 	struct proc *procp;
   2432  1.1.1.3  fvdl 	struct mbuf **mrq;
   2433      1.1   cgd {
   2434  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   2435  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   2436  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   2437  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   2438      1.1   cgd 	register char *bp, *be;
   2439      1.1   cgd 	register struct mbuf *mp;
   2440  1.1.1.2  fvdl 	register struct dirent *dp;
   2441      1.1   cgd 	register caddr_t cp;
   2442      1.1   cgd 	register u_long *tl;
   2443      1.1   cgd 	register long t1;
   2444      1.1   cgd 	caddr_t bpos;
   2445  1.1.1.2  fvdl 	struct mbuf *mb, *mb2, *mreq, *mp2;
   2446  1.1.1.2  fvdl 	char *cpos, *cend, *cp2, *rbuf;
   2447      1.1   cgd 	struct vnode *vp;
   2448  1.1.1.3  fvdl 	struct vattr at;
   2449  1.1.1.3  fvdl 	nfsfh_t nfh;
   2450      1.1   cgd 	fhandle_t *fhp;
   2451      1.1   cgd 	struct uio io;
   2452      1.1   cgd 	struct iovec iv;
   2453  1.1.1.3  fvdl 	int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
   2454  1.1.1.3  fvdl 	int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
   2455  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
   2456  1.1.1.3  fvdl 	u_quad_t frev, off, toff, verf;
   2457  1.1.1.3  fvdl 	u_long *cookies = NULL, *cookiep;
   2458      1.1   cgd 
   2459      1.1   cgd 	fhp = &nfh.fh_generic;
   2460      1.1   cgd 	nfsm_srvmtofh(fhp);
   2461  1.1.1.3  fvdl 	if (v3) {
   2462  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, 5 * NFSX_UNSIGNED);
   2463  1.1.1.3  fvdl 		fxdr_hyper(tl, &toff);
   2464  1.1.1.3  fvdl 		tl += 2;
   2465  1.1.1.3  fvdl 		fxdr_hyper(tl, &verf);
   2466  1.1.1.3  fvdl 		tl += 2;
   2467  1.1.1.3  fvdl 	} else {
   2468  1.1.1.3  fvdl 		nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
   2469  1.1.1.3  fvdl 		toff = fxdr_unsigned(u_quad_t, *tl++);
   2470  1.1.1.3  fvdl 	}
   2471  1.1.1.3  fvdl 	off = toff;
   2472      1.1   cgd 	cnt = fxdr_unsigned(int, *tl);
   2473  1.1.1.3  fvdl 	siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
   2474  1.1.1.3  fvdl 	xfer = NFS_SRVMAXDATA(nfsd);
   2475  1.1.1.3  fvdl 	if (siz > xfer)
   2476  1.1.1.3  fvdl 		siz = xfer;
   2477      1.1   cgd 	fullsiz = siz;
   2478  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
   2479  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
   2480  1.1.1.3  fvdl 		nfsm_reply(NFSX_UNSIGNED);
   2481  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2482  1.1.1.3  fvdl 		return (0);
   2483  1.1.1.3  fvdl 	}
   2484  1.1.1.3  fvdl 	nqsrv_getl(vp, ND_READ);
   2485  1.1.1.3  fvdl 	if (v3) {
   2486  1.1.1.3  fvdl 		error = getret = VOP_GETATTR(vp, &at, cred, procp);
   2487  1.1.1.3  fvdl 		if (!error && toff && verf != at.va_filerev)
   2488  1.1.1.3  fvdl 			error = NFSERR_BAD_COOKIE;
   2489  1.1.1.3  fvdl 	}
   2490  1.1.1.3  fvdl 	if (!error)
   2491  1.1.1.3  fvdl 		error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
   2492  1.1.1.3  fvdl 	if (error) {
   2493      1.1   cgd 		vput(vp);
   2494  1.1.1.3  fvdl 		nfsm_reply(NFSX_POSTOPATTR(v3));
   2495  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2496  1.1.1.3  fvdl 		return (0);
   2497      1.1   cgd 	}
   2498  1.1.1.3  fvdl 	VOP_UNLOCK(vp, 0, procp);
   2499      1.1   cgd 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
   2500      1.1   cgd again:
   2501      1.1   cgd 	iv.iov_base = rbuf;
   2502      1.1   cgd 	iv.iov_len = fullsiz;
   2503      1.1   cgd 	io.uio_iov = &iv;
   2504      1.1   cgd 	io.uio_iovcnt = 1;
   2505  1.1.1.2  fvdl 	io.uio_offset = (off_t)off;
   2506      1.1   cgd 	io.uio_resid = fullsiz;
   2507      1.1   cgd 	io.uio_segflg = UIO_SYSSPACE;
   2508      1.1   cgd 	io.uio_rw = UIO_READ;
   2509      1.1   cgd 	io.uio_procp = (struct proc *)0;
   2510  1.1.1.3  fvdl 	eofflag = 0;
   2511  1.1.1.3  fvdl 	if (cookies) {
   2512  1.1.1.3  fvdl 		free((caddr_t)cookies, M_TEMP);
   2513  1.1.1.3  fvdl 		cookies = NULL;
   2514  1.1.1.3  fvdl 	}
   2515  1.1.1.3  fvdl 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
   2516  1.1.1.2  fvdl 	off = (off_t)io.uio_offset;
   2517  1.1.1.3  fvdl 	if (!cookies && !error)
   2518  1.1.1.3  fvdl 		error = NFSERR_PERM;
   2519  1.1.1.3  fvdl 	if (v3) {
   2520  1.1.1.3  fvdl 		getret = VOP_GETATTR(vp, &at, cred, procp);
   2521  1.1.1.3  fvdl 		if (!error)
   2522  1.1.1.3  fvdl 			error = getret;
   2523  1.1.1.3  fvdl 	}
   2524      1.1   cgd 	if (error) {
   2525      1.1   cgd 		vrele(vp);
   2526      1.1   cgd 		free((caddr_t)rbuf, M_TEMP);
   2527  1.1.1.3  fvdl 		if (cookies)
   2528  1.1.1.3  fvdl 			free((caddr_t)cookies, M_TEMP);
   2529  1.1.1.3  fvdl 		nfsm_reply(NFSX_POSTOPATTR(v3));
   2530  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2531  1.1.1.3  fvdl 		return (0);
   2532      1.1   cgd 	}
   2533      1.1   cgd 	if (io.uio_resid) {
   2534      1.1   cgd 		siz -= io.uio_resid;
   2535      1.1   cgd 
   2536      1.1   cgd 		/*
   2537      1.1   cgd 		 * If nothing read, return eof
   2538      1.1   cgd 		 * rpc reply
   2539      1.1   cgd 		 */
   2540      1.1   cgd 		if (siz == 0) {
   2541      1.1   cgd 			vrele(vp);
   2542  1.1.1.3  fvdl 			nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
   2543  1.1.1.3  fvdl 				2 * NFSX_UNSIGNED);
   2544  1.1.1.3  fvdl 			if (v3) {
   2545  1.1.1.3  fvdl 				nfsm_srvpostop_attr(getret, &at);
   2546  1.1.1.3  fvdl 				nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
   2547  1.1.1.3  fvdl 				txdr_hyper(&at.va_filerev, tl);
   2548  1.1.1.3  fvdl 				tl += 2;
   2549  1.1.1.3  fvdl 			} else
   2550  1.1.1.3  fvdl 				nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
   2551      1.1   cgd 			*tl++ = nfs_false;
   2552      1.1   cgd 			*tl = nfs_true;
   2553      1.1   cgd 			FREE((caddr_t)rbuf, M_TEMP);
   2554  1.1.1.3  fvdl 			FREE((caddr_t)cookies, M_TEMP);
   2555      1.1   cgd 			return (0);
   2556      1.1   cgd 		}
   2557      1.1   cgd 	}
   2558      1.1   cgd 
   2559      1.1   cgd 	/*
   2560      1.1   cgd 	 * Check for degenerate cases of nothing useful read.
   2561      1.1   cgd 	 * If so go try again
   2562      1.1   cgd 	 */
   2563  1.1.1.3  fvdl 	cpos = rbuf;
   2564      1.1   cgd 	cend = rbuf + siz;
   2565  1.1.1.2  fvdl 	dp = (struct dirent *)cpos;
   2566  1.1.1.3  fvdl 	cookiep = cookies;
   2567  1.1.1.3  fvdl 	while (dp->d_fileno == 0 && cpos < cend && ncookies > 0) {
   2568      1.1   cgd 		cpos += dp->d_reclen;
   2569  1.1.1.2  fvdl 		dp = (struct dirent *)cpos;
   2570  1.1.1.3  fvdl 		cookiep++;
   2571  1.1.1.3  fvdl 		ncookies--;
   2572      1.1   cgd 	}
   2573  1.1.1.3  fvdl 	if (cpos >= cend || ncookies == 0) {
   2574      1.1   cgd 		toff = off;
   2575      1.1   cgd 		siz = fullsiz;
   2576      1.1   cgd 		goto again;
   2577      1.1   cgd 	}
   2578      1.1   cgd 
   2579  1.1.1.3  fvdl 	len = 3 * NFSX_UNSIGNED;	/* paranoia, probably can be 0 */
   2580  1.1.1.3  fvdl 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
   2581  1.1.1.3  fvdl 	if (v3) {
   2582  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2583  1.1.1.3  fvdl 		nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
   2584  1.1.1.3  fvdl 		txdr_hyper(&at.va_filerev, tl);
   2585  1.1.1.3  fvdl 	}
   2586  1.1.1.2  fvdl 	mp = mp2 = mb;
   2587  1.1.1.2  fvdl 	bp = bpos;
   2588  1.1.1.2  fvdl 	be = bp + M_TRAILINGSPACE(mp);
   2589      1.1   cgd 
   2590      1.1   cgd 	/* Loop through the records and build reply */
   2591  1.1.1.3  fvdl 	while (cpos < cend && ncookies > 0) {
   2592  1.1.1.2  fvdl 		if (dp->d_fileno != 0) {
   2593  1.1.1.2  fvdl 			nlen = dp->d_namlen;
   2594  1.1.1.2  fvdl 			rem = nfsm_rndup(nlen)-nlen;
   2595  1.1.1.3  fvdl 			len += (4 * NFSX_UNSIGNED + nlen + rem);
   2596  1.1.1.3  fvdl 			if (v3)
   2597  1.1.1.3  fvdl 				len += 2 * NFSX_UNSIGNED;
   2598  1.1.1.2  fvdl 			if (len > cnt) {
   2599  1.1.1.2  fvdl 				eofflag = 0;
   2600  1.1.1.2  fvdl 				break;
   2601  1.1.1.2  fvdl 			}
   2602  1.1.1.2  fvdl 			/*
   2603  1.1.1.2  fvdl 			 * Build the directory record xdr from
   2604  1.1.1.2  fvdl 			 * the dirent entry.
   2605  1.1.1.2  fvdl 			 */
   2606  1.1.1.2  fvdl 			nfsm_clget;
   2607  1.1.1.2  fvdl 			*tl = nfs_true;
   2608  1.1.1.2  fvdl 			bp += NFSX_UNSIGNED;
   2609  1.1.1.3  fvdl 			if (v3) {
   2610  1.1.1.3  fvdl 				nfsm_clget;
   2611  1.1.1.3  fvdl 				*tl = 0;
   2612  1.1.1.3  fvdl 				bp += NFSX_UNSIGNED;
   2613  1.1.1.3  fvdl 			}
   2614  1.1.1.2  fvdl 			nfsm_clget;
   2615  1.1.1.2  fvdl 			*tl = txdr_unsigned(dp->d_fileno);
   2616  1.1.1.2  fvdl 			bp += NFSX_UNSIGNED;
   2617  1.1.1.2  fvdl 			nfsm_clget;
   2618  1.1.1.2  fvdl 			*tl = txdr_unsigned(nlen);
   2619  1.1.1.2  fvdl 			bp += NFSX_UNSIGNED;
   2620  1.1.1.2  fvdl 
   2621  1.1.1.2  fvdl 			/* And loop around copying the name */
   2622  1.1.1.2  fvdl 			xfer = nlen;
   2623  1.1.1.2  fvdl 			cp = dp->d_name;
   2624  1.1.1.2  fvdl 			while (xfer > 0) {
   2625  1.1.1.2  fvdl 				nfsm_clget;
   2626  1.1.1.2  fvdl 				if ((bp+xfer) > be)
   2627  1.1.1.2  fvdl 					tsiz = be-bp;
   2628  1.1.1.2  fvdl 				else
   2629  1.1.1.2  fvdl 					tsiz = xfer;
   2630  1.1.1.2  fvdl 				bcopy(cp, bp, tsiz);
   2631  1.1.1.2  fvdl 				bp += tsiz;
   2632  1.1.1.2  fvdl 				xfer -= tsiz;
   2633  1.1.1.2  fvdl 				if (xfer > 0)
   2634  1.1.1.2  fvdl 					cp += tsiz;
   2635  1.1.1.2  fvdl 			}
   2636  1.1.1.2  fvdl 			/* And null pad to a long boundary */
   2637  1.1.1.2  fvdl 			for (i = 0; i < rem; i++)
   2638  1.1.1.2  fvdl 				*bp++ = '\0';
   2639  1.1.1.2  fvdl 			nfsm_clget;
   2640  1.1.1.2  fvdl 
   2641  1.1.1.2  fvdl 			/* Finish off the record */
   2642  1.1.1.3  fvdl 			if (v3) {
   2643  1.1.1.3  fvdl 				*tl = 0;
   2644  1.1.1.3  fvdl 				bp += NFSX_UNSIGNED;
   2645  1.1.1.3  fvdl 				nfsm_clget;
   2646  1.1.1.3  fvdl 			}
   2647  1.1.1.3  fvdl 			*tl = txdr_unsigned(*cookiep);
   2648  1.1.1.2  fvdl 			bp += NFSX_UNSIGNED;
   2649  1.1.1.3  fvdl 		}
   2650  1.1.1.2  fvdl 		cpos += dp->d_reclen;
   2651  1.1.1.2  fvdl 		dp = (struct dirent *)cpos;
   2652  1.1.1.3  fvdl 		cookiep++;
   2653  1.1.1.3  fvdl 		ncookies--;
   2654  1.1.1.2  fvdl 	}
   2655  1.1.1.2  fvdl 	vrele(vp);
   2656  1.1.1.2  fvdl 	nfsm_clget;
   2657  1.1.1.2  fvdl 	*tl = nfs_false;
   2658  1.1.1.2  fvdl 	bp += NFSX_UNSIGNED;
   2659  1.1.1.2  fvdl 	nfsm_clget;
   2660  1.1.1.2  fvdl 	if (eofflag)
   2661  1.1.1.2  fvdl 		*tl = nfs_true;
   2662  1.1.1.2  fvdl 	else
   2663  1.1.1.2  fvdl 		*tl = nfs_false;
   2664  1.1.1.2  fvdl 	bp += NFSX_UNSIGNED;
   2665  1.1.1.2  fvdl 	if (mp != mb) {
   2666  1.1.1.2  fvdl 		if (bp < be)
   2667  1.1.1.2  fvdl 			mp->m_len = bp - mtod(mp, caddr_t);
   2668  1.1.1.2  fvdl 	} else
   2669  1.1.1.2  fvdl 		mp->m_len += bp - bpos;
   2670  1.1.1.3  fvdl 	FREE((caddr_t)rbuf, M_TEMP);
   2671  1.1.1.3  fvdl 	FREE((caddr_t)cookies, M_TEMP);
   2672  1.1.1.2  fvdl 	nfsm_srvdone;
   2673  1.1.1.2  fvdl }
   2674  1.1.1.2  fvdl 
   2675  1.1.1.3  fvdl int
   2676  1.1.1.3  fvdl nfsrv_readdirplus(nfsd, slp, procp, mrq)
   2677  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   2678  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   2679  1.1.1.3  fvdl 	struct proc *procp;
   2680  1.1.1.3  fvdl 	struct mbuf **mrq;
   2681  1.1.1.2  fvdl {
   2682  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   2683  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   2684  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   2685  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   2686  1.1.1.2  fvdl 	register char *bp, *be;
   2687  1.1.1.2  fvdl 	register struct mbuf *mp;
   2688  1.1.1.2  fvdl 	register struct dirent *dp;
   2689  1.1.1.2  fvdl 	register caddr_t cp;
   2690  1.1.1.2  fvdl 	register u_long *tl;
   2691  1.1.1.2  fvdl 	register long t1;
   2692  1.1.1.2  fvdl 	caddr_t bpos;
   2693  1.1.1.2  fvdl 	struct mbuf *mb, *mb2, *mreq, *mp2;
   2694  1.1.1.2  fvdl 	char *cpos, *cend, *cp2, *rbuf;
   2695  1.1.1.2  fvdl 	struct vnode *vp, *nvp;
   2696  1.1.1.2  fvdl 	struct flrep fl;
   2697  1.1.1.3  fvdl 	nfsfh_t nfh;
   2698  1.1.1.3  fvdl 	fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
   2699  1.1.1.2  fvdl 	struct uio io;
   2700  1.1.1.2  fvdl 	struct iovec iv;
   2701  1.1.1.3  fvdl 	struct vattr va, at, *vap = &va;
   2702  1.1.1.3  fvdl 	struct nfs_fattr *fp;
   2703  1.1.1.3  fvdl 	int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
   2704  1.1.1.3  fvdl 	int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
   2705  1.1.1.3  fvdl 	u_quad_t frev, off, toff, verf;
   2706  1.1.1.3  fvdl 	u_long *cookies = NULL, *cookiep;
   2707  1.1.1.2  fvdl 
   2708  1.1.1.2  fvdl 	fhp = &nfh.fh_generic;
   2709  1.1.1.2  fvdl 	nfsm_srvmtofh(fhp);
   2710  1.1.1.3  fvdl 	nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED);
   2711  1.1.1.3  fvdl 	fxdr_hyper(tl, &toff);
   2712  1.1.1.3  fvdl 	tl += 2;
   2713  1.1.1.3  fvdl 	fxdr_hyper(tl, &verf);
   2714  1.1.1.3  fvdl 	tl += 2;
   2715  1.1.1.3  fvdl 	siz = fxdr_unsigned(int, *tl++);
   2716  1.1.1.3  fvdl 	cnt = fxdr_unsigned(int, *tl);
   2717  1.1.1.3  fvdl 	off = toff;
   2718  1.1.1.3  fvdl 	siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
   2719  1.1.1.3  fvdl 	xfer = NFS_SRVMAXDATA(nfsd);
   2720  1.1.1.3  fvdl 	if (siz > xfer)
   2721  1.1.1.3  fvdl 		siz = xfer;
   2722  1.1.1.2  fvdl 	fullsiz = siz;
   2723  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
   2724  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
   2725  1.1.1.3  fvdl 		nfsm_reply(NFSX_UNSIGNED);
   2726  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2727  1.1.1.3  fvdl 		return (0);
   2728  1.1.1.3  fvdl 	}
   2729  1.1.1.3  fvdl 	error = getret = VOP_GETATTR(vp, &at, cred, procp);
   2730  1.1.1.3  fvdl 	if (!error && toff && verf != at.va_filerev)
   2731  1.1.1.3  fvdl 		error = NFSERR_BAD_COOKIE;
   2732  1.1.1.3  fvdl 	if (!error) {
   2733  1.1.1.3  fvdl 		nqsrv_getl(vp, ND_READ);
   2734  1.1.1.3  fvdl 		error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
   2735  1.1.1.3  fvdl 	}
   2736  1.1.1.3  fvdl 	if (error) {
   2737  1.1.1.2  fvdl 		vput(vp);
   2738  1.1.1.3  fvdl 		nfsm_reply(NFSX_V3POSTOPATTR);
   2739  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2740  1.1.1.3  fvdl 		return (0);
   2741  1.1.1.2  fvdl 	}
   2742  1.1.1.3  fvdl 	VOP_UNLOCK(vp, 0, procp);
   2743  1.1.1.2  fvdl 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
   2744  1.1.1.2  fvdl again:
   2745  1.1.1.2  fvdl 	iv.iov_base = rbuf;
   2746  1.1.1.2  fvdl 	iv.iov_len = fullsiz;
   2747  1.1.1.2  fvdl 	io.uio_iov = &iv;
   2748  1.1.1.2  fvdl 	io.uio_iovcnt = 1;
   2749  1.1.1.2  fvdl 	io.uio_offset = (off_t)off;
   2750  1.1.1.2  fvdl 	io.uio_resid = fullsiz;
   2751  1.1.1.2  fvdl 	io.uio_segflg = UIO_SYSSPACE;
   2752  1.1.1.2  fvdl 	io.uio_rw = UIO_READ;
   2753  1.1.1.2  fvdl 	io.uio_procp = (struct proc *)0;
   2754  1.1.1.3  fvdl 	eofflag = 0;
   2755  1.1.1.3  fvdl 	if (cookies) {
   2756  1.1.1.3  fvdl 		free((caddr_t)cookies, M_TEMP);
   2757  1.1.1.3  fvdl 		cookies = NULL;
   2758  1.1.1.3  fvdl 	}
   2759  1.1.1.3  fvdl 	error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
   2760  1.1.1.3  fvdl 	off = (u_quad_t)io.uio_offset;
   2761  1.1.1.3  fvdl 	getret = VOP_GETATTR(vp, &at, cred, procp);
   2762  1.1.1.3  fvdl 	if (!cookies && !error)
   2763  1.1.1.3  fvdl 		error = NFSERR_PERM;
   2764  1.1.1.3  fvdl 	if (!error)
   2765  1.1.1.3  fvdl 		error = getret;
   2766  1.1.1.2  fvdl 	if (error) {
   2767  1.1.1.2  fvdl 		vrele(vp);
   2768  1.1.1.3  fvdl 		if (cookies)
   2769  1.1.1.3  fvdl 			free((caddr_t)cookies, M_TEMP);
   2770  1.1.1.2  fvdl 		free((caddr_t)rbuf, M_TEMP);
   2771  1.1.1.3  fvdl 		nfsm_reply(NFSX_V3POSTOPATTR);
   2772  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   2773  1.1.1.3  fvdl 		return (0);
   2774  1.1.1.2  fvdl 	}
   2775  1.1.1.2  fvdl 	if (io.uio_resid) {
   2776  1.1.1.2  fvdl 		siz -= io.uio_resid;
   2777  1.1.1.2  fvdl 
   2778  1.1.1.2  fvdl 		/*
   2779  1.1.1.2  fvdl 		 * If nothing read, return eof
   2780  1.1.1.2  fvdl 		 * rpc reply
   2781  1.1.1.2  fvdl 		 */
   2782  1.1.1.2  fvdl 		if (siz == 0) {
   2783  1.1.1.2  fvdl 			vrele(vp);
   2784  1.1.1.3  fvdl 			nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
   2785  1.1.1.3  fvdl 				2 * NFSX_UNSIGNED);
   2786  1.1.1.3  fvdl 			nfsm_srvpostop_attr(getret, &at);
   2787  1.1.1.3  fvdl 			nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
   2788  1.1.1.3  fvdl 			txdr_hyper(&at.va_filerev, tl);
   2789  1.1.1.3  fvdl 			tl += 2;
   2790  1.1.1.2  fvdl 			*tl++ = nfs_false;
   2791  1.1.1.2  fvdl 			*tl = nfs_true;
   2792  1.1.1.3  fvdl 			FREE((caddr_t)cookies, M_TEMP);
   2793  1.1.1.2  fvdl 			FREE((caddr_t)rbuf, M_TEMP);
   2794  1.1.1.2  fvdl 			return (0);
   2795  1.1.1.2  fvdl 		}
   2796  1.1.1.2  fvdl 	}
   2797  1.1.1.2  fvdl 
   2798  1.1.1.2  fvdl 	/*
   2799  1.1.1.2  fvdl 	 * Check for degenerate cases of nothing useful read.
   2800  1.1.1.2  fvdl 	 * If so go try again
   2801  1.1.1.2  fvdl 	 */
   2802  1.1.1.3  fvdl 	cpos = rbuf;
   2803  1.1.1.2  fvdl 	cend = rbuf + siz;
   2804  1.1.1.2  fvdl 	dp = (struct dirent *)cpos;
   2805  1.1.1.3  fvdl 	cookiep = cookies;
   2806  1.1.1.3  fvdl 	while (dp->d_fileno == 0 && cpos < cend && ncookies > 0) {
   2807  1.1.1.2  fvdl 		cpos += dp->d_reclen;
   2808  1.1.1.2  fvdl 		dp = (struct dirent *)cpos;
   2809  1.1.1.3  fvdl 		cookiep++;
   2810  1.1.1.3  fvdl 		ncookies--;
   2811  1.1.1.2  fvdl 	}
   2812  1.1.1.3  fvdl 	if (cpos >= cend || ncookies == 0) {
   2813  1.1.1.2  fvdl 		toff = off;
   2814  1.1.1.2  fvdl 		siz = fullsiz;
   2815  1.1.1.2  fvdl 		goto again;
   2816  1.1.1.2  fvdl 	}
   2817  1.1.1.2  fvdl 
   2818  1.1.1.3  fvdl 	dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
   2819  1.1.1.3  fvdl 	nfsm_reply(cnt);
   2820  1.1.1.3  fvdl 	nfsm_srvpostop_attr(getret, &at);
   2821  1.1.1.3  fvdl 	nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
   2822  1.1.1.3  fvdl 	txdr_hyper(&at.va_filerev, tl);
   2823  1.1.1.2  fvdl 	mp = mp2 = mb;
   2824  1.1.1.2  fvdl 	bp = bpos;
   2825  1.1.1.2  fvdl 	be = bp + M_TRAILINGSPACE(mp);
   2826  1.1.1.2  fvdl 
   2827  1.1.1.2  fvdl 	/* Loop through the records and build reply */
   2828  1.1.1.3  fvdl 	while (cpos < cend && ncookies > 0) {
   2829  1.1.1.2  fvdl 		if (dp->d_fileno != 0) {
   2830      1.1   cgd 			nlen = dp->d_namlen;
   2831      1.1   cgd 			rem = nfsm_rndup(nlen)-nlen;
   2832      1.1   cgd 
   2833      1.1   cgd 			/*
   2834  1.1.1.2  fvdl 			 * For readdir_and_lookup get the vnode using
   2835  1.1.1.2  fvdl 			 * the file number.
   2836      1.1   cgd 			 */
   2837  1.1.1.2  fvdl 			if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
   2838  1.1.1.2  fvdl 				goto invalid;
   2839  1.1.1.3  fvdl 			bzero((caddr_t)nfhp, NFSX_V3FH);
   2840  1.1.1.3  fvdl 			nfhp->fh_fsid =
   2841  1.1.1.2  fvdl 				nvp->v_mount->mnt_stat.f_fsid;
   2842  1.1.1.3  fvdl 			if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
   2843  1.1.1.2  fvdl 				vput(nvp);
   2844  1.1.1.2  fvdl 				goto invalid;
   2845  1.1.1.2  fvdl 			}
   2846  1.1.1.3  fvdl 			if (VOP_GETATTR(nvp, vap, cred, procp)) {
   2847  1.1.1.2  fvdl 				vput(nvp);
   2848  1.1.1.2  fvdl 				goto invalid;
   2849  1.1.1.2  fvdl 			}
   2850  1.1.1.2  fvdl 			vput(nvp);
   2851  1.1.1.3  fvdl 
   2852  1.1.1.3  fvdl 			/*
   2853  1.1.1.3  fvdl 			 * If either the dircount or maxcount will be
   2854  1.1.1.3  fvdl 			 * exceeded, get out now. Both of these lengths
   2855  1.1.1.3  fvdl 			 * are calculated conservatively, including all
   2856  1.1.1.3  fvdl 			 * XDR overheads.
   2857  1.1.1.3  fvdl 			 */
   2858  1.1.1.3  fvdl 			len += (7 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
   2859  1.1.1.3  fvdl 				NFSX_V3POSTOPATTR);
   2860  1.1.1.3  fvdl 			dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
   2861  1.1.1.3  fvdl 			if (len > cnt || dirlen > fullsiz) {
   2862      1.1   cgd 				eofflag = 0;
   2863      1.1   cgd 				break;
   2864      1.1   cgd 			}
   2865  1.1.1.3  fvdl 
   2866  1.1.1.2  fvdl 			/*
   2867  1.1.1.2  fvdl 			 * Build the directory record xdr from
   2868  1.1.1.2  fvdl 			 * the dirent entry.
   2869  1.1.1.2  fvdl 			 */
   2870  1.1.1.3  fvdl 			fp = (struct nfs_fattr *)&fl.fl_fattr;
   2871  1.1.1.3  fvdl 			nfsm_srvfillattr(vap, fp);
   2872  1.1.1.3  fvdl 			fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
   2873  1.1.1.3  fvdl 			fl.fl_fhok = nfs_true;
   2874  1.1.1.3  fvdl 			fl.fl_postopok = nfs_true;
   2875  1.1.1.3  fvdl 			fl.fl_off.nfsuquad[0] = 0;
   2876  1.1.1.3  fvdl 			fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
   2877  1.1.1.3  fvdl 
   2878      1.1   cgd 			nfsm_clget;
   2879      1.1   cgd 			*tl = nfs_true;
   2880      1.1   cgd 			bp += NFSX_UNSIGNED;
   2881  1.1.1.3  fvdl 			nfsm_clget;
   2882  1.1.1.3  fvdl 			*tl = 0;
   2883  1.1.1.3  fvdl 			bp += NFSX_UNSIGNED;
   2884      1.1   cgd 			nfsm_clget;
   2885  1.1.1.2  fvdl 			*tl = txdr_unsigned(dp->d_fileno);
   2886      1.1   cgd 			bp += NFSX_UNSIGNED;
   2887      1.1   cgd 			nfsm_clget;
   2888      1.1   cgd 			*tl = txdr_unsigned(nlen);
   2889      1.1   cgd 			bp += NFSX_UNSIGNED;
   2890      1.1   cgd 
   2891  1.1.1.2  fvdl 			/* And loop around copying the name */
   2892      1.1   cgd 			xfer = nlen;
   2893      1.1   cgd 			cp = dp->d_name;
   2894      1.1   cgd 			while (xfer > 0) {
   2895      1.1   cgd 				nfsm_clget;
   2896  1.1.1.3  fvdl 				if ((bp + xfer) > be)
   2897  1.1.1.3  fvdl 					tsiz = be - bp;
   2898      1.1   cgd 				else
   2899      1.1   cgd 					tsiz = xfer;
   2900      1.1   cgd 				bcopy(cp, bp, tsiz);
   2901      1.1   cgd 				bp += tsiz;
   2902      1.1   cgd 				xfer -= tsiz;
   2903      1.1   cgd 				if (xfer > 0)
   2904      1.1   cgd 					cp += tsiz;
   2905      1.1   cgd 			}
   2906      1.1   cgd 			/* And null pad to a long boundary */
   2907      1.1   cgd 			for (i = 0; i < rem; i++)
   2908      1.1   cgd 				*bp++ = '\0';
   2909      1.1   cgd 
   2910  1.1.1.3  fvdl 			/*
   2911  1.1.1.3  fvdl 			 * Now copy the flrep structure out.
   2912  1.1.1.3  fvdl 			 */
   2913  1.1.1.3  fvdl 			xfer = sizeof (struct flrep);
   2914  1.1.1.3  fvdl 			cp = (caddr_t)&fl;
   2915  1.1.1.3  fvdl 			while (xfer > 0) {
   2916  1.1.1.3  fvdl 				nfsm_clget;
   2917  1.1.1.3  fvdl 				if ((bp + xfer) > be)
   2918  1.1.1.3  fvdl 					tsiz = be - bp;
   2919  1.1.1.3  fvdl 				else
   2920  1.1.1.3  fvdl 					tsiz = xfer;
   2921  1.1.1.3  fvdl 				bcopy(cp, bp, tsiz);
   2922  1.1.1.3  fvdl 				bp += tsiz;
   2923  1.1.1.3  fvdl 				xfer -= tsiz;
   2924  1.1.1.3  fvdl 				if (xfer > 0)
   2925  1.1.1.3  fvdl 					cp += tsiz;
   2926  1.1.1.3  fvdl 			}
   2927  1.1.1.3  fvdl 		}
   2928  1.1.1.2  fvdl invalid:
   2929      1.1   cgd 		cpos += dp->d_reclen;
   2930  1.1.1.2  fvdl 		dp = (struct dirent *)cpos;
   2931  1.1.1.3  fvdl 		cookiep++;
   2932  1.1.1.3  fvdl 		ncookies--;
   2933      1.1   cgd 	}
   2934  1.1.1.2  fvdl 	vrele(vp);
   2935      1.1   cgd 	nfsm_clget;
   2936      1.1   cgd 	*tl = nfs_false;
   2937      1.1   cgd 	bp += NFSX_UNSIGNED;
   2938      1.1   cgd 	nfsm_clget;
   2939      1.1   cgd 	if (eofflag)
   2940      1.1   cgd 		*tl = nfs_true;
   2941      1.1   cgd 	else
   2942      1.1   cgd 		*tl = nfs_false;
   2943      1.1   cgd 	bp += NFSX_UNSIGNED;
   2944  1.1.1.2  fvdl 	if (mp != mb) {
   2945  1.1.1.2  fvdl 		if (bp < be)
   2946  1.1.1.2  fvdl 			mp->m_len = bp - mtod(mp, caddr_t);
   2947  1.1.1.2  fvdl 	} else
   2948  1.1.1.2  fvdl 		mp->m_len += bp - bpos;
   2949  1.1.1.3  fvdl 	FREE((caddr_t)cookies, M_TEMP);
   2950  1.1.1.3  fvdl 	FREE((caddr_t)rbuf, M_TEMP);
   2951  1.1.1.3  fvdl 	nfsm_srvdone;
   2952  1.1.1.3  fvdl }
   2953  1.1.1.3  fvdl 
   2954  1.1.1.3  fvdl /*
   2955  1.1.1.3  fvdl  * nfs commit service
   2956  1.1.1.3  fvdl  */
   2957  1.1.1.3  fvdl int
   2958  1.1.1.3  fvdl nfsrv_commit(nfsd, slp, procp, mrq)
   2959  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   2960  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   2961  1.1.1.3  fvdl 	struct proc *procp;
   2962  1.1.1.3  fvdl 	struct mbuf **mrq;
   2963  1.1.1.3  fvdl {
   2964  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   2965  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   2966  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   2967  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   2968  1.1.1.3  fvdl 	struct vattr bfor, aft;
   2969  1.1.1.3  fvdl 	struct vnode *vp;
   2970  1.1.1.3  fvdl 	nfsfh_t nfh;
   2971  1.1.1.3  fvdl 	fhandle_t *fhp;
   2972  1.1.1.3  fvdl 	register u_long *tl;
   2973  1.1.1.3  fvdl 	register long t1;
   2974  1.1.1.3  fvdl 	caddr_t bpos;
   2975  1.1.1.3  fvdl 	int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
   2976  1.1.1.3  fvdl 	char *cp2;
   2977  1.1.1.3  fvdl 	struct mbuf *mb, *mb2, *mreq;
   2978  1.1.1.3  fvdl 	u_quad_t frev, off;
   2979  1.1.1.3  fvdl 
   2980  1.1.1.3  fvdl #ifndef nolint
   2981  1.1.1.3  fvdl 	cache = 0;
   2982  1.1.1.3  fvdl #endif
   2983  1.1.1.3  fvdl 	fhp = &nfh.fh_generic;
   2984  1.1.1.3  fvdl 	nfsm_srvmtofh(fhp);
   2985  1.1.1.3  fvdl 	nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
   2986  1.1.1.3  fvdl 
   2987  1.1.1.3  fvdl 	/*
   2988  1.1.1.3  fvdl 	 * XXX At this time VOP_FSYNC() does not accept offset and byte
   2989  1.1.1.3  fvdl 	 * count parameters, so these arguments are useless (someday maybe).
   2990  1.1.1.3  fvdl 	 */
   2991  1.1.1.3  fvdl 	fxdr_hyper(tl, &off);
   2992  1.1.1.3  fvdl 	tl += 2;
   2993  1.1.1.3  fvdl 	cnt = fxdr_unsigned(int, *tl);
   2994  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
   2995  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
   2996  1.1.1.3  fvdl 		nfsm_reply(2 * NFSX_UNSIGNED);
   2997  1.1.1.3  fvdl 		nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
   2998  1.1.1.3  fvdl 		return (0);
   2999  1.1.1.3  fvdl 	}
   3000  1.1.1.3  fvdl 	for_ret = VOP_GETATTR(vp, &bfor, cred, procp);
   3001  1.1.1.3  fvdl 	error = VOP_FSYNC(vp, cred, MNT_WAIT, procp);
   3002  1.1.1.3  fvdl 	aft_ret = VOP_GETATTR(vp, &aft, cred, procp);
   3003  1.1.1.3  fvdl 	vput(vp);
   3004  1.1.1.3  fvdl 	nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
   3005  1.1.1.3  fvdl 	nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
   3006  1.1.1.3  fvdl 	if (!error) {
   3007  1.1.1.3  fvdl 		nfsm_build(tl, u_long *, NFSX_V3WRITEVERF);
   3008  1.1.1.3  fvdl 		*tl++ = txdr_unsigned(boottime.tv_sec);
   3009  1.1.1.3  fvdl 		*tl = txdr_unsigned(boottime.tv_usec);
   3010  1.1.1.3  fvdl 	} else
   3011  1.1.1.3  fvdl 		return (0);
   3012      1.1   cgd 	nfsm_srvdone;
   3013      1.1   cgd }
   3014      1.1   cgd 
   3015      1.1   cgd /*
   3016      1.1   cgd  * nfs statfs service
   3017      1.1   cgd  */
   3018  1.1.1.3  fvdl int
   3019  1.1.1.3  fvdl nfsrv_statfs(nfsd, slp, procp, mrq)
   3020  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   3021  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   3022  1.1.1.3  fvdl 	struct proc *procp;
   3023  1.1.1.3  fvdl 	struct mbuf **mrq;
   3024      1.1   cgd {
   3025  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   3026  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   3027  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   3028  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   3029      1.1   cgd 	register struct statfs *sf;
   3030  1.1.1.3  fvdl 	register struct nfs_statfs *sfp;
   3031      1.1   cgd 	register u_long *tl;
   3032      1.1   cgd 	register long t1;
   3033      1.1   cgd 	caddr_t bpos;
   3034  1.1.1.3  fvdl 	int error = 0, rdonly, cache, getret = 1;
   3035  1.1.1.3  fvdl 	int v3 = (nfsd->nd_flag & ND_NFSV3);
   3036      1.1   cgd 	char *cp2;
   3037      1.1   cgd 	struct mbuf *mb, *mb2, *mreq;
   3038      1.1   cgd 	struct vnode *vp;
   3039  1.1.1.3  fvdl 	struct vattr at;
   3040  1.1.1.3  fvdl 	nfsfh_t nfh;
   3041      1.1   cgd 	fhandle_t *fhp;
   3042      1.1   cgd 	struct statfs statfs;
   3043  1.1.1.3  fvdl 	u_quad_t frev, tval;
   3044      1.1   cgd 
   3045  1.1.1.3  fvdl #ifndef nolint
   3046  1.1.1.3  fvdl 	cache = 0;
   3047  1.1.1.3  fvdl #endif
   3048      1.1   cgd 	fhp = &nfh.fh_generic;
   3049      1.1   cgd 	nfsm_srvmtofh(fhp);
   3050  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
   3051  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
   3052  1.1.1.3  fvdl 		nfsm_reply(NFSX_UNSIGNED);
   3053  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   3054  1.1.1.3  fvdl 		return (0);
   3055  1.1.1.3  fvdl 	}
   3056      1.1   cgd 	sf = &statfs;
   3057  1.1.1.3  fvdl 	error = VFS_STATFS(vp->v_mount, sf, procp);
   3058  1.1.1.3  fvdl 	getret = VOP_GETATTR(vp, &at, cred, procp);
   3059      1.1   cgd 	vput(vp);
   3060  1.1.1.3  fvdl 	nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
   3061  1.1.1.3  fvdl 	if (v3)
   3062  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   3063  1.1.1.3  fvdl 	if (error)
   3064  1.1.1.3  fvdl 		return (0);
   3065  1.1.1.3  fvdl 	nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
   3066  1.1.1.3  fvdl 	if (v3) {
   3067  1.1.1.3  fvdl 		tval = (u_quad_t)sf->f_blocks;
   3068  1.1.1.3  fvdl 		tval *= (u_quad_t)sf->f_bsize;
   3069  1.1.1.3  fvdl 		txdr_hyper(&tval, &sfp->sf_tbytes);
   3070  1.1.1.3  fvdl 		tval = (u_quad_t)sf->f_bfree;
   3071  1.1.1.3  fvdl 		tval *= (u_quad_t)sf->f_bsize;
   3072  1.1.1.3  fvdl 		txdr_hyper(&tval, &sfp->sf_fbytes);
   3073  1.1.1.3  fvdl 		tval = (u_quad_t)sf->f_bavail;
   3074  1.1.1.3  fvdl 		tval *= (u_quad_t)sf->f_bsize;
   3075  1.1.1.3  fvdl 		txdr_hyper(&tval, &sfp->sf_abytes);
   3076  1.1.1.3  fvdl 		sfp->sf_tfiles.nfsuquad[0] = 0;
   3077  1.1.1.3  fvdl 		sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
   3078  1.1.1.3  fvdl 		sfp->sf_ffiles.nfsuquad[0] = 0;
   3079  1.1.1.3  fvdl 		sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
   3080  1.1.1.3  fvdl 		sfp->sf_afiles.nfsuquad[0] = 0;
   3081  1.1.1.3  fvdl 		sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
   3082  1.1.1.3  fvdl 		sfp->sf_invarsec = 0;
   3083  1.1.1.3  fvdl 	} else {
   3084  1.1.1.3  fvdl 		sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
   3085  1.1.1.3  fvdl 		sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
   3086  1.1.1.3  fvdl 		sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
   3087  1.1.1.3  fvdl 		sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
   3088  1.1.1.3  fvdl 		sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
   3089  1.1.1.3  fvdl 	}
   3090  1.1.1.3  fvdl 	nfsm_srvdone;
   3091  1.1.1.3  fvdl }
   3092  1.1.1.3  fvdl 
   3093  1.1.1.3  fvdl /*
   3094  1.1.1.3  fvdl  * nfs fsinfo service
   3095  1.1.1.3  fvdl  */
   3096  1.1.1.3  fvdl int
   3097  1.1.1.3  fvdl nfsrv_fsinfo(nfsd, slp, procp, mrq)
   3098  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   3099  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   3100  1.1.1.3  fvdl 	struct proc *procp;
   3101  1.1.1.3  fvdl 	struct mbuf **mrq;
   3102  1.1.1.3  fvdl {
   3103  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   3104  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   3105  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   3106  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   3107  1.1.1.3  fvdl 	register u_long *tl;
   3108  1.1.1.3  fvdl 	register struct nfsv3_fsinfo *sip;
   3109  1.1.1.3  fvdl 	register long t1;
   3110  1.1.1.3  fvdl 	caddr_t bpos;
   3111  1.1.1.3  fvdl 	int error = 0, rdonly, cache, getret = 1, pref;
   3112  1.1.1.3  fvdl 	char *cp2;
   3113  1.1.1.3  fvdl 	struct mbuf *mb, *mb2, *mreq;
   3114  1.1.1.3  fvdl 	struct vnode *vp;
   3115  1.1.1.3  fvdl 	struct vattr at;
   3116  1.1.1.3  fvdl 	nfsfh_t nfh;
   3117  1.1.1.3  fvdl 	fhandle_t *fhp;
   3118  1.1.1.3  fvdl 	u_quad_t frev;
   3119  1.1.1.3  fvdl 
   3120  1.1.1.3  fvdl #ifndef nolint
   3121  1.1.1.3  fvdl 	cache = 0;
   3122  1.1.1.3  fvdl #endif
   3123  1.1.1.3  fvdl 	fhp = &nfh.fh_generic;
   3124  1.1.1.3  fvdl 	nfsm_srvmtofh(fhp);
   3125  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
   3126  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
   3127  1.1.1.3  fvdl 		nfsm_reply(NFSX_UNSIGNED);
   3128  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   3129  1.1.1.3  fvdl 		return (0);
   3130  1.1.1.2  fvdl 	}
   3131  1.1.1.3  fvdl 	getret = VOP_GETATTR(vp, &at, cred, procp);
   3132  1.1.1.3  fvdl 	vput(vp);
   3133  1.1.1.3  fvdl 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
   3134  1.1.1.3  fvdl 	nfsm_srvpostop_attr(getret, &at);
   3135  1.1.1.3  fvdl 	nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
   3136  1.1.1.3  fvdl 
   3137  1.1.1.3  fvdl 	/*
   3138  1.1.1.3  fvdl 	 * XXX
   3139  1.1.1.3  fvdl 	 * There should be file system VFS OP(s) to get this information.
   3140  1.1.1.3  fvdl 	 * For now, assume ufs.
   3141  1.1.1.3  fvdl 	 */
   3142  1.1.1.3  fvdl 	if (slp->ns_so->so_type == SOCK_DGRAM)
   3143  1.1.1.3  fvdl 		pref = NFS_MAXDGRAMDATA;
   3144  1.1.1.3  fvdl 	else
   3145  1.1.1.3  fvdl 		pref = NFS_MAXDATA;
   3146  1.1.1.3  fvdl 	sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
   3147  1.1.1.3  fvdl 	sip->fs_rtpref = txdr_unsigned(pref);
   3148  1.1.1.3  fvdl 	sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
   3149  1.1.1.3  fvdl 	sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
   3150  1.1.1.3  fvdl 	sip->fs_wtpref = txdr_unsigned(pref);
   3151  1.1.1.3  fvdl 	sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
   3152  1.1.1.3  fvdl 	sip->fs_dtpref = txdr_unsigned(pref);
   3153  1.1.1.3  fvdl 	sip->fs_maxfilesize.nfsuquad[0] = 0xffffffff;
   3154  1.1.1.3  fvdl 	sip->fs_maxfilesize.nfsuquad[1] = 0xffffffff;
   3155  1.1.1.3  fvdl 	sip->fs_timedelta.nfsv3_sec = 0;
   3156  1.1.1.3  fvdl 	sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
   3157  1.1.1.3  fvdl 	sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
   3158  1.1.1.3  fvdl 		NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
   3159  1.1.1.3  fvdl 		NFSV3FSINFO_CANSETTIME);
   3160  1.1.1.3  fvdl 	nfsm_srvdone;
   3161  1.1.1.3  fvdl }
   3162  1.1.1.3  fvdl 
   3163  1.1.1.3  fvdl /*
   3164  1.1.1.3  fvdl  * nfs pathconf service
   3165  1.1.1.3  fvdl  */
   3166  1.1.1.3  fvdl int
   3167  1.1.1.3  fvdl nfsrv_pathconf(nfsd, slp, procp, mrq)
   3168  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   3169  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   3170  1.1.1.3  fvdl 	struct proc *procp;
   3171  1.1.1.3  fvdl 	struct mbuf **mrq;
   3172  1.1.1.3  fvdl {
   3173  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   3174  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   3175  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   3176  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   3177  1.1.1.3  fvdl 	register u_long *tl;
   3178  1.1.1.3  fvdl 	register struct nfsv3_pathconf *pc;
   3179  1.1.1.3  fvdl 	register long t1;
   3180  1.1.1.3  fvdl 	caddr_t bpos;
   3181  1.1.1.3  fvdl 	int error = 0, rdonly, cache, getret = 1, linkmax, namemax;
   3182  1.1.1.3  fvdl 	int chownres, notrunc;
   3183  1.1.1.3  fvdl 	char *cp2;
   3184  1.1.1.3  fvdl 	struct mbuf *mb, *mb2, *mreq;
   3185  1.1.1.3  fvdl 	struct vnode *vp;
   3186  1.1.1.3  fvdl 	struct vattr at;
   3187  1.1.1.3  fvdl 	nfsfh_t nfh;
   3188  1.1.1.3  fvdl 	fhandle_t *fhp;
   3189  1.1.1.3  fvdl 	u_quad_t frev;
   3190  1.1.1.3  fvdl 
   3191  1.1.1.3  fvdl #ifndef nolint
   3192  1.1.1.3  fvdl 	cache = 0;
   3193  1.1.1.3  fvdl #endif
   3194  1.1.1.3  fvdl 	fhp = &nfh.fh_generic;
   3195  1.1.1.3  fvdl 	nfsm_srvmtofh(fhp);
   3196  1.1.1.3  fvdl 	if (error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
   3197  1.1.1.3  fvdl 		 &rdonly, (nfsd->nd_flag & ND_KERBAUTH))) {
   3198  1.1.1.3  fvdl 		nfsm_reply(NFSX_UNSIGNED);
   3199  1.1.1.3  fvdl 		nfsm_srvpostop_attr(getret, &at);
   3200  1.1.1.3  fvdl 		return (0);
   3201  1.1.1.3  fvdl 	}
   3202  1.1.1.3  fvdl 	error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
   3203  1.1.1.3  fvdl 	if (!error)
   3204  1.1.1.3  fvdl 		error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
   3205  1.1.1.3  fvdl 	if (!error)
   3206  1.1.1.3  fvdl 		error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
   3207  1.1.1.3  fvdl 	if (!error)
   3208  1.1.1.3  fvdl 		error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
   3209  1.1.1.3  fvdl 	getret = VOP_GETATTR(vp, &at, cred, procp);
   3210  1.1.1.3  fvdl 	vput(vp);
   3211  1.1.1.3  fvdl 	nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
   3212  1.1.1.3  fvdl 	nfsm_srvpostop_attr(getret, &at);
   3213  1.1.1.3  fvdl 	if (error)
   3214  1.1.1.3  fvdl 		return (0);
   3215  1.1.1.3  fvdl 	nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
   3216  1.1.1.3  fvdl 
   3217  1.1.1.3  fvdl 	pc->pc_linkmax = txdr_unsigned(linkmax);
   3218  1.1.1.3  fvdl 	pc->pc_namemax = txdr_unsigned(namemax);
   3219  1.1.1.3  fvdl 	pc->pc_notrunc = txdr_unsigned(notrunc);
   3220  1.1.1.3  fvdl 	pc->pc_chownrestricted = txdr_unsigned(chownres);
   3221  1.1.1.3  fvdl 
   3222  1.1.1.3  fvdl 	/*
   3223  1.1.1.3  fvdl 	 * These should probably be supported by VOP_PATHCONF(), but
   3224  1.1.1.3  fvdl 	 * until msdosfs is exportable (why would you want to?), the
   3225  1.1.1.3  fvdl 	 * Unix defaults should be ok.
   3226  1.1.1.3  fvdl 	 */
   3227  1.1.1.3  fvdl 	pc->pc_caseinsensitive = nfs_false;
   3228  1.1.1.3  fvdl 	pc->pc_casepreserving = nfs_true;
   3229      1.1   cgd 	nfsm_srvdone;
   3230      1.1   cgd }
   3231      1.1   cgd 
   3232      1.1   cgd /*
   3233      1.1   cgd  * Null operation, used by clients to ping server
   3234      1.1   cgd  */
   3235      1.1   cgd /* ARGSUSED */
   3236  1.1.1.3  fvdl int
   3237  1.1.1.3  fvdl nfsrv_null(nfsd, slp, procp, mrq)
   3238  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   3239  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   3240  1.1.1.3  fvdl 	struct proc *procp;
   3241  1.1.1.3  fvdl 	struct mbuf **mrq;
   3242      1.1   cgd {
   3243  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   3244  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   3245  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   3246  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   3247      1.1   cgd 	caddr_t bpos;
   3248  1.1.1.3  fvdl 	int error = NFSERR_RETVOID, cache;
   3249      1.1   cgd 	struct mbuf *mb, *mreq;
   3250  1.1.1.2  fvdl 	u_quad_t frev;
   3251      1.1   cgd 
   3252  1.1.1.3  fvdl #ifndef nolint
   3253  1.1.1.3  fvdl 	cache = 0;
   3254  1.1.1.3  fvdl #endif
   3255      1.1   cgd 	nfsm_reply(0);
   3256  1.1.1.3  fvdl 	return (0);
   3257      1.1   cgd }
   3258      1.1   cgd 
   3259      1.1   cgd /*
   3260      1.1   cgd  * No operation, used for obsolete procedures
   3261      1.1   cgd  */
   3262      1.1   cgd /* ARGSUSED */
   3263  1.1.1.3  fvdl int
   3264  1.1.1.3  fvdl nfsrv_noop(nfsd, slp, procp, mrq)
   3265  1.1.1.3  fvdl 	struct nfsrv_descript *nfsd;
   3266  1.1.1.3  fvdl 	struct nfssvc_sock *slp;
   3267  1.1.1.3  fvdl 	struct proc *procp;
   3268  1.1.1.3  fvdl 	struct mbuf **mrq;
   3269      1.1   cgd {
   3270  1.1.1.3  fvdl 	struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
   3271  1.1.1.3  fvdl 	struct mbuf *nam = nfsd->nd_nam;
   3272  1.1.1.3  fvdl 	caddr_t dpos = nfsd->nd_dpos;
   3273  1.1.1.3  fvdl 	struct ucred *cred = &nfsd->nd_cr;
   3274      1.1   cgd 	caddr_t bpos;
   3275  1.1.1.2  fvdl 	int error, cache;
   3276      1.1   cgd 	struct mbuf *mb, *mreq;
   3277  1.1.1.2  fvdl 	u_quad_t frev;
   3278      1.1   cgd 
   3279  1.1.1.3  fvdl #ifndef nolint
   3280  1.1.1.3  fvdl 	cache = 0;
   3281  1.1.1.3  fvdl #endif
   3282  1.1.1.2  fvdl 	if (nfsd->nd_repstat)
   3283  1.1.1.2  fvdl 		error = nfsd->nd_repstat;
   3284  1.1.1.2  fvdl 	else
   3285  1.1.1.2  fvdl 		error = EPROCUNAVAIL;
   3286      1.1   cgd 	nfsm_reply(0);
   3287  1.1.1.3  fvdl 	return (0);
   3288      1.1   cgd }
   3289      1.1   cgd 
   3290      1.1   cgd /*
   3291      1.1   cgd  * Perform access checking for vnodes obtained from file handles that would
   3292      1.1   cgd  * refer to files already opened by a Unix client. You cannot just use
   3293      1.1   cgd  * vn_writechk() and VOP_ACCESS() for two reasons.
   3294  1.1.1.2  fvdl  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
   3295      1.1   cgd  * 2 - The owner is to be given access irrespective of mode bits so that
   3296      1.1   cgd  *     processes that chmod after opening a file don't break. I don't like
   3297      1.1   cgd  *     this because it opens a security hole, but since the nfs server opens
   3298      1.1   cgd  *     a security hole the size of a barn door anyhow, what the heck.
   3299      1.1   cgd  */
   3300  1.1.1.3  fvdl int
   3301  1.1.1.2  fvdl nfsrv_access(vp, flags, cred, rdonly, p)
   3302      1.1   cgd 	register struct vnode *vp;
   3303      1.1   cgd 	int flags;
   3304      1.1   cgd 	register struct ucred *cred;
   3305  1.1.1.2  fvdl 	int rdonly;
   3306      1.1   cgd 	struct proc *p;
   3307      1.1   cgd {
   3308      1.1   cgd 	struct vattr vattr;
   3309      1.1   cgd 	int error;
   3310      1.1   cgd 	if (flags & VWRITE) {
   3311  1.1.1.2  fvdl 		/* Just vn_writechk() changed to check rdonly */
   3312      1.1   cgd 		/*
   3313      1.1   cgd 		 * Disallow write attempts on read-only file systems;
   3314      1.1   cgd 		 * unless the file is a socket or a block or character
   3315      1.1   cgd 		 * device resident on the file system.
   3316      1.1   cgd 		 */
   3317  1.1.1.2  fvdl 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
   3318      1.1   cgd 			switch (vp->v_type) {
   3319      1.1   cgd 			case VREG: case VDIR: case VLNK:
   3320      1.1   cgd 				return (EROFS);
   3321      1.1   cgd 			}
   3322      1.1   cgd 		}
   3323      1.1   cgd 		/*
   3324      1.1   cgd 		 * If there's shared text associated with
   3325      1.1   cgd 		 * the inode, try to free it up once.  If
   3326      1.1   cgd 		 * we fail, we can't allow writing.
   3327      1.1   cgd 		 */
   3328      1.1   cgd 		if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
   3329      1.1   cgd 			return (ETXTBSY);
   3330      1.1   cgd 	}
   3331      1.1   cgd 	if (error = VOP_GETATTR(vp, &vattr, cred, p))
   3332      1.1   cgd 		return (error);
   3333      1.1   cgd 	if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
   3334      1.1   cgd 	    cred->cr_uid != vattr.va_uid)
   3335      1.1   cgd 		return (error);
   3336      1.1   cgd 	return (0);
   3337      1.1   cgd }
   3338