xref: /original-bsd/sys/nfs/nfs_serv.c (revision 50ed812d)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)nfs_serv.c	7.64 (Berkeley) 04/29/93
11  */
12 
13 /*
14  * nfs version 2 server calls to vnode ops
15  * - these routines generally have 3 phases
16  *   1 - break down and validate rpc request in mbuf list
17  *   2 - do the vnode ops for the request
18  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
19  *   3 - build the rpc reply in an mbuf list
20  *   nb:
21  *	- do not mix the phases, since the nfsm_?? macros can return failures
22  *	  on a bad rpc or similar and do not do any vrele() or vput()'s
23  *
24  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
25  *	error number iff error != 0 whereas
26  *	returning an error from the server function implies a fatal error
27  *	such as a badly constructed rpc request that should be dropped without
28  *	a reply.
29  */
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/proc.h>
34 #include <sys/file.h>
35 #include <sys/namei.h>
36 #include <sys/vnode.h>
37 #include <sys/mount.h>
38 #include <sys/mbuf.h>
39 #include <sys/dirent.h>
40 #include <sys/stat.h>
41 
42 #include <vm/vm.h>
43 
44 #include <nfs/nfsv2.h>
45 #include <nfs/rpcv2.h>
46 #include <nfs/nfs.h>
47 #include <nfs/xdr_subs.h>
48 #include <nfs/nfsm_subs.h>
49 #include <nfs/nqnfs.h>
50 
51 /* Defs */
52 #define	TRUE	1
53 #define	FALSE	0
54 
55 /* Global vars */
56 extern u_long nfs_procids[NFS_NPROCS];
57 extern u_long nfs_xdrneg1;
58 extern u_long nfs_false, nfs_true;
59 nfstype nfs_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
60 		      NFCHR, NFNON };
61 
62 /*
63  * nqnfs access service
64  */
65 nqnfsrv_access(nfsd, mrep, md, dpos, cred, nam, mrq)
66 	struct nfsd *nfsd;
67 	struct mbuf *mrep, *md;
68 	caddr_t dpos;
69 	struct ucred *cred;
70 	struct mbuf *nam, **mrq;
71 {
72 	struct vnode *vp;
73 	nfsv2fh_t nfh;
74 	fhandle_t *fhp;
75 	register u_long *tl;
76 	register long t1;
77 	caddr_t bpos;
78 	int error = 0, rdonly, cache, mode = 0;
79 	char *cp2;
80 	struct mbuf *mb, *mb2, *mreq;
81 	u_quad_t frev;
82 
83 	fhp = &nfh.fh_generic;
84 	nfsm_srvmtofh(fhp);
85 	nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
86 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
87 		nfsm_reply(0);
88 	if (*tl++ == nfs_true)
89 		mode |= VREAD;
90 	if (*tl++ == nfs_true)
91 		mode |= VWRITE;
92 	if (*tl == nfs_true)
93 		mode |= VEXEC;
94 	error = nfsrv_access(vp, mode, cred, rdonly, nfsd->nd_procp);
95 	vput(vp);
96 	nfsm_reply(0);
97 	nfsm_srvdone;
98 }
99 
100 /*
101  * nfs getattr service
102  */
103 nfsrv_getattr(nfsd, mrep, md, dpos, cred, nam, mrq)
104 	struct nfsd *nfsd;
105 	struct mbuf *mrep, *md;
106 	caddr_t dpos;
107 	struct ucred *cred;
108 	struct mbuf *nam, **mrq;
109 {
110 	register struct nfsv2_fattr *fp;
111 	struct vattr va;
112 	register struct vattr *vap = &va;
113 	struct vnode *vp;
114 	nfsv2fh_t nfh;
115 	fhandle_t *fhp;
116 	register u_long *tl;
117 	register long t1;
118 	caddr_t bpos;
119 	int error = 0, rdonly, cache;
120 	char *cp2;
121 	struct mbuf *mb, *mb2, *mreq;
122 	u_quad_t frev;
123 
124 	fhp = &nfh.fh_generic;
125 	nfsm_srvmtofh(fhp);
126 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
127 		nfsm_reply(0);
128 	nqsrv_getl(vp, NQL_READ);
129 	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
130 	vput(vp);
131 	nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
132 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
133 	nfsm_srvfillattr;
134 	nfsm_srvdone;
135 }
136 
137 /*
138  * nfs setattr service
139  */
140 nfsrv_setattr(nfsd, mrep, md, dpos, cred, nam, mrq)
141 	struct nfsd *nfsd;
142 	struct mbuf *mrep, *md;
143 	caddr_t dpos;
144 	struct ucred *cred;
145 	struct mbuf *nam, **mrq;
146 {
147 	struct vattr va;
148 	register struct vattr *vap = &va;
149 	register struct nfsv2_sattr *sp;
150 	register struct nfsv2_fattr *fp;
151 	struct vnode *vp;
152 	nfsv2fh_t nfh;
153 	fhandle_t *fhp;
154 	register u_long *tl;
155 	register long t1;
156 	caddr_t bpos;
157 	int error = 0, rdonly, cache, duration2, cache2;
158 	char *cp2;
159 	struct mbuf *mb, *mb2, *mreq;
160 	u_quad_t frev, frev2;
161 
162 	fhp = &nfh.fh_generic;
163 	nfsm_srvmtofh(fhp);
164 	nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));
165 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
166 		nfsm_reply(0);
167 	nqsrv_getl(vp, NQL_WRITE);
168 	VATTR_NULL(vap);
169 	/*
170 	 * Nah nah nah nah na nah
171 	 * There is a bug in the Sun client that puts 0xffff in the mode
172 	 * field of sattr when it should put in 0xffffffff. The u_short
173 	 * doesn't sign extend.
174 	 * --> check the low order 2 bytes for 0xffff
175 	 */
176 	if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
177 		vap->va_mode = nfstov_mode(sp->sa_mode);
178 	if (sp->sa_uid != nfs_xdrneg1)
179 		vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
180 	if (sp->sa_gid != nfs_xdrneg1)
181 		vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
182 	if (nfsd->nd_nqlflag == NQL_NOVAL) {
183 		if (sp->sa_nfssize != nfs_xdrneg1)
184 			vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_nfssize);
185 		if (sp->sa_nfsatime.nfs_sec != nfs_xdrneg1) {
186 #ifdef notyet
187 			fxdr_nfstime(&sp->sa_nfsatime, &vap->va_atime);
188 #else
189 			vap->va_atime.ts_sec =
190 				fxdr_unsigned(long, sp->sa_nfsatime.nfs_sec);
191 			vap->va_atime.ts_nsec = 0;
192 #endif
193 		}
194 		if (sp->sa_nfsmtime.nfs_sec != nfs_xdrneg1)
195 			fxdr_nfstime(&sp->sa_nfsmtime, &vap->va_mtime);
196 	} else {
197 		fxdr_hyper(&sp->sa_nqsize, &vap->va_size);
198 		fxdr_nqtime(&sp->sa_nqatime, &vap->va_atime);
199 		fxdr_nqtime(&sp->sa_nqmtime, &vap->va_mtime);
200 		vap->va_flags = fxdr_unsigned(u_long, sp->sa_nqflags);
201 	}
202 
203 	/*
204 	 * If the size is being changed write acces is required, otherwise
205 	 * just check for a read only file system.
206 	 */
207 	if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
208 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
209 			error = EROFS;
210 			goto out;
211 		}
212 	} else {
213 		if (vp->v_type == VDIR) {
214 			error = EISDIR;
215 			goto out;
216 		} else if (error = nfsrv_access(vp, VWRITE, cred, rdonly,
217 			nfsd->nd_procp))
218 			goto out;
219 	}
220 	if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
221 		vput(vp);
222 		nfsm_reply(0);
223 	}
224 	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
225 out:
226 	vput(vp);
227 	nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 2*NFSX_UNSIGNED);
228 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
229 	nfsm_srvfillattr;
230 	if (nfsd->nd_nqlflag != NQL_NOVAL) {
231 		nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
232 		txdr_hyper(&frev2, tl);
233 	}
234 	nfsm_srvdone;
235 }
236 
237 /*
238  * nfs lookup rpc
239  */
240 nfsrv_lookup(nfsd, mrep, md, dpos, cred, nam, mrq)
241 	struct nfsd *nfsd;
242 	struct mbuf *mrep, *md;
243 	caddr_t dpos;
244 	struct ucred *cred;
245 	struct mbuf *nam, **mrq;
246 {
247 	register struct nfsv2_fattr *fp;
248 	struct nameidata nd;
249 	struct vnode *vp;
250 	nfsv2fh_t nfh;
251 	fhandle_t *fhp;
252 	register caddr_t cp;
253 	register u_long *tl;
254 	register long t1;
255 	caddr_t bpos;
256 	int error = 0, rdonly, cache, duration2, cache2, len;
257 	char *cp2;
258 	struct mbuf *mb, *mb2, *mreq;
259 	struct vattr va, *vap = &va;
260 	u_quad_t frev, frev2;
261 
262 	fhp = &nfh.fh_generic;
263 	duration2 = 0;
264 	if (nfsd->nd_nqlflag != NQL_NOVAL) {
265 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
266 		duration2 = fxdr_unsigned(int, *tl);
267 	}
268 	nfsm_srvmtofh(fhp);
269 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
270 	nd.ni_cnd.cn_cred = cred;
271 	nd.ni_cnd.cn_nameiop = LOOKUP;
272 	nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
273 	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,
274 	    nfsd->nd_procp))
275 		nfsm_reply(0);
276 	nqsrv_getl(nd.ni_startdir, NQL_READ);
277 	vrele(nd.ni_startdir);
278 	FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
279 	vp = nd.ni_vp;
280 	bzero((caddr_t)fhp, sizeof(nfh));
281 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
282 	if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
283 		vput(vp);
284 		nfsm_reply(0);
285 	}
286 	if (duration2)
287 		(void) nqsrv_getlease(vp, &duration2, NQL_READ, nfsd,
288 			nam, &cache2, &frev2, cred);
289 	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
290 	vput(vp);
291 	nfsm_reply(NFSX_FH + NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL) + 5*NFSX_UNSIGNED);
292 	if (nfsd->nd_nqlflag != NQL_NOVAL) {
293 		if (duration2) {
294 			nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
295 			*tl++ = txdr_unsigned(NQL_READ);
296 			*tl++ = txdr_unsigned(cache2);
297 			*tl++ = txdr_unsigned(duration2);
298 			txdr_hyper(&frev2, tl);
299 		} else {
300 			nfsm_build(tl, u_long *, NFSX_UNSIGNED);
301 			*tl = 0;
302 		}
303 	}
304 	nfsm_srvfhtom(fhp);
305 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
306 	nfsm_srvfillattr;
307 	nfsm_srvdone;
308 }
309 
310 /*
311  * nfs readlink service
312  */
313 nfsrv_readlink(nfsd, mrep, md, dpos, cred, nam, mrq)
314 	struct nfsd *nfsd;
315 	struct mbuf *mrep, *md;
316 	caddr_t dpos;
317 	struct ucred *cred;
318 	struct mbuf *nam, **mrq;
319 {
320 	struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
321 	register struct iovec *ivp = iv;
322 	register struct mbuf *mp;
323 	register u_long *tl;
324 	register long t1;
325 	caddr_t bpos;
326 	int error = 0, rdonly, cache, i, tlen, len;
327 	char *cp2;
328 	struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
329 	struct vnode *vp;
330 	nfsv2fh_t nfh;
331 	fhandle_t *fhp;
332 	struct uio io, *uiop = &io;
333 	u_quad_t frev;
334 
335 	fhp = &nfh.fh_generic;
336 	nfsm_srvmtofh(fhp);
337 	len = 0;
338 	i = 0;
339 	while (len < NFS_MAXPATHLEN) {
340 		MGET(mp, M_WAIT, MT_DATA);
341 		MCLGET(mp, M_WAIT);
342 		mp->m_len = NFSMSIZ(mp);
343 		if (len == 0)
344 			mp3 = mp2 = mp;
345 		else {
346 			mp2->m_next = mp;
347 			mp2 = mp;
348 		}
349 		if ((len+mp->m_len) > NFS_MAXPATHLEN) {
350 			mp->m_len = NFS_MAXPATHLEN-len;
351 			len = NFS_MAXPATHLEN;
352 		} else
353 			len += mp->m_len;
354 		ivp->iov_base = mtod(mp, caddr_t);
355 		ivp->iov_len = mp->m_len;
356 		i++;
357 		ivp++;
358 	}
359 	uiop->uio_iov = iv;
360 	uiop->uio_iovcnt = i;
361 	uiop->uio_offset = 0;
362 	uiop->uio_resid = len;
363 	uiop->uio_rw = UIO_READ;
364 	uiop->uio_segflg = UIO_SYSSPACE;
365 	uiop->uio_procp = (struct proc *)0;
366 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) {
367 		m_freem(mp3);
368 		nfsm_reply(0);
369 	}
370 	if (vp->v_type != VLNK) {
371 		error = EINVAL;
372 		goto out;
373 	}
374 	nqsrv_getl(vp, NQL_READ);
375 	error = VOP_READLINK(vp, uiop, cred);
376 out:
377 	vput(vp);
378 	if (error)
379 		m_freem(mp3);
380 	nfsm_reply(NFSX_UNSIGNED);
381 	if (uiop->uio_resid > 0) {
382 		len -= uiop->uio_resid;
383 		tlen = nfsm_rndup(len);
384 		nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
385 	}
386 	nfsm_build(tl, u_long *, NFSX_UNSIGNED);
387 	*tl = txdr_unsigned(len);
388 	mb->m_next = mp3;
389 	nfsm_srvdone;
390 }
391 
392 /*
393  * nfs read service
394  */
395 nfsrv_read(nfsd, mrep, md, dpos, cred, nam, mrq)
396 	struct nfsd *nfsd;
397 	struct mbuf *mrep, *md;
398 	caddr_t dpos;
399 	struct ucred *cred;
400 	struct mbuf *nam, **mrq;
401 {
402 	register struct iovec *iv;
403 	struct iovec *iv2;
404 	register struct mbuf *m;
405 	register struct nfsv2_fattr *fp;
406 	register u_long *tl;
407 	register long t1;
408 	caddr_t bpos;
409 	int error = 0, rdonly, cache, i, cnt, len, left, siz, tlen;
410 	char *cp2;
411 	struct mbuf *mb, *mb2, *mreq;
412 	struct mbuf *m2;
413 	struct vnode *vp;
414 	nfsv2fh_t nfh;
415 	fhandle_t *fhp;
416 	struct uio io, *uiop = &io;
417 	struct vattr va, *vap = &va;
418 	off_t off;
419 	u_quad_t frev;
420 
421 	fhp = &nfh.fh_generic;
422 	nfsm_srvmtofh(fhp);
423 	if (nfsd->nd_nqlflag == NQL_NOVAL) {
424 		nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
425 		off = (off_t)fxdr_unsigned(u_long, *tl);
426 	} else {
427 		nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
428 		fxdr_hyper(tl, &off);
429 	}
430 	nfsm_srvstrsiz(cnt, NFS_MAXDATA);
431 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
432 		nfsm_reply(0);
433 	nqsrv_getl(vp, NQL_READ);
434 	if ((error = nfsrv_access(vp, VREAD, cred, rdonly, nfsd->nd_procp)) &&
435 	    (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp))) {
436 		vput(vp);
437 		nfsm_reply(0);
438 	}
439 	if (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp)) {
440 		vput(vp);
441 		nfsm_reply(0);
442 	}
443 	if (off >= vap->va_size)
444 		cnt = 0;
445 	else if ((off + cnt) > vap->va_size)
446 		cnt = nfsm_rndup(vap->va_size - off);
447 	nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)+NFSX_UNSIGNED+nfsm_rndup(cnt));
448 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
449 	nfsm_build(tl, u_long *, NFSX_UNSIGNED);
450 	len = left = cnt;
451 	if (cnt > 0) {
452 		/*
453 		 * Generate the mbuf list with the uio_iov ref. to it.
454 		 */
455 		i = 0;
456 		m = m2 = mb;
457 		MALLOC(iv, struct iovec *,
458 		       ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec),
459 		       M_TEMP, M_WAITOK);
460 		iv2 = iv;
461 		while (left > 0) {
462 			siz = min(M_TRAILINGSPACE(m), left);
463 			if (siz > 0) {
464 				m->m_len += siz;
465 				iv->iov_base = bpos;
466 				iv->iov_len = siz;
467 				iv++;
468 				i++;
469 				left -= siz;
470 			}
471 			if (left > 0) {
472 				MGET(m, M_WAIT, MT_DATA);
473 				MCLGET(m, M_WAIT);
474 				m->m_len = 0;
475 				m2->m_next = m;
476 				m2 = m;
477 				bpos = mtod(m, caddr_t);
478 			}
479 		}
480 		uiop->uio_iov = iv2;
481 		uiop->uio_iovcnt = i;
482 		uiop->uio_offset = off;
483 		uiop->uio_resid = cnt;
484 		uiop->uio_rw = UIO_READ;
485 		uiop->uio_segflg = UIO_SYSSPACE;
486 		error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
487 		off = uiop->uio_offset;
488 		FREE((caddr_t)iv2, M_TEMP);
489 		if (error || (error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp))) {
490 			m_freem(mreq);
491 			vput(vp);
492 			nfsm_reply(0);
493 		}
494 	} else
495 		uiop->uio_resid = 0;
496 	vput(vp);
497 	nfsm_srvfillattr;
498 	len -= uiop->uio_resid;
499 	tlen = nfsm_rndup(len);
500 	if (cnt != tlen || tlen != len)
501 		nfsm_adj(mb, cnt-tlen, tlen-len);
502 	*tl = txdr_unsigned(len);
503 	nfsm_srvdone;
504 }
505 
506 /*
507  * nfs write service
508  */
509 nfsrv_write(nfsd, mrep, md, dpos, cred, nam, mrq)
510 	struct nfsd *nfsd;
511 	struct mbuf *mrep, *md;
512 	caddr_t dpos;
513 	struct ucred *cred;
514 	struct mbuf *nam, **mrq;
515 {
516 	register struct iovec *ivp;
517 	register struct mbuf *mp;
518 	register struct nfsv2_fattr *fp;
519 	struct iovec iv[NFS_MAXIOVEC];
520 	struct vattr va;
521 	register struct vattr *vap = &va;
522 	register u_long *tl;
523 	register long t1;
524 	caddr_t bpos;
525 	int error = 0, rdonly, cache, siz, len, xfer;
526 	int ioflags = IO_SYNC | IO_NODELOCKED;
527 	char *cp2;
528 	struct mbuf *mb, *mb2, *mreq;
529 	struct vnode *vp;
530 	nfsv2fh_t nfh;
531 	fhandle_t *fhp;
532 	struct uio io, *uiop = &io;
533 	off_t off;
534 	u_quad_t frev;
535 
536 	fhp = &nfh.fh_generic;
537 	nfsm_srvmtofh(fhp);
538 	nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);
539 	if (nfsd->nd_nqlflag == NQL_NOVAL) {
540 		off = (off_t)fxdr_unsigned(u_long, *++tl);
541 		tl += 2;
542 	} else {
543 		fxdr_hyper(tl, &off);
544 		tl += 2;
545 		if (fxdr_unsigned(u_long, *tl++))
546 			ioflags |= IO_APPEND;
547 	}
548 	len = fxdr_unsigned(long, *tl);
549 	if (len > NFS_MAXDATA || len <= 0) {
550 		error = EBADRPC;
551 		nfsm_reply(0);
552 	}
553 	if (dpos == (mtod(md, caddr_t)+md->m_len)) {
554 		mp = md->m_next;
555 		if (mp == NULL) {
556 			error = EBADRPC;
557 			nfsm_reply(0);
558 		}
559 	} else {
560 		mp = md;
561 		siz = dpos-mtod(mp, caddr_t);
562 		mp->m_len -= siz;
563 		NFSMADV(mp, siz);
564 	}
565 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
566 		nfsm_reply(0);
567 	nqsrv_getl(vp, NQL_WRITE);
568 	if (error = nfsrv_access(vp, VWRITE, cred, rdonly, nfsd->nd_procp)) {
569 		vput(vp);
570 		nfsm_reply(0);
571 	}
572 	uiop->uio_resid = 0;
573 	uiop->uio_rw = UIO_WRITE;
574 	uiop->uio_segflg = UIO_SYSSPACE;
575 	uiop->uio_procp = (struct proc *)0;
576 	/*
577 	 * Do up to NFS_MAXIOVEC mbufs of write each iteration of the
578 	 * loop until done.
579 	 */
580 	while (len > 0 && uiop->uio_resid == 0) {
581 		ivp = iv;
582 		siz = 0;
583 		uiop->uio_iov = ivp;
584 		uiop->uio_iovcnt = 0;
585 		uiop->uio_offset = off;
586 		while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) {
587 			ivp->iov_base = mtod(mp, caddr_t);
588 			if (len < mp->m_len)
589 				ivp->iov_len = xfer = len;
590 			else
591 				ivp->iov_len = xfer = mp->m_len;
592 #ifdef notdef
593 			/* Not Yet .. */
594 			if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0)
595 				ivp->iov_op = NULL;	/* what should it be ?? */
596 			else
597 				ivp->iov_op = NULL;
598 #endif
599 			uiop->uio_iovcnt++;
600 			ivp++;
601 			len -= xfer;
602 			siz += xfer;
603 			mp = mp->m_next;
604 		}
605 		if (len > 0 && mp == NULL) {
606 			error = EBADRPC;
607 			vput(vp);
608 			nfsm_reply(0);
609 		}
610 		uiop->uio_resid = siz;
611 		if (error = VOP_WRITE(vp, uiop, ioflags, cred)) {
612 			vput(vp);
613 			nfsm_reply(0);
614 		}
615 		off = uiop->uio_offset;
616 	}
617 	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
618 	vput(vp);
619 	nfsm_reply(NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
620 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
621 	nfsm_srvfillattr;
622 	if (nfsd->nd_nqlflag != NQL_NOVAL) {
623 		nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
624 		txdr_hyper(&vap->va_filerev, tl);
625 	}
626 	nfsm_srvdone;
627 }
628 
629 /*
630  * nfs create service
631  * now does a truncate to 0 length via. setattr if it already exists
632  */
633 nfsrv_create(nfsd, mrep, md, dpos, cred, nam, mrq)
634 	struct nfsd *nfsd;
635 	struct mbuf *mrep, *md;
636 	caddr_t dpos;
637 	struct ucred *cred;
638 	struct mbuf *nam, **mrq;
639 {
640 	register struct nfsv2_fattr *fp;
641 	struct vattr va;
642 	register struct vattr *vap = &va;
643 	register struct nfsv2_sattr *sp;
644 	register u_long *tl;
645 	struct nameidata nd;
646 	register caddr_t cp;
647 	register long t1;
648 	caddr_t bpos;
649 	int error = 0, rdev, cache, len, tsize;
650 	char *cp2;
651 	struct mbuf *mb, *mb2, *mreq;
652 	struct vnode *vp;
653 	nfsv2fh_t nfh;
654 	fhandle_t *fhp;
655 	u_quad_t frev;
656 
657 	nd.ni_cnd.cn_nameiop = 0;
658 	fhp = &nfh.fh_generic;
659 	nfsm_srvmtofh(fhp);
660 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
661 	nd.ni_cnd.cn_cred = cred;
662 	nd.ni_cnd.cn_nameiop = CREATE;
663 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
664 	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,
665 	    nfsd->nd_procp))
666 		nfsm_reply(0);
667 	VATTR_NULL(vap);
668 	nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));
669 	/*
670 	 * Iff doesn't exist, create it
671 	 * otherwise just truncate to 0 length
672 	 *   should I set the mode too ??
673 	 */
674 	if (nd.ni_vp == NULL) {
675 		vap->va_type = IFTOVT(fxdr_unsigned(u_long, sp->sa_mode));
676 		if (vap->va_type == VNON)
677 			vap->va_type = VREG;
678 		vap->va_mode = nfstov_mode(sp->sa_mode);
679 		if (nfsd->nd_nqlflag == NQL_NOVAL)
680 			rdev = fxdr_unsigned(long, sp->sa_nfssize);
681 		else
682 			rdev = fxdr_unsigned(long, sp->sa_nqrdev);
683 		if (vap->va_type == VREG || vap->va_type == VSOCK) {
684 			vrele(nd.ni_startdir);
685 			nqsrv_getl(nd.ni_dvp, NQL_WRITE);
686 			if (error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap))
687 				nfsm_reply(0);
688 			FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
689 		} else if (vap->va_type == VCHR || vap->va_type == VBLK ||
690 			vap->va_type == VFIFO) {
691 			if (vap->va_type == VCHR && rdev == 0xffffffff)
692 				vap->va_type = VFIFO;
693 			if (vap->va_type == VFIFO) {
694 #ifndef FIFO
695 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
696 				vput(nd.ni_dvp);
697 				error = ENXIO;
698 				goto out;
699 #endif /* FIFO */
700 			} else if (error = suser(cred, (u_short *)0)) {
701 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
702 				vput(nd.ni_dvp);
703 				goto out;
704 			} else
705 				vap->va_rdev = (dev_t)rdev;
706 			nqsrv_getl(nd.ni_dvp, NQL_WRITE);
707 			if (error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) {
708 				vrele(nd.ni_startdir);
709 				nfsm_reply(0);
710 			}
711 			nd.ni_cnd.cn_nameiop = LOOKUP;
712 			nd.ni_cnd.cn_flags &= ~(LOCKPARENT | SAVESTART);
713 			nd.ni_cnd.cn_proc = nfsd->nd_procp;
714 			nd.ni_cnd.cn_cred = nfsd->nd_procp->p_ucred;
715 			if (error = lookup(&nd)) {
716 				free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
717 				nfsm_reply(0);
718 			}
719 			FREE(nd.ni_cnd.cn_pnbuf, M_NAMEI);
720 			if (nd.ni_cnd.cn_flags & ISSYMLINK) {
721 				vrele(nd.ni_dvp);
722 				vput(nd.ni_vp);
723 				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
724 				error = EINVAL;
725 				nfsm_reply(0);
726 			}
727 		} else {
728 			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
729 			vput(nd.ni_dvp);
730 			error = ENXIO;
731 			goto out;
732 		}
733 		vp = nd.ni_vp;
734 	} else {
735 		vrele(nd.ni_startdir);
736 		free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
737 		vp = nd.ni_vp;
738 		if (nd.ni_dvp == vp)
739 			vrele(nd.ni_dvp);
740 		else
741 			vput(nd.ni_dvp);
742 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
743 		if (nfsd->nd_nqlflag == NQL_NOVAL) {
744 			tsize = fxdr_unsigned(long, sp->sa_nfssize);
745 			if (tsize != -1)
746 				vap->va_size = (u_quad_t)tsize;
747 			else
748 				vap->va_size = -1;
749 		} else
750 			fxdr_hyper(&sp->sa_nqsize, &vap->va_size);
751 		if (vap->va_size != -1) {
752 			nqsrv_getl(vp, NQL_WRITE);
753 			if (error = VOP_SETATTR(vp, vap, cred, nfsd->nd_procp)) {
754 				vput(vp);
755 				nfsm_reply(0);
756 			}
757 		}
758 	}
759 	bzero((caddr_t)fhp, sizeof(nfh));
760 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
761 	if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
762 		vput(vp);
763 		nfsm_reply(0);
764 	}
765 	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
766 	vput(vp);
767 	nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
768 	nfsm_srvfhtom(fhp);
769 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
770 	nfsm_srvfillattr;
771 	return (error);
772 nfsmout:
773 	if (nd.ni_cnd.cn_nameiop || nd.ni_cnd.cn_flags)
774 		vrele(nd.ni_startdir);
775 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
776 	if (nd.ni_dvp == nd.ni_vp)
777 		vrele(nd.ni_dvp);
778 	else
779 		vput(nd.ni_dvp);
780 	if (nd.ni_vp)
781 		vput(nd.ni_vp);
782 	return (error);
783 
784 out:
785 	vrele(nd.ni_startdir);
786 	free(nd.ni_cnd.cn_pnbuf, M_NAMEI);
787 	nfsm_reply(0);
788 }
789 
790 /*
791  * nfs remove service
792  */
793 nfsrv_remove(nfsd, mrep, md, dpos, cred, nam, mrq)
794 	struct nfsd *nfsd;
795 	struct mbuf *mrep, *md;
796 	caddr_t dpos;
797 	struct ucred *cred;
798 	struct mbuf *nam, **mrq;
799 {
800 	struct nameidata nd;
801 	register u_long *tl;
802 	register long t1;
803 	caddr_t bpos;
804 	int error = 0, cache, len;
805 	char *cp2;
806 	struct mbuf *mb, *mreq;
807 	struct vnode *vp;
808 	nfsv2fh_t nfh;
809 	fhandle_t *fhp;
810 	u_quad_t frev;
811 
812 	fhp = &nfh.fh_generic;
813 	nfsm_srvmtofh(fhp);
814 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
815 	nd.ni_cnd.cn_cred = cred;
816 	nd.ni_cnd.cn_nameiop = DELETE;
817 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
818 	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,
819 	    nfsd->nd_procp))
820 		nfsm_reply(0);
821 	vp = nd.ni_vp;
822 	if (vp->v_type == VDIR &&
823 		(error = suser(cred, (u_short *)0)))
824 		goto out;
825 	/*
826 	 * The root of a mounted filesystem cannot be deleted.
827 	 */
828 	if (vp->v_flag & VROOT) {
829 		error = EBUSY;
830 		goto out;
831 	}
832 	if (vp->v_flag & VTEXT)
833 		(void) vnode_pager_uncache(vp);
834 out:
835 	if (!error) {
836 		nqsrv_getl(nd.ni_dvp, NQL_WRITE);
837 		nqsrv_getl(vp, NQL_WRITE);
838 		error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
839 	} else {
840 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
841 		if (nd.ni_dvp == vp)
842 			vrele(nd.ni_dvp);
843 		else
844 			vput(nd.ni_dvp);
845 		vput(vp);
846 	}
847 	nfsm_reply(0);
848 	nfsm_srvdone;
849 }
850 
851 /*
852  * nfs rename service
853  */
854 nfsrv_rename(nfsd, mrep, md, dpos, cred, nam, mrq)
855 	struct nfsd *nfsd;
856 	struct mbuf *mrep, *md;
857 	caddr_t dpos;
858 	struct ucred *cred;
859 	struct mbuf *nam, **mrq;
860 {
861 	register u_long *tl;
862 	register long t1;
863 	caddr_t bpos;
864 	int error = 0, rdonly, cache, len, len2;
865 	char *cp2;
866 	struct mbuf *mb, *mreq;
867 	struct nameidata fromnd, tond;
868 	struct vnode *fvp, *tvp, *tdvp;
869 	nfsv2fh_t fnfh, tnfh;
870 	fhandle_t *ffhp, *tfhp;
871 	u_quad_t frev;
872 	uid_t saved_uid;
873 
874 	ffhp = &fnfh.fh_generic;
875 	tfhp = &tnfh.fh_generic;
876 	fromnd.ni_cnd.cn_nameiop = 0;
877 	tond.ni_cnd.cn_nameiop = 0;
878 	nfsm_srvmtofh(ffhp);
879 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
880 	/*
881 	 * Remember our original uid so that we can reset cr_uid before
882 	 * the second nfs_namei() call, in case it is remapped.
883 	 */
884 	saved_uid = cred->cr_uid;
885 	fromnd.ni_cnd.cn_cred = cred;
886 	fromnd.ni_cnd.cn_nameiop = DELETE;
887 	fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
888 	if (error = nfs_namei(&fromnd, ffhp, len, nfsd->nd_slp, nam, &md,
889 	    &dpos, nfsd->nd_procp))
890 		nfsm_reply(0);
891 	fvp = fromnd.ni_vp;
892 	nfsm_srvmtofh(tfhp);
893 	nfsm_strsiz(len2, NFS_MAXNAMLEN);
894 	cred->cr_uid = saved_uid;
895 	tond.ni_cnd.cn_cred = cred;
896 	tond.ni_cnd.cn_nameiop = RENAME;
897 	tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
898 	if (error = nfs_namei(&tond, tfhp, len2, nfsd->nd_slp, nam, &md,
899 	    &dpos, nfsd->nd_procp)) {
900 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
901 		vrele(fromnd.ni_dvp);
902 		vrele(fvp);
903 		goto out1;
904 	}
905 	tdvp = tond.ni_dvp;
906 	tvp = tond.ni_vp;
907 	if (tvp != NULL) {
908 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
909 			error = EISDIR;
910 			goto out;
911 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
912 			error = ENOTDIR;
913 			goto out;
914 		}
915 		if (tvp->v_type == VDIR && tvp->v_mountedhere) {
916 			error = EXDEV;
917 			goto out;
918 		}
919 	}
920 	if (fvp->v_type == VDIR && fvp->v_mountedhere) {
921 		error = EBUSY;
922 		goto out;
923 	}
924 	if (fvp->v_mount != tdvp->v_mount) {
925 		error = EXDEV;
926 		goto out;
927 	}
928 	if (fvp == tdvp)
929 		error = EINVAL;
930 	/*
931 	 * If source is the same as the destination (that is the
932 	 * same vnode with the same name in the same directory),
933 	 * then there is nothing to do.
934 	 */
935 	if (fvp == tvp && fromnd.ni_dvp == tdvp &&
936 	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
937 	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
938 	      fromnd.ni_cnd.cn_namelen))
939 		error = -1;
940 out:
941 	if (!error) {
942 		nqsrv_getl(fromnd.ni_dvp, NQL_WRITE);
943 		nqsrv_getl(tdvp, NQL_WRITE);
944 		if (tvp)
945 			nqsrv_getl(tvp, NQL_WRITE);
946 		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
947 				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
948 	} else {
949 		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
950 		if (tdvp == tvp)
951 			vrele(tdvp);
952 		else
953 			vput(tdvp);
954 		if (tvp)
955 			vput(tvp);
956 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
957 		vrele(fromnd.ni_dvp);
958 		vrele(fvp);
959 	}
960 	vrele(tond.ni_startdir);
961 	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
962 out1:
963 	vrele(fromnd.ni_startdir);
964 	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
965 	nfsm_reply(0);
966 	return (error);
967 
968 nfsmout:
969 	if (tond.ni_cnd.cn_nameiop || tond.ni_cnd.cn_flags) {
970 		vrele(tond.ni_startdir);
971 		FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
972 	}
973 	if (fromnd.ni_cnd.cn_nameiop || fromnd.ni_cnd.cn_flags) {
974 		vrele(fromnd.ni_startdir);
975 		FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
976 		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
977 		vrele(fromnd.ni_dvp);
978 		vrele(fvp);
979 	}
980 	return (error);
981 }
982 
983 /*
984  * nfs link service
985  */
986 nfsrv_link(nfsd, mrep, md, dpos, cred, nam, mrq)
987 	struct nfsd *nfsd;
988 	struct mbuf *mrep, *md;
989 	caddr_t dpos;
990 	struct ucred *cred;
991 	struct mbuf *nam, **mrq;
992 {
993 	struct nameidata nd;
994 	register u_long *tl;
995 	register long t1;
996 	caddr_t bpos;
997 	int error = 0, rdonly, cache, len;
998 	char *cp2;
999 	struct mbuf *mb, *mreq;
1000 	struct vnode *vp, *xp;
1001 	nfsv2fh_t nfh, dnfh;
1002 	fhandle_t *fhp, *dfhp;
1003 	u_quad_t frev;
1004 
1005 	fhp = &nfh.fh_generic;
1006 	dfhp = &dnfh.fh_generic;
1007 	nfsm_srvmtofh(fhp);
1008 	nfsm_srvmtofh(dfhp);
1009 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
1010 	if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
1011 		nfsm_reply(0);
1012 	if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)))
1013 		goto out1;
1014 	nd.ni_cnd.cn_cred = cred;
1015 	nd.ni_cnd.cn_nameiop = CREATE;
1016 	nd.ni_cnd.cn_flags = LOCKPARENT;
1017 	if (error = nfs_namei(&nd, dfhp, len, nfsd->nd_slp, nam, &md, &dpos,
1018 	    nfsd->nd_procp))
1019 		goto out1;
1020 	xp = nd.ni_vp;
1021 	if (xp != NULL) {
1022 		error = EEXIST;
1023 		goto out;
1024 	}
1025 	xp = nd.ni_dvp;
1026 	if (vp->v_mount != xp->v_mount)
1027 		error = EXDEV;
1028 out:
1029 	if (!error) {
1030 		nqsrv_getl(vp, NQL_WRITE);
1031 		nqsrv_getl(xp, NQL_WRITE);
1032 		error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
1033 	} else {
1034 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1035 		if (nd.ni_dvp == nd.ni_vp)
1036 			vrele(nd.ni_dvp);
1037 		else
1038 			vput(nd.ni_dvp);
1039 		if (nd.ni_vp)
1040 			vrele(nd.ni_vp);
1041 	}
1042 out1:
1043 	vrele(vp);
1044 	nfsm_reply(0);
1045 	nfsm_srvdone;
1046 }
1047 
1048 /*
1049  * nfs symbolic link service
1050  */
1051 nfsrv_symlink(nfsd, mrep, md, dpos, cred, nam, mrq)
1052 	struct nfsd *nfsd;
1053 	struct mbuf *mrep, *md;
1054 	caddr_t dpos;
1055 	struct ucred *cred;
1056 	struct mbuf *nam, **mrq;
1057 {
1058 	struct vattr va;
1059 	struct nameidata nd;
1060 	register struct vattr *vap = &va;
1061 	register u_long *tl;
1062 	register long t1;
1063 	struct nfsv2_sattr *sp;
1064 	caddr_t bpos;
1065 	struct uio io;
1066 	struct iovec iv;
1067 	int error = 0, rdonly, cache, len, len2;
1068 	char *pathcp, *cp2;
1069 	struct mbuf *mb, *mreq;
1070 	nfsv2fh_t nfh;
1071 	fhandle_t *fhp;
1072 	u_quad_t frev;
1073 
1074 	pathcp = (char *)0;
1075 	fhp = &nfh.fh_generic;
1076 	nfsm_srvmtofh(fhp);
1077 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
1078 	nd.ni_cnd.cn_cred = cred;
1079 	nd.ni_cnd.cn_nameiop = CREATE;
1080 	nd.ni_cnd.cn_flags = LOCKPARENT;
1081 	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,
1082 	    nfsd->nd_procp))
1083 		goto out;
1084 	nfsm_strsiz(len2, NFS_MAXPATHLEN);
1085 	MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
1086 	iv.iov_base = pathcp;
1087 	iv.iov_len = len2;
1088 	io.uio_resid = len2;
1089 	io.uio_offset = 0;
1090 	io.uio_iov = &iv;
1091 	io.uio_iovcnt = 1;
1092 	io.uio_segflg = UIO_SYSSPACE;
1093 	io.uio_rw = UIO_READ;
1094 	io.uio_procp = (struct proc *)0;
1095 	nfsm_mtouio(&io, len2);
1096 	nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL));
1097 	*(pathcp + len2) = '\0';
1098 	if (nd.ni_vp) {
1099 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1100 		if (nd.ni_dvp == nd.ni_vp)
1101 			vrele(nd.ni_dvp);
1102 		else
1103 			vput(nd.ni_dvp);
1104 		vrele(nd.ni_vp);
1105 		error = EEXIST;
1106 		goto out;
1107 	}
1108 	VATTR_NULL(vap);
1109 	vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);
1110 	nqsrv_getl(nd.ni_dvp, NQL_WRITE);
1111 	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
1112 out:
1113 	if (pathcp)
1114 		FREE(pathcp, M_TEMP);
1115 	nfsm_reply(0);
1116 	return (error);
1117 nfsmout:
1118 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1119 	if (nd.ni_dvp == nd.ni_vp)
1120 		vrele(nd.ni_dvp);
1121 	else
1122 		vput(nd.ni_dvp);
1123 	if (nd.ni_vp)
1124 		vrele(nd.ni_vp);
1125 	if (pathcp)
1126 		FREE(pathcp, M_TEMP);
1127 	return (error);
1128 }
1129 
1130 /*
1131  * nfs mkdir service
1132  */
1133 nfsrv_mkdir(nfsd, mrep, md, dpos, cred, nam, mrq)
1134 	struct nfsd *nfsd;
1135 	struct mbuf *mrep, *md;
1136 	caddr_t dpos;
1137 	struct ucred *cred;
1138 	struct mbuf *nam, **mrq;
1139 {
1140 	struct vattr va;
1141 	register struct vattr *vap = &va;
1142 	register struct nfsv2_fattr *fp;
1143 	struct nameidata nd;
1144 	register caddr_t cp;
1145 	register u_long *tl;
1146 	register long t1;
1147 	caddr_t bpos;
1148 	int error = 0, rdonly, cache, len;
1149 	char *cp2;
1150 	struct mbuf *mb, *mb2, *mreq;
1151 	struct vnode *vp;
1152 	nfsv2fh_t nfh;
1153 	fhandle_t *fhp;
1154 	u_quad_t frev;
1155 
1156 	fhp = &nfh.fh_generic;
1157 	nfsm_srvmtofh(fhp);
1158 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
1159 	nd.ni_cnd.cn_cred = cred;
1160 	nd.ni_cnd.cn_nameiop = CREATE;
1161 	nd.ni_cnd.cn_flags = LOCKPARENT;
1162 	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,
1163 	    nfsd->nd_procp))
1164 		nfsm_reply(0);
1165 	nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
1166 	VATTR_NULL(vap);
1167 	vap->va_type = VDIR;
1168 	vap->va_mode = nfstov_mode(*tl++);
1169 	vp = nd.ni_vp;
1170 	if (vp != NULL) {
1171 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1172 		if (nd.ni_dvp == vp)
1173 			vrele(nd.ni_dvp);
1174 		else
1175 			vput(nd.ni_dvp);
1176 		vrele(vp);
1177 		error = EEXIST;
1178 		nfsm_reply(0);
1179 	}
1180 	nqsrv_getl(nd.ni_dvp, NQL_WRITE);
1181 	if (error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap))
1182 		nfsm_reply(0);
1183 	vp = nd.ni_vp;
1184 	bzero((caddr_t)fhp, sizeof(nfh));
1185 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1186 	if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
1187 		vput(vp);
1188 		nfsm_reply(0);
1189 	}
1190 	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
1191 	vput(vp);
1192 	nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
1193 	nfsm_srvfhtom(fhp);
1194 	nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL));
1195 	nfsm_srvfillattr;
1196 	return (error);
1197 nfsmout:
1198 	VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1199 	if (nd.ni_dvp == nd.ni_vp)
1200 		vrele(nd.ni_dvp);
1201 	else
1202 		vput(nd.ni_dvp);
1203 	if (nd.ni_vp)
1204 		vrele(nd.ni_vp);
1205 	return (error);
1206 }
1207 
1208 /*
1209  * nfs rmdir service
1210  */
1211 nfsrv_rmdir(nfsd, mrep, md, dpos, cred, nam, mrq)
1212 	struct nfsd *nfsd;
1213 	struct mbuf *mrep, *md;
1214 	caddr_t dpos;
1215 	struct ucred *cred;
1216 	struct mbuf *nam, **mrq;
1217 {
1218 	register u_long *tl;
1219 	register long t1;
1220 	caddr_t bpos;
1221 	int error = 0, rdonly, cache, len;
1222 	char *cp2;
1223 	struct mbuf *mb, *mreq;
1224 	struct vnode *vp;
1225 	nfsv2fh_t nfh;
1226 	fhandle_t *fhp;
1227 	struct nameidata nd;
1228 	u_quad_t frev;
1229 
1230 	fhp = &nfh.fh_generic;
1231 	nfsm_srvmtofh(fhp);
1232 	nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
1233 	nd.ni_cnd.cn_cred = cred;
1234 	nd.ni_cnd.cn_nameiop = DELETE;
1235 	nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1236 	if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos,
1237 	    nfsd->nd_procp))
1238 		nfsm_reply(0);
1239 	vp = nd.ni_vp;
1240 	if (vp->v_type != VDIR) {
1241 		error = ENOTDIR;
1242 		goto out;
1243 	}
1244 	/*
1245 	 * No rmdir "." please.
1246 	 */
1247 	if (nd.ni_dvp == vp) {
1248 		error = EINVAL;
1249 		goto out;
1250 	}
1251 	/*
1252 	 * The root of a mounted filesystem cannot be deleted.
1253 	 */
1254 	if (vp->v_flag & VROOT)
1255 		error = EBUSY;
1256 out:
1257 	if (!error) {
1258 		nqsrv_getl(nd.ni_dvp, NQL_WRITE);
1259 		nqsrv_getl(vp, NQL_WRITE);
1260 		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1261 	} else {
1262 		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1263 		if (nd.ni_dvp == nd.ni_vp)
1264 			vrele(nd.ni_dvp);
1265 		else
1266 			vput(nd.ni_dvp);
1267 		vput(vp);
1268 	}
1269 	nfsm_reply(0);
1270 	nfsm_srvdone;
1271 }
1272 
1273 /*
1274  * nfs readdir service
1275  * - mallocs what it thinks is enough to read
1276  *	count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
1277  * - calls VOP_READDIR()
1278  * - loops around building the reply
1279  *	if the output generated exceeds count break out of loop
1280  *	The nfsm_clget macro is used here so that the reply will be packed
1281  *	tightly in mbuf clusters.
1282  * - it only knows that it has encountered eof when the VOP_READDIR()
1283  *	reads nothing
1284  * - as such one readdir rpc will return eof false although you are there
1285  *	and then the next will return eof
1286  * - it trims out records with d_fileno == 0
1287  *	this doesn't matter for Unix clients, but they might confuse clients
1288  *	for other os'.
1289  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
1290  *	than requested, but this may not apply to all filesystems. For
1291  *	example, client NFS does not { although it is never remote mounted
1292  *	anyhow }
1293  *     The alternate call nqnfsrv_readdirlook() does lookups as well.
1294  * PS: The NFS protocol spec. does not clarify what the "count" byte
1295  *	argument is a count of.. just name strings and file id's or the
1296  *	entire reply rpc or ...
1297  *	I tried just file name and id sizes and it confused the Sun client,
1298  *	so I am using the full rpc size now. The "paranoia.." comment refers
1299  *	to including the status longwords that are not a part of the dir.
1300  *	"entry" structures, but are in the rpc.
1301  */
1302 struct flrep {
1303 	u_long fl_cachable;
1304 	u_long fl_duration;
1305 	u_long fl_frev[2];
1306 	nfsv2fh_t fl_nfh;
1307 	u_long fl_fattr[NFSX_NQFATTR / sizeof (u_long)];
1308 };
1309 
1310 nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)
1311 	struct nfsd *nfsd;
1312 	struct mbuf *mrep, *md;
1313 	caddr_t dpos;
1314 	struct ucred *cred;
1315 	struct mbuf *nam, **mrq;
1316 {
1317 	register char *bp, *be;
1318 	register struct mbuf *mp;
1319 	register struct dirent *dp;
1320 	register caddr_t cp;
1321 	register u_long *tl;
1322 	register long t1;
1323 	caddr_t bpos;
1324 	struct mbuf *mb, *mb2, *mreq, *mp2;
1325 	char *cpos, *cend, *cp2, *rbuf;
1326 	struct vnode *vp;
1327 	nfsv2fh_t nfh;
1328 	fhandle_t *fhp;
1329 	struct uio io;
1330 	struct iovec iv;
1331 	struct vattr va;
1332 	int len, nlen, rem, xfer, tsiz, i, error = 0;
1333 	int siz, cnt, fullsiz, eofflag, rdonly, cache;
1334 	u_quad_t frev;
1335 	u_long on, off, toff;
1336 
1337 	fhp = &nfh.fh_generic;
1338 	nfsm_srvmtofh(fhp);
1339 	nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
1340 	toff = fxdr_unsigned(u_long, *tl++);
1341 	off = (toff & ~(NFS_DIRBLKSIZ-1));
1342 	on = (toff & (NFS_DIRBLKSIZ-1));
1343 	cnt = fxdr_unsigned(int, *tl);
1344 	siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
1345 	if (cnt > NFS_MAXREADDIR)
1346 		siz = NFS_MAXREADDIR;
1347 	fullsiz = siz;
1348 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
1349 		nfsm_reply(0);
1350 	nqsrv_getl(vp, NQL_READ);
1351 	if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) {
1352 		vput(vp);
1353 		nfsm_reply(0);
1354 	}
1355 	VOP_UNLOCK(vp);
1356 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
1357 again:
1358 	iv.iov_base = rbuf;
1359 	iv.iov_len = fullsiz;
1360 	io.uio_iov = &iv;
1361 	io.uio_iovcnt = 1;
1362 	io.uio_offset = (off_t)off;
1363 	io.uio_resid = fullsiz;
1364 	io.uio_segflg = UIO_SYSSPACE;
1365 	io.uio_rw = UIO_READ;
1366 	io.uio_procp = (struct proc *)0;
1367 	error = VOP_READDIR(vp, &io, cred);
1368 	off = (off_t)io.uio_offset;
1369 	if (error) {
1370 		vrele(vp);
1371 		free((caddr_t)rbuf, M_TEMP);
1372 		nfsm_reply(0);
1373 	}
1374 	if (io.uio_resid < fullsiz)
1375 		eofflag = 0;
1376 	else
1377 		eofflag = 1;
1378 	if (io.uio_resid) {
1379 		siz -= io.uio_resid;
1380 
1381 		/*
1382 		 * If nothing read, return eof
1383 		 * rpc reply
1384 		 */
1385 		if (siz == 0) {
1386 			vrele(vp);
1387 			nfsm_reply(2*NFSX_UNSIGNED);
1388 			nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
1389 			*tl++ = nfs_false;
1390 			*tl = nfs_true;
1391 			FREE((caddr_t)rbuf, M_TEMP);
1392 			return (0);
1393 		}
1394 	}
1395 
1396 	/*
1397 	 * Check for degenerate cases of nothing useful read.
1398 	 * If so go try again
1399 	 */
1400 	cpos = rbuf + on;
1401 	cend = rbuf + siz;
1402 	dp = (struct dirent *)cpos;
1403 	while (cpos < cend && dp->d_fileno == 0) {
1404 		cpos += dp->d_reclen;
1405 		dp = (struct dirent *)cpos;
1406 	}
1407 	if (cpos >= cend) {
1408 		toff = off;
1409 		siz = fullsiz;
1410 		on = 0;
1411 		goto again;
1412 	}
1413 
1414 	cpos = rbuf + on;
1415 	cend = rbuf + siz;
1416 	dp = (struct dirent *)cpos;
1417 	len = 3*NFSX_UNSIGNED;	/* paranoia, probably can be 0 */
1418 	nfsm_reply(siz);
1419 	mp = mp2 = mb;
1420 	bp = bpos;
1421 	be = bp + M_TRAILINGSPACE(mp);
1422 
1423 	/* Loop through the records and build reply */
1424 	while (cpos < cend) {
1425 		if (dp->d_fileno != 0) {
1426 			nlen = dp->d_namlen;
1427 			rem = nfsm_rndup(nlen)-nlen;
1428 			len += (4*NFSX_UNSIGNED + nlen + rem);
1429 			if (len > cnt) {
1430 				eofflag = 0;
1431 				break;
1432 			}
1433 			/*
1434 			 * Build the directory record xdr from
1435 			 * the dirent entry.
1436 			 */
1437 			nfsm_clget;
1438 			*tl = nfs_true;
1439 			bp += NFSX_UNSIGNED;
1440 			nfsm_clget;
1441 			*tl = txdr_unsigned(dp->d_fileno);
1442 			bp += NFSX_UNSIGNED;
1443 			nfsm_clget;
1444 			*tl = txdr_unsigned(nlen);
1445 			bp += NFSX_UNSIGNED;
1446 
1447 			/* And loop around copying the name */
1448 			xfer = nlen;
1449 			cp = dp->d_name;
1450 			while (xfer > 0) {
1451 				nfsm_clget;
1452 				if ((bp+xfer) > be)
1453 					tsiz = be-bp;
1454 				else
1455 					tsiz = xfer;
1456 				bcopy(cp, bp, tsiz);
1457 				bp += tsiz;
1458 				xfer -= tsiz;
1459 				if (xfer > 0)
1460 					cp += tsiz;
1461 			}
1462 			/* And null pad to a long boundary */
1463 			for (i = 0; i < rem; i++)
1464 				*bp++ = '\0';
1465 			nfsm_clget;
1466 
1467 			/* Finish off the record */
1468 			toff += dp->d_reclen;
1469 			*tl = txdr_unsigned(toff);
1470 			bp += NFSX_UNSIGNED;
1471 		} else
1472 			toff += dp->d_reclen;
1473 		cpos += dp->d_reclen;
1474 		dp = (struct dirent *)cpos;
1475 	}
1476 	vrele(vp);
1477 	nfsm_clget;
1478 	*tl = nfs_false;
1479 	bp += NFSX_UNSIGNED;
1480 	nfsm_clget;
1481 	if (eofflag)
1482 		*tl = nfs_true;
1483 	else
1484 		*tl = nfs_false;
1485 	bp += NFSX_UNSIGNED;
1486 	if (mp != mb) {
1487 		if (bp < be)
1488 			mp->m_len = bp - mtod(mp, caddr_t);
1489 	} else
1490 		mp->m_len += bp - bpos;
1491 	FREE(rbuf, M_TEMP);
1492 	nfsm_srvdone;
1493 }
1494 
1495 nqnfsrv_readdirlook(nfsd, mrep, md, dpos, cred, nam, mrq)
1496 	struct nfsd *nfsd;
1497 	struct mbuf *mrep, *md;
1498 	caddr_t dpos;
1499 	struct ucred *cred;
1500 	struct mbuf *nam, **mrq;
1501 {
1502 	register char *bp, *be;
1503 	register struct mbuf *mp;
1504 	register struct dirent *dp;
1505 	register caddr_t cp;
1506 	register u_long *tl;
1507 	register long t1;
1508 	caddr_t bpos;
1509 	struct mbuf *mb, *mb2, *mreq, *mp2;
1510 	char *cpos, *cend, *cp2, *rbuf;
1511 	struct vnode *vp, *nvp;
1512 	struct flrep fl;
1513 	nfsv2fh_t nfh;
1514 	fhandle_t *fhp;
1515 	struct uio io;
1516 	struct iovec iv;
1517 	struct vattr va, *vap = &va;
1518 	struct nfsv2_fattr *fp;
1519 	int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2;
1520 	int siz, cnt, fullsiz, eofflag, rdonly, cache;
1521 	u_quad_t frev, frev2;
1522 	u_long on, off, toff;
1523 
1524 	fhp = &nfh.fh_generic;
1525 	nfsm_srvmtofh(fhp);
1526 	nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
1527 	toff = fxdr_unsigned(u_long, *tl++);
1528 	off = (toff & ~(NFS_DIRBLKSIZ-1));
1529 	on = (toff & (NFS_DIRBLKSIZ-1));
1530 	cnt = fxdr_unsigned(int, *tl++);
1531 	duration2 = fxdr_unsigned(int, *tl);
1532 	siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
1533 	if (cnt > NFS_MAXREADDIR)
1534 		siz = NFS_MAXREADDIR;
1535 	fullsiz = siz;
1536 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
1537 		nfsm_reply(0);
1538 	nqsrv_getl(vp, NQL_READ);
1539 	if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) {
1540 		vput(vp);
1541 		nfsm_reply(0);
1542 	}
1543 	VOP_UNLOCK(vp);
1544 	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
1545 again:
1546 	iv.iov_base = rbuf;
1547 	iv.iov_len = fullsiz;
1548 	io.uio_iov = &iv;
1549 	io.uio_iovcnt = 1;
1550 	io.uio_offset = (off_t)off;
1551 	io.uio_resid = fullsiz;
1552 	io.uio_segflg = UIO_SYSSPACE;
1553 	io.uio_rw = UIO_READ;
1554 	io.uio_procp = (struct proc *)0;
1555 	error = VOP_READDIR(vp, &io, cred);
1556 	off = (u_long)io.uio_offset;
1557 	if (error) {
1558 		vrele(vp);
1559 		free((caddr_t)rbuf, M_TEMP);
1560 		nfsm_reply(0);
1561 	}
1562 	if (io.uio_resid < fullsiz)
1563 		eofflag = 0;
1564 	else
1565 		eofflag = 1;
1566 	if (io.uio_resid) {
1567 		siz -= io.uio_resid;
1568 
1569 		/*
1570 		 * If nothing read, return eof
1571 		 * rpc reply
1572 		 */
1573 		if (siz == 0) {
1574 			vrele(vp);
1575 			nfsm_reply(2 * NFSX_UNSIGNED);
1576 			nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
1577 			*tl++ = nfs_false;
1578 			*tl = nfs_true;
1579 			FREE((caddr_t)rbuf, M_TEMP);
1580 			return (0);
1581 		}
1582 	}
1583 
1584 	/*
1585 	 * Check for degenerate cases of nothing useful read.
1586 	 * If so go try again
1587 	 */
1588 	cpos = rbuf + on;
1589 	cend = rbuf + siz;
1590 	dp = (struct dirent *)cpos;
1591 	while (cpos < cend && dp->d_fileno == 0) {
1592 		cpos += dp->d_reclen;
1593 		dp = (struct dirent *)cpos;
1594 	}
1595 	if (cpos >= cend) {
1596 		toff = off;
1597 		siz = fullsiz;
1598 		on = 0;
1599 		goto again;
1600 	}
1601 
1602 	cpos = rbuf + on;
1603 	cend = rbuf + siz;
1604 	dp = (struct dirent *)cpos;
1605 	len = 3 * NFSX_UNSIGNED;	/* paranoia, probably can be 0 */
1606 	nfsm_reply(siz);
1607 	mp = mp2 = mb;
1608 	bp = bpos;
1609 	be = bp + M_TRAILINGSPACE(mp);
1610 
1611 	/* Loop through the records and build reply */
1612 	while (cpos < cend) {
1613 		if (dp->d_fileno != 0) {
1614 			nlen = dp->d_namlen;
1615 			rem = nfsm_rndup(nlen)-nlen;
1616 
1617 			/*
1618 			 * For readdir_and_lookup get the vnode using
1619 			 * the file number.
1620 			 */
1621 			if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
1622 				goto invalid;
1623 			bzero((caddr_t)&fl.fl_nfh, sizeof (nfsv2fh_t));
1624 			fl.fl_nfh.fh_generic.fh_fsid =
1625 				nvp->v_mount->mnt_stat.f_fsid;
1626 			if (VFS_VPTOFH(nvp, &fl.fl_nfh.fh_generic.fh_fid)) {
1627 				vput(nvp);
1628 				goto invalid;
1629 			}
1630 			if (duration2) {
1631 				(void) nqsrv_getlease(nvp, &duration2, NQL_READ,
1632 					nfsd, nam, &cache2, &frev2, cred);
1633 				fl.fl_duration = txdr_unsigned(duration2);
1634 				fl.fl_cachable = txdr_unsigned(cache2);
1635 				txdr_hyper(&frev2, fl.fl_frev);
1636 			} else
1637 				fl.fl_duration = 0;
1638 			if (VOP_GETATTR(nvp, vap, cred, nfsd->nd_procp)) {
1639 				vput(nvp);
1640 				goto invalid;
1641 			}
1642 			vput(nvp);
1643 			fp = (struct nfsv2_fattr *)&fl.fl_fattr;
1644 			nfsm_srvfillattr;
1645 			len += (4*NFSX_UNSIGNED + nlen + rem + NFSX_FH
1646 				+ NFSX_NQFATTR);
1647 			if (len > cnt) {
1648 				eofflag = 0;
1649 				break;
1650 			}
1651 			/*
1652 			 * Build the directory record xdr from
1653 			 * the dirent entry.
1654 			 */
1655 			nfsm_clget;
1656 			*tl = nfs_true;
1657 			bp += NFSX_UNSIGNED;
1658 
1659 			/*
1660 			 * For readdir_and_lookup copy the stuff out.
1661 			 */
1662 			xfer = sizeof (struct flrep);
1663 			cp = (caddr_t)&fl;
1664 			while (xfer > 0) {
1665 				nfsm_clget;
1666 				if ((bp+xfer) > be)
1667 					tsiz = be-bp;
1668 				else
1669 					tsiz = xfer;
1670 				bcopy(cp, bp, tsiz);
1671 				bp += tsiz;
1672 				xfer -= tsiz;
1673 				if (xfer > 0)
1674 					cp += tsiz;
1675 			}
1676 			nfsm_clget;
1677 			*tl = txdr_unsigned(dp->d_fileno);
1678 			bp += NFSX_UNSIGNED;
1679 			nfsm_clget;
1680 			*tl = txdr_unsigned(nlen);
1681 			bp += NFSX_UNSIGNED;
1682 
1683 			/* And loop around copying the name */
1684 			xfer = nlen;
1685 			cp = dp->d_name;
1686 			while (xfer > 0) {
1687 				nfsm_clget;
1688 				if ((bp+xfer) > be)
1689 					tsiz = be-bp;
1690 				else
1691 					tsiz = xfer;
1692 				bcopy(cp, bp, tsiz);
1693 				bp += tsiz;
1694 				xfer -= tsiz;
1695 				if (xfer > 0)
1696 					cp += tsiz;
1697 			}
1698 			/* And null pad to a long boundary */
1699 			for (i = 0; i < rem; i++)
1700 				*bp++ = '\0';
1701 			nfsm_clget;
1702 
1703 			/* Finish off the record */
1704 			toff += dp->d_reclen;
1705 			*tl = txdr_unsigned(toff);
1706 			bp += NFSX_UNSIGNED;
1707 		} else
1708 invalid:
1709 			toff += dp->d_reclen;
1710 		cpos += dp->d_reclen;
1711 		dp = (struct dirent *)cpos;
1712 	}
1713 	vrele(vp);
1714 	nfsm_clget;
1715 	*tl = nfs_false;
1716 	bp += NFSX_UNSIGNED;
1717 	nfsm_clget;
1718 	if (eofflag)
1719 		*tl = nfs_true;
1720 	else
1721 		*tl = nfs_false;
1722 	bp += NFSX_UNSIGNED;
1723 	if (mp != mb) {
1724 		if (bp < be)
1725 			mp->m_len = bp - mtod(mp, caddr_t);
1726 	} else
1727 		mp->m_len += bp - bpos;
1728 	FREE(rbuf, M_TEMP);
1729 	nfsm_srvdone;
1730 }
1731 
1732 /*
1733  * nfs statfs service
1734  */
1735 nfsrv_statfs(nfsd, mrep, md, dpos, cred, nam, mrq)
1736 	struct nfsd *nfsd;
1737 	struct mbuf *mrep, *md;
1738 	caddr_t dpos;
1739 	struct ucred *cred;
1740 	struct mbuf *nam, **mrq;
1741 {
1742 	register struct statfs *sf;
1743 	register struct nfsv2_statfs *sfp;
1744 	register u_long *tl;
1745 	register long t1;
1746 	caddr_t bpos;
1747 	int error = 0, rdonly, cache, isnq;
1748 	char *cp2;
1749 	struct mbuf *mb, *mb2, *mreq;
1750 	struct vnode *vp;
1751 	nfsv2fh_t nfh;
1752 	fhandle_t *fhp;
1753 	struct statfs statfs;
1754 	u_quad_t frev;
1755 
1756 	fhp = &nfh.fh_generic;
1757 	isnq = (nfsd->nd_nqlflag != NQL_NOVAL);
1758 	nfsm_srvmtofh(fhp);
1759 	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))
1760 		nfsm_reply(0);
1761 	sf = &statfs;
1762 	error = VFS_STATFS(vp->v_mount, sf, nfsd->nd_procp);
1763 	vput(vp);
1764 	nfsm_reply(NFSX_STATFS(isnq));
1765 	nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
1766 	sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
1767 	sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
1768 	sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
1769 	sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
1770 	sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
1771 	if (isnq) {
1772 		sfp->sf_files = txdr_unsigned(sf->f_files);
1773 		sfp->sf_ffree = txdr_unsigned(sf->f_ffree);
1774 	}
1775 	nfsm_srvdone;
1776 }
1777 
1778 /*
1779  * Null operation, used by clients to ping server
1780  */
1781 /* ARGSUSED */
1782 nfsrv_null(nfsd, mrep, md, dpos, cred, nam, mrq)
1783 	struct nfsd *nfsd;
1784 	struct mbuf *mrep, *md;
1785 	caddr_t dpos;
1786 	struct ucred *cred;
1787 	struct mbuf *nam, **mrq;
1788 {
1789 	caddr_t bpos;
1790 	int error = VNOVAL, cache;
1791 	struct mbuf *mb, *mreq;
1792 	u_quad_t frev;
1793 
1794 	nfsm_reply(0);
1795 	return (error);
1796 }
1797 
1798 /*
1799  * No operation, used for obsolete procedures
1800  */
1801 /* ARGSUSED */
1802 nfsrv_noop(nfsd, mrep, md, dpos, cred, nam, mrq)
1803 	struct nfsd *nfsd;
1804 	struct mbuf *mrep, *md;
1805 	caddr_t dpos;
1806 	struct ucred *cred;
1807 	struct mbuf *nam, **mrq;
1808 {
1809 	caddr_t bpos;
1810 	int error, cache;
1811 	struct mbuf *mb, *mreq;
1812 	u_quad_t frev;
1813 
1814 	if (nfsd->nd_repstat)
1815 		error = nfsd->nd_repstat;
1816 	else
1817 		error = EPROCUNAVAIL;
1818 	nfsm_reply(0);
1819 	return (error);
1820 }
1821 
1822 /*
1823  * Perform access checking for vnodes obtained from file handles that would
1824  * refer to files already opened by a Unix client. You cannot just use
1825  * vn_writechk() and VOP_ACCESS() for two reasons.
1826  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
1827  * 2 - The owner is to be given access irrespective of mode bits so that
1828  *     processes that chmod after opening a file don't break. I don't like
1829  *     this because it opens a security hole, but since the nfs server opens
1830  *     a security hole the size of a barn door anyhow, what the heck.
1831  */
1832 nfsrv_access(vp, flags, cred, rdonly, p)
1833 	register struct vnode *vp;
1834 	int flags;
1835 	register struct ucred *cred;
1836 	int rdonly;
1837 	struct proc *p;
1838 {
1839 	struct vattr vattr;
1840 	int error;
1841 	if (flags & VWRITE) {
1842 		/* Just vn_writechk() changed to check rdonly */
1843 		/*
1844 		 * Disallow write attempts on read-only file systems;
1845 		 * unless the file is a socket or a block or character
1846 		 * device resident on the file system.
1847 		 */
1848 		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
1849 			switch (vp->v_type) {
1850 			case VREG: case VDIR: case VLNK:
1851 				return (EROFS);
1852 			}
1853 		}
1854 		/*
1855 		 * If there's shared text associated with
1856 		 * the inode, try to free it up once.  If
1857 		 * we fail, we can't allow writing.
1858 		 */
1859 		if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
1860 			return (ETXTBSY);
1861 	}
1862 	if (error = VOP_GETATTR(vp, &vattr, cred, p))
1863 		return (error);
1864 	if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
1865 	    cred->cr_uid != vattr.va_uid)
1866 		return (error);
1867 	return (0);
1868 }
1869