📄 nfs_serv.c
字号:
error = EXDEV; goto out; } } if (fvp->v_type == VDIR && fvp->v_mountedhere) { error = EBUSY; goto out; } if (fvp->v_mount != tdvp->v_mount) { error = EXDEV; goto out; } if (fvp == tdvp) error = EINVAL; /* * If source is the same as the destination (that is the * same vnode with the same name in the same directory), * then there is nothing to do. */ if (fvp == tvp && fromnd.ni_dvp == tdvp && fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, fromnd.ni_cnd.cn_namelen)) error = -1;out: if (!error) { nqsrv_getl(fromnd.ni_dvp, NQL_WRITE); nqsrv_getl(tdvp, NQL_WRITE); if (tvp) nqsrv_getl(tvp, NQL_WRITE); error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); } else { VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); if (tdvp == tvp) vrele(tdvp); else vput(tdvp); if (tvp) vput(tvp); VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); vrele(fromnd.ni_dvp); vrele(fvp); } vrele(tond.ni_startdir); FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);out1: vrele(fromnd.ni_startdir); FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); nfsm_reply(0); return (error);nfsmout: if (tond.ni_cnd.cn_nameiop || tond.ni_cnd.cn_flags) { vrele(tond.ni_startdir); FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); } if (fromnd.ni_cnd.cn_nameiop || fromnd.ni_cnd.cn_flags) { vrele(fromnd.ni_startdir); FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); vrele(fromnd.ni_dvp); vrele(fvp); } return (error);}/* * nfs link service */nfsrv_link(nfsd, mrep, md, dpos, cred, nam, mrq) struct nfsd *nfsd; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; struct mbuf *nam, **mrq;{ struct nameidata nd; register u_long *tl; register long t1; caddr_t bpos; int error = 0, rdonly, cache, len; char *cp2; struct mbuf *mb, *mreq; struct vnode *vp, *xp; nfsv2fh_t nfh, dnfh; fhandle_t *fhp, *dfhp; u_quad_t frev; fhp = &nfh.fh_generic; dfhp = &dnfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvmtofh(dfhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, nfsd->nd_slp, nam, &rdonly)) nfsm_reply(0); if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0))) goto out1; nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; if (error = nfs_namei(&nd, dfhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp)) goto out1; xp = nd.ni_vp; if (xp != NULL) { error = EEXIST; goto out; } xp = nd.ni_dvp; if (vp->v_mount != xp->v_mount) error = EXDEV;out: if (!error) { nqsrv_getl(vp, NQL_WRITE); nqsrv_getl(xp, NQL_WRITE); error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); if (nd.ni_vp) vrele(nd.ni_vp); }out1: vrele(vp); nfsm_reply(0); nfsm_srvdone;}/* * nfs symbolic link service */nfsrv_symlink(nfsd, mrep, md, dpos, cred, nam, mrq) struct nfsd *nfsd; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; struct mbuf *nam, **mrq;{ struct vattr va; struct nameidata nd; register struct vattr *vap = &va; register u_long *tl; register long t1; struct nfsv2_sattr *sp; caddr_t bpos; struct uio io; struct iovec iv; int error = 0, cache, len, len2; char *pathcp, *cp2; struct mbuf *mb, *mreq; nfsv2fh_t nfh; fhandle_t *fhp; u_quad_t frev; pathcp = (char *)0; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp)) goto out; nfsm_strsiz(len2, NFS_MAXPATHLEN); MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); iv.iov_base = pathcp; iv.iov_len = len2; io.uio_resid = len2; io.uio_offset = 0; io.uio_iov = &iv; io.uio_iovcnt = 1; io.uio_segflg = UIO_SYSSPACE; io.uio_rw = UIO_READ; io.uio_procp = (struct proc *)0; nfsm_mtouio(&io, len2); nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_SATTR(nfsd->nd_nqlflag != NQL_NOVAL)); *(pathcp + len2) = '\0'; if (nd.ni_vp) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(nd.ni_vp); error = EEXIST; goto out; } VATTR_NULL(vap); vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode); nqsrv_getl(nd.ni_dvp, NQL_WRITE); error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);out: if (pathcp) FREE(pathcp, M_TEMP); nfsm_reply(0); return (error);nfsmout: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); if (nd.ni_vp) vrele(nd.ni_vp); if (pathcp) FREE(pathcp, M_TEMP); return (error);}/* * nfs mkdir service */nfsrv_mkdir(nfsd, mrep, md, dpos, cred, nam, mrq) struct nfsd *nfsd; struct mbuf *mrep, *md; caddr_t dpos; struct ucred *cred; struct mbuf *nam, **mrq;{ struct vattr va; register struct vattr *vap = &va; register struct nfsv2_fattr *fp; struct nameidata nd; register caddr_t cp; register u_long *tl; register long t1; caddr_t bpos; int error = 0, cache, len; char *cp2; struct mbuf *mb, *mb2, *mreq; struct vnode *vp; nfsv2fh_t nfh; fhandle_t *fhp; u_quad_t frev; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = CREATE; nd.ni_cnd.cn_flags = LOCKPARENT; if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp)) nfsm_reply(0); nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); VATTR_NULL(vap); vap->va_type = VDIR; vap->va_mode = nfstov_mode(*tl++); vp = nd.ni_vp; if (vp != NULL) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(vp); error = EEXIST; nfsm_reply(0); } nqsrv_getl(nd.ni_dvp, NQL_WRITE); if (error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap)) nfsm_reply(0); vp = nd.ni_vp; bzero((caddr_t)fhp, sizeof(nfh)); fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) { vput(vp); nfsm_reply(0); } error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp); vput(vp); nfsm_reply(NFSX_FH+NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); nfsm_srvfhtom(fhp); nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR(nfsd->nd_nqlflag != NQL_NOVAL)); nfsm_srvfillattr; return (error);nfsmout: VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); if (nd.ni_vp) vrele(nd.ni_vp); return (error);}/* * nfs rmdir service */nfsrv_rmdir(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 u_long *tl; register long t1; caddr_t bpos; int error = 0, cache, len; char *cp2; struct mbuf *mb, *mreq; struct vnode *vp; nfsv2fh_t nfh; fhandle_t *fhp; struct nameidata nd; u_quad_t frev; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_srvstrsiz(len, NFS_MAXNAMLEN); nd.ni_cnd.cn_cred = cred; nd.ni_cnd.cn_nameiop = DELETE; nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; if (error = nfs_namei(&nd, fhp, len, nfsd->nd_slp, nam, &md, &dpos, nfsd->nd_procp)) nfsm_reply(0); vp = nd.ni_vp; if (vp->v_type != VDIR) { error = ENOTDIR; goto out; } /* * No rmdir "." please. */ if (nd.ni_dvp == vp) { error = EINVAL; goto out; } /* * The root of a mounted filesystem cannot be deleted. */ if (vp->v_flag & VROOT) error = EBUSY;out: if (!error) { nqsrv_getl(nd.ni_dvp, NQL_WRITE); nqsrv_getl(vp, NQL_WRITE); error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vput(vp); } nfsm_reply(0); nfsm_srvdone;}/* * nfs readdir service * - mallocs what it thinks is enough to read * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR * - calls VOP_READDIR() * - loops around building the reply * if the output generated exceeds count break out of loop * The nfsm_clget macro is used here so that the reply will be packed * tightly in mbuf clusters. * - it only knows that it has encountered eof when the VOP_READDIR() * reads nothing * - as such one readdir rpc will return eof false although you are there * and then the next will return eof * - it trims out records with d_fileno == 0 * this doesn't matter for Unix clients, but they might confuse clients * for other os'. * NB: It is tempting to set eof to true if the VOP_READDIR() reads less * than requested, but this may not apply to all filesystems. For * example, client NFS does not { although it is never remote mounted * anyhow } * The alternate call nqnfsrv_readdirlook() does lookups as well. * PS: The NFS protocol spec. does not clarify what the "count" byte * argument is a count of.. just name strings and file id's or the * entire reply rpc or ... * I tried just file name and id sizes and it confused the Sun client, * so I am using the full rpc size now. The "paranoia.." comment refers * to including the status longwords that are not a part of the dir. * "entry" structures, but are in the rpc. */struct flrep { u_long fl_cachable; u_long fl_duration; u_long fl_frev[2]; nfsv2fh_t fl_nfh; u_long fl_fattr[NFSX_NQFATTR / sizeof (u_long)];};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; 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; 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 on, off, toff; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); toff = fxdr_unsigned(u_long, *tl++); off = (toff & ~(NFS_DIRBLKSIZ-1)); on = (toff & (NFS_DIRBLKSIZ-1)); cnt = 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 = (off_t)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); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -