⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfs_serv.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Check for degenerate cases of nothing useful read.	 * If so go try again	 */	cpos = rbuf + on;	cend = rbuf + siz;	dp = (struct dirent *)cpos;	while (cpos < cend && dp->d_fileno == 0) {		cpos += dp->d_reclen;		dp = (struct dirent *)cpos;	}	if (cpos >= cend) {		toff = off;		siz = fullsiz;		on = 0;		goto again;	}	cpos = rbuf + on;	cend = rbuf + siz;	dp = (struct dirent *)cpos;	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 long boundary */			for (i = 0; i < rem; i++)				*bp++ = '\0';			nfsm_clget;				/* Finish off the record */			toff += dp->d_reclen;			*tl = txdr_unsigned(toff);			bp += NFSX_UNSIGNED;		} else			toff += dp->d_reclen;		cpos += dp->d_reclen;		dp = (struct dirent *)cpos;	}	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(rbuf, M_TEMP);	nfsm_srvdone;}nqnfsrv_readdirlook(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;	register caddr_t cp;	register u_long *tl;	register long t1;	caddr_t bpos;	struct mbuf *mb, *mb2, *mreq, *mp2;	char *cpos, *cend, *cp2, *rbuf;	struct vnode *vp, *nvp;	struct flrep fl;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct uio io;	struct iovec iv;	struct vattr va, *vap = &va;	struct nfsv2_fattr *fp;	int len, nlen, rem, xfer, tsiz, i, error = 0, duration2, cache2;	int siz, cnt, fullsiz, eofflag, rdonly, cache;	u_quad_t frev, frev2;	u_long on, off, toff;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);	toff = fxdr_unsigned(u_long, *tl++);	off = (toff & ~(NFS_DIRBLKSIZ-1));	on = (toff & (NFS_DIRBLKSIZ-1));	cnt = fxdr_unsigned(int, *tl++);	duration2 = fxdr_unsigned(int, *tl);	siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));	if (cnt > NFS_MAXREADDIR)		siz = NFS_MAXREADDIR;	fullsiz = siz;	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	nqsrv_getl(vp, NQL_READ);	if (error = nfsrv_access(vp, VEXEC, cred, rdonly, nfsd->nd_procp)) {		vput(vp);		nfsm_reply(0);	}	VOP_UNLOCK(vp);	MALLOC(rbuf, caddr_t, siz, 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);	off = (u_long)io.uio_offset;	if (error) {		vrele(vp);		free((caddr_t)rbuf, M_TEMP);		nfsm_reply(0);	}	if (io.uio_resid < fullsiz)		eofflag = 0;	else		eofflag = 1;	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_long *, 2 * NFSX_UNSIGNED);			*tl++ = nfs_false;			*tl = nfs_true;			FREE((caddr_t)rbuf, M_TEMP);			return (0);		}	}	/*	 * Check for degenerate cases of nothing useful read.	 * If so go try again	 */	cpos = rbuf + on;	cend = rbuf + siz;	dp = (struct dirent *)cpos;	while (cpos < cend && dp->d_fileno == 0) {		cpos += dp->d_reclen;		dp = (struct dirent *)cpos;	}	if (cpos >= cend) {		toff = off;		siz = fullsiz;		on = 0;		goto again;	}	cpos = rbuf + on;	cend = rbuf + siz;	dp = (struct dirent *)cpos;	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;				/*			 * For readdir_and_lookup get the vnode using			 * the file number.			 */			if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))				goto invalid;			bzero((caddr_t)&fl.fl_nfh, sizeof (nfsv2fh_t));			fl.fl_nfh.fh_generic.fh_fsid =				nvp->v_mount->mnt_stat.f_fsid;			if (VFS_VPTOFH(nvp, &fl.fl_nfh.fh_generic.fh_fid)) {				vput(nvp);				goto invalid;			}			if (duration2) {				(void) nqsrv_getlease(nvp, &duration2, NQL_READ,					nfsd, nam, &cache2, &frev2, cred);				fl.fl_duration = txdr_unsigned(duration2);				fl.fl_cachable = txdr_unsigned(cache2);				txdr_hyper(&frev2, fl.fl_frev);			} else				fl.fl_duration = 0;			if (VOP_GETATTR(nvp, vap, cred, nfsd->nd_procp)) {				vput(nvp);				goto invalid;			}			vput(nvp);			fp = (struct nfsv2_fattr *)&fl.fl_fattr;			nfsm_srvfillattr;			len += (4*NFSX_UNSIGNED + nlen + rem + NFSX_FH				+ NFSX_NQFATTR);			if (len > cnt) {				eofflag = 0;				break;			}			/*			 * Build the directory record xdr from			 * the dirent entry.			 */			nfsm_clget;			*tl = nfs_true;			bp += NFSX_UNSIGNED;			/*			 * For readdir_and_lookup copy the stuff out.			 */			xfer = sizeof (struct flrep);			cp = (caddr_t)&fl;			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;			}			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 long boundary */			for (i = 0; i < rem; i++)				*bp++ = '\0';			nfsm_clget;				/* Finish off the record */			toff += dp->d_reclen;			*tl = txdr_unsigned(toff);			bp += NFSX_UNSIGNED;		} elseinvalid:			toff += dp->d_reclen;		cpos += dp->d_reclen;		dp = (struct dirent *)cpos;	}	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(rbuf, M_TEMP);	nfsm_srvdone;}/* * nfs statfs service */nfsrv_statfs(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 struct statfs *sf;	register struct nfsv2_statfs *sfp;	register u_long *tl;	register long t1;	caddr_t bpos;	int error = 0, rdonly, cache, isnq;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	struct statfs statfs;	u_quad_t frev;	fhp = &nfh.fh_generic;	isnq = (nfsd->nd_nqlflag != NQL_NOVAL);	nfsm_srvmtofh(fhp);	if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	sf = &statfs;	error = VFS_STATFS(vp->v_mount, sf, nfsd->nd_procp);	vput(vp);	nfsm_reply(NFSX_STATFS(isnq));	nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));	sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);	sfp->sf_bsize = txdr_unsigned(sf->f_bsize);	sfp->sf_blocks = txdr_unsigned(sf->f_blocks);	sfp->sf_bfree = txdr_unsigned(sf->f_bfree);	sfp->sf_bavail = txdr_unsigned(sf->f_bavail);	if (isnq) {		sfp->sf_files = txdr_unsigned(sf->f_files);		sfp->sf_ffree = txdr_unsigned(sf->f_ffree);	}	nfsm_srvdone;}/* * Null operation, used by clients to ping server *//* ARGSUSED */nfsrv_null(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	caddr_t bpos;	int error = VNOVAL, cache;	struct mbuf *mb, *mreq;	u_quad_t frev;	nfsm_reply(0);	return (error);}/* * No operation, used for obsolete procedures *//* ARGSUSED */nfsrv_noop(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	caddr_t bpos;	int error, cache;	struct mbuf *mb, *mreq;	u_quad_t frev;	if (nfsd->nd_repstat)		error = nfsd->nd_repstat;	else		error = EPROCUNAVAIL;	nfsm_reply(0);	return (error);}/* * Perform access checking for vnodes obtained from file handles that would * refer to files already opened by a Unix client. You cannot just use * vn_writechk() and VOP_ACCESS() for two reasons. * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case * 2 - The owner is to be given access irrespective of mode bits so that *     processes that chmod after opening a file don't break. I don't like *     this because it opens a security hole, but since the nfs server opens *     a security hole the size of a barn door anyhow, what the heck. */nfsrv_access(vp, flags, cred, rdonly, p)	register struct vnode *vp;	int flags;	register struct ucred *cred;	int rdonly;	struct proc *p;{	struct vattr vattr;	int error;	if (flags & VWRITE) {		/* Just vn_writechk() changed to check rdonly */		/*		 * Disallow write attempts on read-only file systems;		 * unless the file is a socket or a block or character		 * device resident on the file system.		 */		if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {			switch (vp->v_type) {			case VREG: case VDIR: case VLNK:				return (EROFS);			}		}		/*		 * If there's shared text associated with		 * the inode, try to free it up once.  If		 * we fail, we can't allow writing.		 */		if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))			return (ETXTBSY);	}	if (error = VOP_GETATTR(vp, &vattr, cred, p))		return (error);	if ((error = VOP_ACCESS(vp, flags, cred, p)) &&	    cred->cr_uid != vattr.va_uid)		return (error);	return (0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -