if (dp->d_fileno == 0) { cpos += dp->d_reclen; cookie++; } else break; } if (cpos >= cend) {
cookiep++; ncookies--; } if (cpos >= cend || ncookies == 0) { toff = off;
nfsrv_readdir(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	register char *bp, *be;	register struct mbuf *mp;	register struct dirent *dp = NULL;	register caddr_t cp;	register u_int32_t *tl;	register int32_t t1;	caddr_t bpos;	struct mbuf *mb, *mb2, *mreq, *mp2;	char *cpos, *cend, *cp2, *rbuf;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct uio io;	struct iovec iv;	int len, nlen, rem, xfer, tsiz, i, error = 0;	int siz, cnt, fullsiz, eofflag, rdonly, cache;	u_quad_t frev;	u_long off, *cookiebuf, *cookie;	int ncookies;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_dissect(tl, u_int32_t *, 2*NFSX_UNSIGNED);	off = fxdr_unsigned(u_int32_t, *tl++);	cnt = fxdr_unsigned(int, *tl);	siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));	if (cnt > NFS_MAXREADDIR)		siz = NFS_MAXREADDIR;	fullsiz = siz;	ncookies = siz / 16;	/* Guess at the number of cookies needed. */	error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly);	if (error)		nfsm_reply(0);	nqsrv_getl(vp, NQL_READ);	error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp);	if (error) {		vput(vp);		nfsm_reply(0);	}	VOP_UNLOCK(vp);	MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);	MALLOC(cookiebuf, u_long *, ncookies * sizeof(*cookiebuf), M_TEMP,	    M_WAITOK);again:	iv.iov_base = rbuf;	iv.iov_len = fullsiz;	io.uio_iov = &iv;	io.uio_iovcnt = 1;	io.uio_offset = (off_t)off;	io.uio_resid = fullsiz;	io.uio_segflg = UIO_SYSSPACE;	io.uio_rw = UIO_READ;	io.uio_procp = (struct proc *)0;	error = VOP_READDIR(vp, &io, cred, &eofflag, cookiebuf, ncookies);	cookie = cookiebuf;	off = (off_t)io.uio_offset;	if (error) {		vrele(vp);		free((caddr_t)cookiebuf, M_TEMP);		free((caddr_t)rbuf, M_TEMP);		nfsm_reply(0);	}	if (io.uio_resid) {		siz -= io.uio_resid;		/*		 * If nothing read, return eof		 * rpc reply		 */		if (siz == 0) {			vrele(vp);			nfsm_reply(2*NFSX_UNSIGNED);			nfsm_build(tl, u_int32_t *, 2*NFSX_UNSIGNED);			*tl++ = nfs_false;			*tl = nfs_true;			FREE((caddr_t)cookiebuf, M_TEMP);			FREE((caddr_t)rbuf, M_TEMP);			return (0);		}	}	/*	 * Check for degenerate cases of nothing useful read.	 * If so go try again	 */	cpos = rbuf;	cend = rbuf + siz;	while (cpos < cend) {		dp = (struct dirent *)cpos;		if (dp->d_fileno == 0) {			cpos += dp->d_reclen;			cookie++;		} else			break;	}	if (cpos >= cend) {		siz = fullsiz;		goto again;	}	len = 3*NFSX_UNSIGNED;	/* paranoia, probably can be 0 */	nfsm_reply(siz);	mp = mp2 = mb;	bp = bpos;	be = bp + M_TRAILINGSPACE(mp);	/* Loop through the records and build reply */	while (cpos < cend) {		if (dp->d_fileno != 0) {			nlen = dp->d_namlen;			rem = nfsm_rndup(nlen)-nlen;			len += (4*NFSX_UNSIGNED + nlen + rem);			if (len > cnt) {				eofflag = 0;				break;			}			/*			 * Build the directory record xdr from			 * the dirent entry.			 */			nfsm_clget;			*tl = nfs_true;			bp += NFSX_UNSIGNED;			nfsm_clget;			*tl = txdr_unsigned(dp->d_fileno);			bp += NFSX_UNSIGNED;			nfsm_clget;			*tl = txdr_unsigned(nlen);			bp += NFSX_UNSIGNED;				/* And loop around copying the name */			xfer = nlen;			cp = dp->d_name;			while (xfer > 0) {				nfsm_clget;				if ((bp+xfer) > be)					tsiz = be-bp;				else					tsiz = xfer;				bcopy(cp, bp, tsiz);				bp += tsiz;				xfer -= tsiz;				if (xfer > 0)					cp += tsiz;			}			/* And null pad to a int32_t boundary */			for (i = 0; i < rem; i++)				*bp++ = '\0';			nfsm_clget;				/* Finish off the record */			*tl = txdr_unsigned(*cookie);			bp += NFSX_UNSIGNED;		}		cpos += dp->d_reclen;		dp = (struct dirent *)cpos;		cookie++;	}	vrele(vp);	nfsm_clget;	*tl = nfs_false;	bp += NFSX_UNSIGNED;	nfsm_clget;	if (eofflag)		*tl = nfs_true;	else		*tl = nfs_false;	bp += NFSX_UNSIGNED;	if (mp != mb) {		if (bp < be)			mp->m_len = bp - mtod(mp, caddr_t);	} else		mp->m_len += bp - bpos;	FREE(cookiebuf, M_TEMP);	FREE(rbuf, M_TEMP);	nfsm_srvdone;}