dp->d_namlen = (u_char)len; dp->d_type = DT_UNKNOWN; nfsm_adv(len);
nfs_readdirrpc(vp, uiop, cred)	register struct vnode *vp;	struct uio *uiop;	struct ucred *cred;{	register long len;	register struct dirent *dp = NULL;	register u_int32_t *tl;	register caddr_t cp;	register int32_t t1;	long tlen, lastlen = 0;	caddr_t bpos, dpos, cp2;	int error = 0;	struct mbuf *mreq, *mrep, *md, *mb, *mb2;	struct mbuf *md2;	caddr_t dpos2;	int siz;	int more_dirs = 1;	u_long off = 0, savoff = 0;	struct dirent *savdp = NULL;	struct nfsmount *nmp;	struct nfsnode *np = VTONFS(vp);	long tresid, extra;	nmp = VFSTONFS(vp->v_mount);	extra = uiop->uio_resid & (NFS_DIRBLKSIZ - 1);	uiop->uio_resid -= extra;	tresid = uiop->uio_resid;	/*	 * Loop around doing readdir rpc's of size uio_resid or nm_rsize,	 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ.	 * The stopping criteria is EOF or buffer full.	 */	while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {		nfsstats.rpccnt[NFSPROC_READDIR]++;		nfsm_reqhead(vp, NFSPROC_READDIR,			NFSX_FH + 2 * NFSX_UNSIGNED);		nfsm_fhtom(vp);		nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);		off = (u_long)uiop->uio_offset;		*tl++ = txdr_unsigned(off);		*tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?			nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));		nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred);		siz = 0;		nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);		more_dirs = fxdr_unsigned(int, *tl);			/* Save the position so that we can do nfsm_mtouio() later */		dpos2 = dpos;		md2 = md;			/* loop thru the dir entries, doctoring them to 4bsd form */#ifdef lint		dp = (struct dirent *)0;#endif /* lint */		while (more_dirs && siz < uiop->uio_resid) {			savoff = off;		/* Hold onto offset and dp */			savdp = dp;			nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);			dp = (struct dirent *)tl;			dp->d_fileno = fxdr_unsigned(u_int32_t, *tl++);			len = fxdr_unsigned(int, *tl);			if (len <= 0 || len > NFS_MAXNAMLEN) {				error = EBADRPC;				m_freem(mrep);				goto nfsmout;			}			dp->d_namlen = (u_char)len;			dp->d_type = DT_UNKNOWN;			nfsm_adv(len);		/* Point past name */			tlen = nfsm_rndup(len);			/*			 * This should not be necessary, but some servers have			 * broken XDR such that these bytes are not null filled.			 */			if (tlen != len) {				*dpos = '\0';	/* Null-terminate */				nfsm_adv(tlen - len);				len = tlen;			}			nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);			off = fxdr_unsigned(u_int32_t, *tl);			*tl++ = 0;	/* Ensures null termination of name */			more_dirs = fxdr_unsigned(int, *tl);			*tl = off;	/* Store offset for cookie retrieval */			dp->d_reclen = len + 4 * NFSX_UNSIGNED;			siz += dp->d_reclen;		}		/*		 * If at end of rpc data, get the eof boolean		 */		if (!more_dirs) {			nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);			more_dirs = (fxdr_unsigned(int, *tl) == 0);			/*			 * If at EOF, cache directory offset			 */			if (!more_dirs)				np->n_direofoffset = off;		}		/*		 * If there is too much to fit in the data buffer, use savoff and		 * savdp to trim off the last record.		 * --> we are not at eof		 */		if (siz > uiop->uio_resid) {			off = savoff;			siz -= dp->d_reclen;			dp = savdp;			more_dirs = 0;	/* Paranoia */		}		if (siz > 0) {			lastlen = dp->d_reclen;			md = md2;			dpos = dpos2;			nfsm_mtouio(uiop, siz);			uiop->uio_offset = (off_t)off;		} else			more_dirs = 0;	/* Ugh, never happens, but in case.. */		m_freem(mrep);	}	/*	 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ	 * by increasing d_reclen for the last record.	 */	if (uiop->uio_resid < tresid) {		len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1);		if (len > 0) {			dp = (struct dirent *)				(uiop->uio_iov->iov_base - lastlen);			dp->d_reclen += len;			*(u_long *)((caddr_t)dp + dp->d_reclen -				    sizeof(u_long)) = off;			uiop->uio_iov->iov_base += len;			uiop->uio_iov->iov_len -= len;			uiop->uio_resid -= len;		}	}nfsmout:	uiop->uio_resid += extra;	return (error);}