Annotation of Net2/nfs/nfs_serv.c, revision 1.1

1.1     ! root        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:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)nfs_serv.c  7.40 (Berkeley) 5/15/91
        !            37:  */
        !            38: 
        !            39: /*
        !            40:  * nfs version 2 server calls to vnode ops
        !            41:  * - these routines generally have 3 phases
        !            42:  *   1 - break down and validate rpc request in mbuf list
        !            43:  *   2 - do the vnode ops for the request
        !            44:  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
        !            45:  *   3 - build the rpc reply in an mbuf list
        !            46:  *   nb:
        !            47:  *     - do not mix the phases, since the nfsm_?? macros can return failures
        !            48:  *       on a bad rpc or similar and do not do any vrele() or vput()'s
        !            49:  *
        !            50:  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
        !            51:  *     error number iff error != 0 whereas
        !            52:  *     returning an error from the server function implies a fatal error
        !            53:  *     such as a badly constructed rpc request that should be dropped without
        !            54:  *     a reply.
        !            55:  */
        !            56: 
        !            57: #include "param.h"
        !            58: #include "proc.h"
        !            59: #include "file.h"
        !            60: #include "namei.h"
        !            61: #include "vnode.h"
        !            62: #include "mount.h"
        !            63: #include "mbuf.h"
        !            64: 
        !            65: #include "../ufs/quota.h"
        !            66: #include "../ufs/inode.h"
        !            67: #include "../ufs/dir.h"
        !            68: 
        !            69: #include "nfsv2.h"
        !            70: #include "nfs.h"
        !            71: #include "xdr_subs.h"
        !            72: #include "nfsm_subs.h"
        !            73: 
        !            74: /* Defs */
        !            75: #define        TRUE    1
        !            76: #define        FALSE   0
        !            77: 
        !            78: /* Global vars */
        !            79: extern u_long nfs_procids[NFS_NPROCS];
        !            80: extern u_long nfs_xdrneg1;
        !            81: extern u_long nfs_false, nfs_true;
        !            82: nfstype nfs_type[9]={ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
        !            83:                      NFCHR, NFNON };
        !            84: 
        !            85: /*
        !            86:  * nfs getattr service
        !            87:  */
        !            88: nfsrv_getattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !            89:        struct mbuf **mrq;
        !            90:        struct mbuf *mrep, *md;
        !            91:        caddr_t dpos;
        !            92:        struct ucred *cred;
        !            93:        u_long xid;
        !            94:        int *repstat;
        !            95:        struct proc *p;
        !            96: {
        !            97:        register struct nfsv2_fattr *fp;
        !            98:        struct vattr va;
        !            99:        register struct vattr *vap = &va;
        !           100:        struct vnode *vp;
        !           101:        nfsv2fh_t nfh;
        !           102:        fhandle_t *fhp;
        !           103:        register u_long *tl;
        !           104:        register long t1;
        !           105:        caddr_t bpos;
        !           106:        int error = 0;
        !           107:        char *cp2;
        !           108:        struct mbuf *mb, *mb2, *mreq;
        !           109: 
        !           110:        fhp = &nfh.fh_generic;
        !           111:        nfsm_srvmtofh(fhp);
        !           112:        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
        !           113:                nfsm_reply(0);
        !           114:        error = VOP_GETATTR(vp, vap, cred, p);
        !           115:        vput(vp);
        !           116:        nfsm_reply(NFSX_FATTR);
        !           117:        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        !           118:        nfsm_srvfillattr;
        !           119:        nfsm_srvdone;
        !           120: }
        !           121: 
        !           122: /*
        !           123:  * nfs setattr service
        !           124:  */
        !           125: nfsrv_setattr(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           126:        struct mbuf **mrq;
        !           127:        struct mbuf *mrep, *md;
        !           128:        caddr_t dpos;
        !           129:        struct ucred *cred;
        !           130:        u_long xid;
        !           131:        int *repstat;
        !           132:        struct proc *p;
        !           133: {
        !           134:        struct vattr va;
        !           135:        register struct vattr *vap = &va;
        !           136:        register struct nfsv2_sattr *sp;
        !           137:        register struct nfsv2_fattr *fp;
        !           138:        struct vnode *vp;
        !           139:        nfsv2fh_t nfh;
        !           140:        fhandle_t *fhp;
        !           141:        register u_long *tl;
        !           142:        register long t1;
        !           143:        caddr_t bpos;
        !           144:        int error = 0;
        !           145:        char *cp2;
        !           146:        struct mbuf *mb, *mb2, *mreq;
        !           147: 
        !           148:        fhp = &nfh.fh_generic;
        !           149:        nfsm_srvmtofh(fhp);
        !           150:        nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
        !           151:        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
        !           152:                nfsm_reply(0);
        !           153:        if (error = nfsrv_access(vp, VWRITE, cred, p))
        !           154:                goto out;
        !           155:        VATTR_NULL(vap);
        !           156:        /*
        !           157:         * Nah nah nah nah na nah
        !           158:         * There is a bug in the Sun client that puts 0xffff in the mode
        !           159:         * field of sattr when it should put in 0xffffffff. The u_short
        !           160:         * doesn't sign extend.
        !           161:         * --> check the low order 2 bytes for 0xffff
        !           162:         */
        !           163:        if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
        !           164:                vap->va_mode = nfstov_mode(sp->sa_mode);
        !           165:        if (sp->sa_uid != nfs_xdrneg1)
        !           166:                vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
        !           167:        if (sp->sa_gid != nfs_xdrneg1)
        !           168:                vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
        !           169:        if (sp->sa_size != nfs_xdrneg1)
        !           170:                vap->va_size = fxdr_unsigned(u_long, sp->sa_size);
        !           171:        /*
        !           172:         * The usec field of sa_atime is overloaded with the va_flags field
        !           173:         * for 4.4BSD clients. Hopefully other clients always set both the
        !           174:         * sec and usec fields to -1 when not setting the atime.
        !           175:         */
        !           176:        if (sp->sa_atime.tv_sec != nfs_xdrneg1) {
        !           177:                vap->va_atime.tv_sec = fxdr_unsigned(long, sp->sa_atime.tv_sec);
        !           178:                vap->va_atime.tv_usec = 0;
        !           179:        }
        !           180:        if (sp->sa_atime.tv_usec != nfs_xdrneg1)
        !           181:                vap->va_flags = fxdr_unsigned(u_long, sp->sa_atime.tv_usec);
        !           182:        if (sp->sa_mtime.tv_sec != nfs_xdrneg1)
        !           183:                fxdr_time(&sp->sa_mtime, &vap->va_mtime);
        !           184:        if (error = VOP_SETATTR(vp, vap, cred, p)) {
        !           185:                vput(vp);
        !           186:                nfsm_reply(0);
        !           187:        }
        !           188:        error = VOP_GETATTR(vp, vap, cred, p);
        !           189: out:
        !           190:        vput(vp);
        !           191:        nfsm_reply(NFSX_FATTR);
        !           192:        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        !           193:        nfsm_srvfillattr;
        !           194:        nfsm_srvdone;
        !           195: }
        !           196: 
        !           197: /*
        !           198:  * nfs lookup rpc
        !           199:  */
        !           200: nfsrv_lookup(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           201:        struct mbuf **mrq;
        !           202:        struct mbuf *mrep, *md;
        !           203:        caddr_t dpos;
        !           204:        struct ucred *cred;
        !           205:        u_long xid;
        !           206:        int *repstat;
        !           207:        struct proc *p;
        !           208: {
        !           209:        register struct nfsv2_fattr *fp;
        !           210:        struct nameidata nd;
        !           211:        struct vnode *vp;
        !           212:        nfsv2fh_t nfh;
        !           213:        fhandle_t *fhp;
        !           214:        register caddr_t cp;
        !           215:        register u_long *tl;
        !           216:        register long t1;
        !           217:        caddr_t bpos;
        !           218:        int error = 0;
        !           219:        char *cp2;
        !           220:        struct mbuf *mb, *mb2, *mreq;
        !           221:        long len;
        !           222:        struct vattr va, *vap = &va;
        !           223: 
        !           224:        fhp = &nfh.fh_generic;
        !           225:        nfsm_srvmtofh(fhp);
        !           226:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !           227:        nd.ni_cred = cred;
        !           228:        nd.ni_nameiop = LOOKUP | LOCKLEAF;
        !           229:        if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
        !           230:                nfsm_reply(0);
        !           231:        vp = nd.ni_vp;
        !           232:        bzero((caddr_t)fhp, sizeof(nfh));
        !           233:        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        !           234:        if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
        !           235:                vput(vp);
        !           236:                nfsm_reply(0);
        !           237:        }
        !           238:        error = VOP_GETATTR(vp, vap, cred, p);
        !           239:        vput(vp);
        !           240:        nfsm_reply(NFSX_FH+NFSX_FATTR);
        !           241:        nfsm_srvfhtom(fhp);
        !           242:        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        !           243:        nfsm_srvfillattr;
        !           244:        nfsm_srvdone;
        !           245: }
        !           246: 
        !           247: /*
        !           248:  * nfs readlink service
        !           249:  */
        !           250: nfsrv_readlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           251:        struct mbuf **mrq;
        !           252:        struct mbuf *mrep, *md;
        !           253:        caddr_t dpos;
        !           254:        struct ucred *cred;
        !           255:        u_long xid;
        !           256:        int *repstat;
        !           257:        struct proc *p;
        !           258: {
        !           259:        struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
        !           260:        register struct iovec *ivp = iv;
        !           261:        register struct mbuf *mp;
        !           262:        register u_long *tl;
        !           263:        register long t1;
        !           264:        caddr_t bpos;
        !           265:        int error = 0;
        !           266:        char *cp2;
        !           267:        struct mbuf *mb, *mb2, *mp2, *mp3, *mreq;
        !           268:        struct vnode *vp;
        !           269:        nfsv2fh_t nfh;
        !           270:        fhandle_t *fhp;
        !           271:        struct uio io, *uiop = &io;
        !           272:        int i, tlen, len;
        !           273: 
        !           274:        fhp = &nfh.fh_generic;
        !           275:        nfsm_srvmtofh(fhp);
        !           276:        len = 0;
        !           277:        i = 0;
        !           278:        while (len < NFS_MAXPATHLEN) {
        !           279:                MGET(mp, M_WAIT, MT_DATA);
        !           280:                MCLGET(mp, M_WAIT);
        !           281:                mp->m_len = NFSMSIZ(mp);
        !           282:                if (len == 0)
        !           283:                        mp3 = mp2 = mp;
        !           284:                else {
        !           285:                        mp2->m_next = mp;
        !           286:                        mp2 = mp;
        !           287:                }
        !           288:                if ((len+mp->m_len) > NFS_MAXPATHLEN) {
        !           289:                        mp->m_len = NFS_MAXPATHLEN-len;
        !           290:                        len = NFS_MAXPATHLEN;
        !           291:                } else
        !           292:                        len += mp->m_len;
        !           293:                ivp->iov_base = mtod(mp, caddr_t);
        !           294:                ivp->iov_len = mp->m_len;
        !           295:                i++;
        !           296:                ivp++;
        !           297:        }
        !           298:        uiop->uio_iov = iv;
        !           299:        uiop->uio_iovcnt = i;
        !           300:        uiop->uio_offset = 0;
        !           301:        uiop->uio_resid = len;
        !           302:        uiop->uio_rw = UIO_READ;
        !           303:        uiop->uio_segflg = UIO_SYSSPACE;
        !           304:        uiop->uio_procp = (struct proc *)0;
        !           305:        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred)) {
        !           306:                m_freem(mp3);
        !           307:                nfsm_reply(0);
        !           308:        }
        !           309:        if (vp->v_type != VLNK) {
        !           310:                error = EINVAL;
        !           311:                goto out;
        !           312:        }
        !           313:        error = VOP_READLINK(vp, uiop, cred);
        !           314: out:
        !           315:        vput(vp);
        !           316:        if (error)
        !           317:                m_freem(mp3);
        !           318:        nfsm_reply(NFSX_UNSIGNED);
        !           319:        if (uiop->uio_resid > 0) {
        !           320:                len -= uiop->uio_resid;
        !           321:                tlen = nfsm_rndup(len);
        !           322:                nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
        !           323:        }
        !           324:        nfsm_build(tl, u_long *, NFSX_UNSIGNED);
        !           325:        *tl = txdr_unsigned(len);
        !           326:        mb->m_next = mp3;
        !           327:        nfsm_srvdone;
        !           328: }
        !           329: 
        !           330: /*
        !           331:  * nfs read service
        !           332:  */
        !           333: nfsrv_read(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           334:        struct mbuf **mrq;
        !           335:        struct mbuf *mrep, *md;
        !           336:        caddr_t dpos;
        !           337:        struct ucred *cred;
        !           338:        u_long xid;
        !           339:        int *repstat;
        !           340:        struct proc *p;
        !           341: {
        !           342:        register struct iovec *iv;
        !           343:        struct iovec *iv2;
        !           344:        register struct mbuf *m;
        !           345:        register struct nfsv2_fattr *fp;
        !           346:        register u_long *tl;
        !           347:        register long t1;
        !           348:        caddr_t bpos;
        !           349:        int error = 0;
        !           350:        char *cp2;
        !           351:        struct mbuf *mb, *mb2, *mreq;
        !           352:        struct mbuf *m2, *m3;
        !           353:        struct vnode *vp;
        !           354:        nfsv2fh_t nfh;
        !           355:        fhandle_t *fhp;
        !           356:        struct uio io, *uiop = &io;
        !           357:        struct vattr va, *vap = &va;
        !           358:        int i, cnt, len, left, siz, tlen;
        !           359:        off_t off;
        !           360: 
        !           361:        fhp = &nfh.fh_generic;
        !           362:        nfsm_srvmtofh(fhp);
        !           363:        nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
        !           364:        off = fxdr_unsigned(off_t, *tl);
        !           365:        nfsm_srvstrsiz(cnt, NFS_MAXDATA);
        !           366:        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
        !           367:                nfsm_reply(0);
        !           368:        if (error = nfsrv_access(vp, VREAD | VEXEC, cred, p)) {
        !           369:                vput(vp);
        !           370:                nfsm_reply(0);
        !           371:        }
        !           372:        len = left = cnt;
        !           373:        /*
        !           374:         * Generate the mbuf list with the uio_iov ref. to it.
        !           375:         */
        !           376:        i = 0;
        !           377:        m3 = (struct mbuf *)0;
        !           378: #ifdef lint
        !           379:        m2 = (struct mbuf *)0;
        !           380: #endif /* lint */
        !           381:        MALLOC(iv, struct iovec *,
        !           382:               ((NFS_MAXDATA+MLEN-1)/MLEN) * sizeof (struct iovec), M_TEMP,
        !           383:               M_WAITOK);
        !           384:        iv2 = iv;
        !           385:        while (left > 0) {
        !           386:                MGET(m, M_WAIT, MT_DATA);
        !           387:                if (left > MINCLSIZE)
        !           388:                        MCLGET(m, M_WAIT);
        !           389:                m->m_len = 0;
        !           390:                siz = min(M_TRAILINGSPACE(m), left);
        !           391:                m->m_len = siz;
        !           392:                iv->iov_base = mtod(m, caddr_t);
        !           393:                iv->iov_len = siz;
        !           394:                iv++;
        !           395:                i++;
        !           396:                left -= siz;
        !           397:                if (m3) {
        !           398:                        m2->m_next = m;
        !           399:                        m2 = m;
        !           400:                } else
        !           401:                        m3 = m2 = m;
        !           402:        }
        !           403:        uiop->uio_iov = iv2;
        !           404:        uiop->uio_iovcnt = i;
        !           405:        uiop->uio_offset = off;
        !           406:        uiop->uio_resid = cnt;
        !           407:        uiop->uio_rw = UIO_READ;
        !           408:        uiop->uio_segflg = UIO_SYSSPACE;
        !           409:        uiop->uio_procp = (struct proc *)0;
        !           410:        error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
        !           411:        off = uiop->uio_offset;
        !           412:        FREE((caddr_t)iv2, M_TEMP);
        !           413:        if (error) {
        !           414:                m_freem(m3);
        !           415:                vput(vp);
        !           416:                nfsm_reply(0);
        !           417:        }
        !           418:        if (error = VOP_GETATTR(vp, vap, cred, p))
        !           419:                m_freem(m3);
        !           420:        vput(vp);
        !           421:        nfsm_reply(NFSX_FATTR+NFSX_UNSIGNED);
        !           422:        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        !           423:        nfsm_srvfillattr;
        !           424:        len -= uiop->uio_resid;
        !           425:        if (len > 0) {
        !           426:                tlen = nfsm_rndup(len);
        !           427:                if (cnt != tlen || tlen != len)
        !           428:                        nfsm_adj(m3, cnt-tlen, tlen-len);
        !           429:        } else {
        !           430:                m_freem(m3);
        !           431:                m3 = (struct mbuf *)0;
        !           432:        }
        !           433:        nfsm_build(tl, u_long *, NFSX_UNSIGNED);
        !           434:        *tl = txdr_unsigned(len);
        !           435:        mb->m_next = m3;
        !           436:        nfsm_srvdone;
        !           437: }
        !           438: 
        !           439: /*
        !           440:  * nfs write service
        !           441:  */
        !           442: nfsrv_write(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           443:        struct mbuf *mrep, *md, **mrq;
        !           444:        caddr_t dpos;
        !           445:        struct ucred *cred;
        !           446:        u_long xid;
        !           447:        int *repstat;
        !           448:        struct proc *p;
        !           449: {
        !           450:        register struct iovec *ivp;
        !           451:        register struct mbuf *mp;
        !           452:        register struct nfsv2_fattr *fp;
        !           453:        struct iovec iv[NFS_MAXIOVEC];
        !           454:        struct vattr va;
        !           455:        register struct vattr *vap = &va;
        !           456:        register u_long *tl;
        !           457:        register long t1;
        !           458:        caddr_t bpos;
        !           459:        int error = 0;
        !           460:        char *cp2;
        !           461:        struct mbuf *mb, *mb2, *mreq;
        !           462:        struct vnode *vp;
        !           463:        nfsv2fh_t nfh;
        !           464:        fhandle_t *fhp;
        !           465:        struct uio io, *uiop = &io;
        !           466:        off_t off;
        !           467:        long siz, len, xfer;
        !           468: 
        !           469:        fhp = &nfh.fh_generic;
        !           470:        nfsm_srvmtofh(fhp);
        !           471:        nfsm_disect(tl, u_long *, 4*NFSX_UNSIGNED);
        !           472:        off = fxdr_unsigned(off_t, *++tl);
        !           473:        tl += 2;
        !           474:        len = fxdr_unsigned(long, *tl);
        !           475:        if (len > NFS_MAXDATA || len <= 0) {
        !           476:                error = EBADRPC;
        !           477:                nfsm_reply(0);
        !           478:        }
        !           479:        if (dpos == (mtod(md, caddr_t)+md->m_len)) {
        !           480:                mp = md->m_next;
        !           481:                if (mp == NULL) {
        !           482:                        error = EBADRPC;
        !           483:                        nfsm_reply(0);
        !           484:                }
        !           485:        } else {
        !           486:                mp = md;
        !           487:                siz = dpos-mtod(mp, caddr_t);
        !           488:                mp->m_len -= siz;
        !           489:                NFSMADV(mp, siz);
        !           490:        }
        !           491:        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
        !           492:                nfsm_reply(0);
        !           493:        if (error = nfsrv_access(vp, VWRITE, cred, p)) {
        !           494:                vput(vp);
        !           495:                nfsm_reply(0);
        !           496:        }
        !           497:        uiop->uio_resid = 0;
        !           498:        uiop->uio_rw = UIO_WRITE;
        !           499:        uiop->uio_segflg = UIO_SYSSPACE;
        !           500:        uiop->uio_procp = (struct proc *)0;
        !           501:        /*
        !           502:         * Do up to NFS_MAXIOVEC mbufs of write each iteration of the
        !           503:         * loop until done.
        !           504:         */
        !           505:        while (len > 0 && uiop->uio_resid == 0) {
        !           506:                ivp = iv;
        !           507:                siz = 0;
        !           508:                uiop->uio_iov = ivp;
        !           509:                uiop->uio_iovcnt = 0;
        !           510:                uiop->uio_offset = off;
        !           511:                while (len > 0 && uiop->uio_iovcnt < NFS_MAXIOVEC && mp != NULL) {
        !           512:                        ivp->iov_base = mtod(mp, caddr_t);
        !           513:                        if (len < mp->m_len)
        !           514:                                ivp->iov_len = xfer = len;
        !           515:                        else
        !           516:                                ivp->iov_len = xfer = mp->m_len;
        !           517: #ifdef notdef
        !           518:                        /* Not Yet .. */
        !           519:                        if (M_HASCL(mp) && (((u_long)ivp->iov_base) & CLOFSET) == 0)
        !           520:                                ivp->iov_op = NULL;     /* what should it be ?? */
        !           521:                        else
        !           522:                                ivp->iov_op = NULL;
        !           523: #endif
        !           524:                        uiop->uio_iovcnt++;
        !           525:                        ivp++;
        !           526:                        len -= xfer;
        !           527:                        siz += xfer;
        !           528:                        mp = mp->m_next;
        !           529:                }
        !           530:                if (len > 0 && mp == NULL) {
        !           531:                        error = EBADRPC;
        !           532:                        vput(vp);
        !           533:                        nfsm_reply(0);
        !           534:                }
        !           535:                uiop->uio_resid = siz;
        !           536:                if (error = VOP_WRITE(vp, uiop, IO_SYNC | IO_NODELOCKED,
        !           537:                        cred)) {
        !           538:                        vput(vp);
        !           539:                        nfsm_reply(0);
        !           540:                }
        !           541:                off = uiop->uio_offset;
        !           542:        }
        !           543:        error = VOP_GETATTR(vp, vap, cred, p);
        !           544:        vput(vp);
        !           545:        nfsm_reply(NFSX_FATTR);
        !           546:        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        !           547:        nfsm_srvfillattr;
        !           548:        nfsm_srvdone;
        !           549: }
        !           550: 
        !           551: /*
        !           552:  * nfs create service
        !           553:  * now does a truncate to 0 length via. setattr if it already exists
        !           554:  */
        !           555: nfsrv_create(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           556:        struct mbuf *mrep, *md, **mrq;
        !           557:        caddr_t dpos;
        !           558:        struct ucred *cred;
        !           559:        u_long xid;
        !           560:        int *repstat;
        !           561:        struct proc *p;
        !           562: {
        !           563:        register struct nfsv2_fattr *fp;
        !           564:        struct vattr va;
        !           565:        register struct vattr *vap = &va;
        !           566:        struct nameidata nd;
        !           567:        register caddr_t cp;
        !           568:        register u_long *tl;
        !           569:        register long t1;
        !           570:        caddr_t bpos;
        !           571:        long rdev;
        !           572:        int error = 0;
        !           573:        char *cp2;
        !           574:        struct mbuf *mb, *mb2, *mreq;
        !           575:        struct vnode *vp;
        !           576:        nfsv2fh_t nfh;
        !           577:        fhandle_t *fhp;
        !           578:        long len;
        !           579: 
        !           580:        nd.ni_nameiop = 0;
        !           581:        fhp = &nfh.fh_generic;
        !           582:        nfsm_srvmtofh(fhp);
        !           583:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !           584:        nd.ni_cred = cred;
        !           585:        nd.ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF | SAVESTART;
        !           586:        if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
        !           587:                nfsm_reply(0);
        !           588:        VATTR_NULL(vap);
        !           589:        nfsm_disect(tl, u_long *, NFSX_SATTR);
        !           590:        /*
        !           591:         * Iff doesn't exist, create it
        !           592:         * otherwise just truncate to 0 length
        !           593:         *   should I set the mode too ??
        !           594:         */
        !           595:        if (nd.ni_vp == NULL) {
        !           596:                vap->va_type = IFTOVT(fxdr_unsigned(u_long, *tl));
        !           597:                if (vap->va_type == VNON)
        !           598:                        vap->va_type = VREG;
        !           599:                vap->va_mode = nfstov_mode(*tl);
        !           600:                rdev = fxdr_unsigned(long, *(tl+3));
        !           601:                if (vap->va_type == VREG || vap->va_type == VSOCK) {
        !           602:                        vrele(nd.ni_startdir);
        !           603:                        if (error = VOP_CREATE(&nd, vap, p))
        !           604:                                nfsm_reply(0);
        !           605:                        FREE(nd.ni_pnbuf, M_NAMEI);
        !           606:                } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
        !           607:                        vap->va_type == VFIFO) {
        !           608:                        if (vap->va_type == VCHR && rdev == 0xffffffff)
        !           609:                                vap->va_type = VFIFO;
        !           610:                        if (vap->va_type == VFIFO) {
        !           611: #ifndef FIFO
        !           612:                                VOP_ABORTOP(&nd);
        !           613:                                vput(nd.ni_dvp);
        !           614:                                error = ENXIO;
        !           615:                                goto out;
        !           616: #endif /* FIFO */
        !           617:                        } else if (error = suser(cred, (short *)0)) {
        !           618:                                VOP_ABORTOP(&nd);
        !           619:                                vput(nd.ni_dvp);
        !           620:                                goto out;
        !           621:                        } else
        !           622:                                vap->va_rdev = (dev_t)rdev;
        !           623:                        if (error = VOP_MKNOD(&nd, vap, cred, p)) {
        !           624:                                vrele(nd.ni_startdir);
        !           625:                                nfsm_reply(0);
        !           626:                        }
        !           627:                        nd.ni_nameiop &= ~(OPMASK | LOCKPARENT | SAVESTART);
        !           628:                        nd.ni_nameiop |= LOOKUP;
        !           629:                        if (error = lookup(&nd, p)) {
        !           630:                                free(nd.ni_pnbuf, M_NAMEI);
        !           631:                                nfsm_reply(0);
        !           632:                        }
        !           633:                        FREE(nd.ni_pnbuf, M_NAMEI);
        !           634:                        if (nd.ni_more) {
        !           635:                                vrele(nd.ni_dvp);
        !           636:                                vput(nd.ni_vp);
        !           637:                                VOP_ABORTOP(&nd);
        !           638:                                error = EINVAL;
        !           639:                                nfsm_reply(0);
        !           640:                        }
        !           641:                } else {
        !           642:                        VOP_ABORTOP(&nd);
        !           643:                        vput(nd.ni_dvp);
        !           644:                        error = ENXIO;
        !           645:                        goto out;
        !           646:                }
        !           647:                vp = nd.ni_vp;
        !           648:        } else {
        !           649:                vrele(nd.ni_startdir);
        !           650:                free(nd.ni_pnbuf, M_NAMEI);
        !           651:                vp = nd.ni_vp;
        !           652:                if (nd.ni_dvp == vp)
        !           653:                        vrele(nd.ni_dvp);
        !           654:                else
        !           655:                        vput(nd.ni_dvp);
        !           656:                VOP_ABORTOP(&nd);
        !           657:                vap->va_size = 0;
        !           658:                if (error = VOP_SETATTR(vp, vap, cred, p)) {
        !           659:                        vput(vp);
        !           660:                        nfsm_reply(0);
        !           661:                }
        !           662:        }
        !           663:        bzero((caddr_t)fhp, sizeof(nfh));
        !           664:        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        !           665:        if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
        !           666:                vput(vp);
        !           667:                nfsm_reply(0);
        !           668:        }
        !           669:        error = VOP_GETATTR(vp, vap, cred, p);
        !           670:        vput(vp);
        !           671:        nfsm_reply(NFSX_FH+NFSX_FATTR);
        !           672:        nfsm_srvfhtom(fhp);
        !           673:        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        !           674:        nfsm_srvfillattr;
        !           675:        return (error);
        !           676: nfsmout:
        !           677:        if (nd.ni_nameiop)
        !           678:                vrele(nd.ni_startdir);
        !           679:        VOP_ABORTOP(&nd);
        !           680:        if (nd.ni_dvp == nd.ni_vp)
        !           681:                vrele(nd.ni_dvp);
        !           682:        else
        !           683:                vput(nd.ni_dvp);
        !           684:        if (nd.ni_vp)
        !           685:                vput(nd.ni_vp);
        !           686:        return (error);
        !           687: 
        !           688: out:
        !           689:        vrele(nd.ni_startdir);
        !           690:        free(nd.ni_pnbuf, M_NAMEI);
        !           691:        nfsm_reply(0);
        !           692: }
        !           693: 
        !           694: /*
        !           695:  * nfs remove service
        !           696:  */
        !           697: nfsrv_remove(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           698:        struct mbuf *mrep, *md, **mrq;
        !           699:        caddr_t dpos;
        !           700:        struct ucred *cred;
        !           701:        u_long xid;
        !           702:        int *repstat;
        !           703:        struct proc *p;
        !           704: {
        !           705:        struct nameidata nd;
        !           706:        register u_long *tl;
        !           707:        register long t1;
        !           708:        caddr_t bpos;
        !           709:        int error = 0;
        !           710:        char *cp2;
        !           711:        struct mbuf *mb, *mreq;
        !           712:        struct vnode *vp;
        !           713:        nfsv2fh_t nfh;
        !           714:        fhandle_t *fhp;
        !           715:        long len;
        !           716: 
        !           717:        fhp = &nfh.fh_generic;
        !           718:        nfsm_srvmtofh(fhp);
        !           719:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !           720:        nd.ni_cred = cred;
        !           721:        nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
        !           722:        if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
        !           723:                nfsm_reply(0);
        !           724:        vp = nd.ni_vp;
        !           725:        if (vp->v_type == VDIR &&
        !           726:                (error = suser(cred, (short *)0)))
        !           727:                goto out;
        !           728:        /*
        !           729:         * The root of a mounted filesystem cannot be deleted.
        !           730:         */
        !           731:        if (vp->v_flag & VROOT) {
        !           732:                error = EBUSY;
        !           733:                goto out;
        !           734:        }
        !           735:        if (vp->v_flag & VTEXT)
        !           736:                (void) vnode_pager_uncache(vp);
        !           737: out:
        !           738:        if (!error) {
        !           739:                error = VOP_REMOVE(&nd, p);
        !           740:        } else {
        !           741:                VOP_ABORTOP(&nd);
        !           742:                if (nd.ni_dvp == vp)
        !           743:                        vrele(nd.ni_dvp);
        !           744:                else
        !           745:                        vput(nd.ni_dvp);
        !           746:                vput(vp);
        !           747:        }
        !           748:        nfsm_reply(0);
        !           749:        nfsm_srvdone;
        !           750: }
        !           751: 
        !           752: /*
        !           753:  * nfs rename service
        !           754:  */
        !           755: nfsrv_rename(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           756:        struct mbuf *mrep, *md, **mrq;
        !           757:        caddr_t dpos;
        !           758:        struct ucred *cred;
        !           759:        u_long xid;
        !           760:        int *repstat;
        !           761:        struct proc *p;
        !           762: {
        !           763:        register u_long *tl;
        !           764:        register long t1;
        !           765:        caddr_t bpos;
        !           766:        int error = 0;
        !           767:        char *cp2;
        !           768:        struct mbuf *mb, *mreq;
        !           769:        struct nameidata fromnd, tond;
        !           770:        struct vnode *fvp, *tvp, *tdvp;
        !           771:        nfsv2fh_t fnfh, tnfh;
        !           772:        fhandle_t *ffhp, *tfhp;
        !           773:        long len, len2;
        !           774:        int rootflg = 0;
        !           775: 
        !           776:        ffhp = &fnfh.fh_generic;
        !           777:        tfhp = &tnfh.fh_generic;
        !           778:        fromnd.ni_nameiop = 0;
        !           779:        tond.ni_nameiop = 0;
        !           780:        nfsm_srvmtofh(ffhp);
        !           781:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !           782:        /*
        !           783:         * Remember if we are root so that we can reset cr_uid before
        !           784:         * the second nfs_namei() call
        !           785:         */
        !           786:        if (cred->cr_uid == 0)
        !           787:                rootflg++;
        !           788:        fromnd.ni_cred = cred;
        !           789:        fromnd.ni_nameiop = DELETE | WANTPARENT | SAVESTART;
        !           790:        if (error = nfs_namei(&fromnd, ffhp, len, &md, &dpos, p))
        !           791:                nfsm_reply(0);
        !           792:        fvp = fromnd.ni_vp;
        !           793:        nfsm_srvmtofh(tfhp);
        !           794:        nfsm_strsiz(len2, NFS_MAXNAMLEN);
        !           795:        if (rootflg)
        !           796:                cred->cr_uid = 0;
        !           797:        tond.ni_cred = cred;
        !           798:        tond.ni_nameiop = RENAME | LOCKPARENT | LOCKLEAF | NOCACHE
        !           799:                | SAVESTART;
        !           800:        if (error = nfs_namei(&tond, tfhp, len2, &md, &dpos, p)) {
        !           801:                VOP_ABORTOP(&fromnd);
        !           802:                vrele(fromnd.ni_dvp);
        !           803:                vrele(fvp);
        !           804:                goto out1;
        !           805:        }
        !           806:        tdvp = tond.ni_dvp;
        !           807:        tvp = tond.ni_vp;
        !           808:        if (tvp != NULL) {
        !           809:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
        !           810:                        error = EISDIR;
        !           811:                        goto out;
        !           812:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
        !           813:                        error = ENOTDIR;
        !           814:                        goto out;
        !           815:                }
        !           816:        }
        !           817:        if (fvp->v_mount != tdvp->v_mount) {
        !           818:                error = EXDEV;
        !           819:                goto out;
        !           820:        }
        !           821:        if (fvp == tdvp)
        !           822:                error = EINVAL;
        !           823:        /*
        !           824:         * If source is the same as the destination (that is the
        !           825:         * same vnode with the same name in the same directory),
        !           826:         * then there is nothing to do.
        !           827:         */
        !           828:        if (fvp == tvp && fromnd.ni_dvp == tdvp &&
        !           829:            fromnd.ni_namelen == tond.ni_namelen &&
        !           830:            !bcmp(fromnd.ni_ptr, tond.ni_ptr, fromnd.ni_namelen))
        !           831:                error = -1;
        !           832: out:
        !           833:        if (!error) {
        !           834:                error = VOP_RENAME(&fromnd, &tond, p);
        !           835:        } else {
        !           836:                VOP_ABORTOP(&tond);
        !           837:                if (tdvp == tvp)
        !           838:                        vrele(tdvp);
        !           839:                else
        !           840:                        vput(tdvp);
        !           841:                if (tvp)
        !           842:                        vput(tvp);
        !           843:                VOP_ABORTOP(&fromnd);
        !           844:                vrele(fromnd.ni_dvp);
        !           845:                vrele(fvp);
        !           846:        }
        !           847:        vrele(tond.ni_startdir);
        !           848:        FREE(tond.ni_pnbuf, M_NAMEI);
        !           849: out1:
        !           850:        vrele(fromnd.ni_startdir);
        !           851:        FREE(fromnd.ni_pnbuf, M_NAMEI);
        !           852:        nfsm_reply(0);
        !           853:        return (error);
        !           854: 
        !           855: nfsmout:
        !           856:        if (tond.ni_nameiop) {
        !           857:                vrele(tond.ni_startdir);
        !           858:                FREE(tond.ni_pnbuf, M_NAMEI);
        !           859:        }
        !           860:        if (fromnd.ni_nameiop) {
        !           861:                vrele(fromnd.ni_startdir);
        !           862:                FREE(fromnd.ni_pnbuf, M_NAMEI);
        !           863:                VOP_ABORTOP(&fromnd);
        !           864:                vrele(fromnd.ni_dvp);
        !           865:                vrele(fvp);
        !           866:        }
        !           867:        return (error);
        !           868: }
        !           869: 
        !           870: /*
        !           871:  * nfs link service
        !           872:  */
        !           873: nfsrv_link(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           874:        struct mbuf *mrep, *md, **mrq;
        !           875:        caddr_t dpos;
        !           876:        struct ucred *cred;
        !           877:        u_long xid;
        !           878:        int *repstat;
        !           879:        struct proc *p;
        !           880: {
        !           881:        struct nameidata nd;
        !           882:        register u_long *tl;
        !           883:        register long t1;
        !           884:        caddr_t bpos;
        !           885:        int error = 0;
        !           886:        char *cp2;
        !           887:        struct mbuf *mb, *mreq;
        !           888:        struct vnode *vp, *xp;
        !           889:        nfsv2fh_t nfh, dnfh;
        !           890:        fhandle_t *fhp, *dfhp;
        !           891:        long len;
        !           892: 
        !           893:        fhp = &nfh.fh_generic;
        !           894:        dfhp = &dnfh.fh_generic;
        !           895:        nfsm_srvmtofh(fhp);
        !           896:        nfsm_srvmtofh(dfhp);
        !           897:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !           898:        if (error = nfsrv_fhtovp(fhp, FALSE, &vp, cred))
        !           899:                nfsm_reply(0);
        !           900:        if (vp->v_type == VDIR && (error = suser(cred, NULL)))
        !           901:                goto out1;
        !           902:        nd.ni_cred = cred;
        !           903:        nd.ni_nameiop = CREATE | LOCKPARENT;
        !           904:        if (error = nfs_namei(&nd, dfhp, len, &md, &dpos, p))
        !           905:                goto out1;
        !           906:        xp = nd.ni_vp;
        !           907:        if (xp != NULL) {
        !           908:                error = EEXIST;
        !           909:                goto out;
        !           910:        }
        !           911:        xp = nd.ni_dvp;
        !           912:        if (vp->v_mount != xp->v_mount)
        !           913:                error = EXDEV;
        !           914: out:
        !           915:        if (!error) {
        !           916:                error = VOP_LINK(vp, &nd, p);
        !           917:        } else {
        !           918:                VOP_ABORTOP(&nd);
        !           919:                if (nd.ni_dvp == nd.ni_vp)
        !           920:                        vrele(nd.ni_dvp);
        !           921:                else
        !           922:                        vput(nd.ni_dvp);
        !           923:                if (nd.ni_vp)
        !           924:                        vrele(nd.ni_vp);
        !           925:        }
        !           926: out1:
        !           927:        vrele(vp);
        !           928:        nfsm_reply(0);
        !           929:        nfsm_srvdone;
        !           930: }
        !           931: 
        !           932: /*
        !           933:  * nfs symbolic link service
        !           934:  */
        !           935: nfsrv_symlink(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !           936:        struct mbuf *mrep, *md, **mrq;
        !           937:        caddr_t dpos;
        !           938:        struct ucred *cred;
        !           939:        u_long xid;
        !           940:        int *repstat;
        !           941:        struct proc *p;
        !           942: {
        !           943:        struct vattr va;
        !           944:        struct nameidata nd;
        !           945:        register struct vattr *vap = &va;
        !           946:        register u_long *tl;
        !           947:        register long t1;
        !           948:        struct nfsv2_sattr *sp;
        !           949:        caddr_t bpos;
        !           950:        struct uio io;
        !           951:        struct iovec iv;
        !           952:        int error = 0;
        !           953:        char *pathcp, *cp2;
        !           954:        struct mbuf *mb, *mreq;
        !           955:        nfsv2fh_t nfh;
        !           956:        fhandle_t *fhp;
        !           957:        long len, len2;
        !           958: 
        !           959:        pathcp = (char *)0;
        !           960:        fhp = &nfh.fh_generic;
        !           961:        nfsm_srvmtofh(fhp);
        !           962:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !           963:        nd.ni_cred = cred;
        !           964:        nd.ni_nameiop = CREATE | LOCKPARENT;
        !           965:        if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
        !           966:                goto out;
        !           967:        nfsm_strsiz(len2, NFS_MAXPATHLEN);
        !           968:        MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
        !           969:        iv.iov_base = pathcp;
        !           970:        iv.iov_len = len2;
        !           971:        io.uio_resid = len2;
        !           972:        io.uio_offset = 0;
        !           973:        io.uio_iov = &iv;
        !           974:        io.uio_iovcnt = 1;
        !           975:        io.uio_segflg = UIO_SYSSPACE;
        !           976:        io.uio_rw = UIO_READ;
        !           977:        io.uio_procp = (struct proc *)0;
        !           978:        nfsm_mtouio(&io, len2);
        !           979:        nfsm_disect(sp, struct nfsv2_sattr *, NFSX_SATTR);
        !           980:        *(pathcp + len2) = '\0';
        !           981:        if (nd.ni_vp) {
        !           982:                VOP_ABORTOP(&nd);
        !           983:                if (nd.ni_dvp == nd.ni_vp)
        !           984:                        vrele(nd.ni_dvp);
        !           985:                else
        !           986:                        vput(nd.ni_dvp);
        !           987:                vrele(nd.ni_vp);
        !           988:                error = EEXIST;
        !           989:                goto out;
        !           990:        }
        !           991:        VATTR_NULL(vap);
        !           992:        vap->va_mode = fxdr_unsigned(u_short, sp->sa_mode);
        !           993:        error = VOP_SYMLINK(&nd, vap, pathcp, p);
        !           994: out:
        !           995:        if (pathcp)
        !           996:                FREE(pathcp, M_TEMP);
        !           997:        nfsm_reply(0);
        !           998:        return (error);
        !           999: nfsmout:
        !          1000:        VOP_ABORTOP(&nd);
        !          1001:        if (nd.ni_dvp == nd.ni_vp)
        !          1002:                vrele(nd.ni_dvp);
        !          1003:        else
        !          1004:                vput(nd.ni_dvp);
        !          1005:        if (nd.ni_vp)
        !          1006:                vrele(nd.ni_vp);
        !          1007:        if (pathcp)
        !          1008:                FREE(pathcp, M_TEMP);
        !          1009:        return (error);
        !          1010: }
        !          1011: 
        !          1012: /*
        !          1013:  * nfs mkdir service
        !          1014:  */
        !          1015: nfsrv_mkdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !          1016:        struct mbuf *mrep, *md, **mrq;
        !          1017:        caddr_t dpos;
        !          1018:        struct ucred *cred;
        !          1019:        u_long xid;
        !          1020:        int *repstat;
        !          1021:        struct proc *p;
        !          1022: {
        !          1023:        struct vattr va;
        !          1024:        register struct vattr *vap = &va;
        !          1025:        register struct nfsv2_fattr *fp;
        !          1026:        struct nameidata nd;
        !          1027:        register caddr_t cp;
        !          1028:        register u_long *tl;
        !          1029:        register long t1;
        !          1030:        caddr_t bpos;
        !          1031:        int error = 0;
        !          1032:        char *cp2;
        !          1033:        struct mbuf *mb, *mb2, *mreq;
        !          1034:        struct vnode *vp;
        !          1035:        nfsv2fh_t nfh;
        !          1036:        fhandle_t *fhp;
        !          1037:        long len;
        !          1038: 
        !          1039:        fhp = &nfh.fh_generic;
        !          1040:        nfsm_srvmtofh(fhp);
        !          1041:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !          1042:        nd.ni_cred = cred;
        !          1043:        nd.ni_nameiop = CREATE | LOCKPARENT;
        !          1044:        if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
        !          1045:                nfsm_reply(0);
        !          1046:        nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
        !          1047:        VATTR_NULL(vap);
        !          1048:        vap->va_type = VDIR;
        !          1049:        vap->va_mode = nfstov_mode(*tl++);
        !          1050:        vp = nd.ni_vp;
        !          1051:        if (vp != NULL) {
        !          1052:                VOP_ABORTOP(&nd);
        !          1053:                if (nd.ni_dvp == vp)
        !          1054:                        vrele(nd.ni_dvp);
        !          1055:                else
        !          1056:                        vput(nd.ni_dvp);
        !          1057:                vrele(vp);
        !          1058:                error = EEXIST;
        !          1059:                nfsm_reply(0);
        !          1060:        }
        !          1061:        if (error = VOP_MKDIR(&nd, vap, p))
        !          1062:                nfsm_reply(0);
        !          1063:        vp = nd.ni_vp;
        !          1064:        bzero((caddr_t)fhp, sizeof(nfh));
        !          1065:        fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
        !          1066:        if (error = VFS_VPTOFH(vp, &fhp->fh_fid)) {
        !          1067:                vput(vp);
        !          1068:                nfsm_reply(0);
        !          1069:        }
        !          1070:        error = VOP_GETATTR(vp, vap, cred, p);
        !          1071:        vput(vp);
        !          1072:        nfsm_reply(NFSX_FH+NFSX_FATTR);
        !          1073:        nfsm_srvfhtom(fhp);
        !          1074:        nfsm_build(fp, struct nfsv2_fattr *, NFSX_FATTR);
        !          1075:        nfsm_srvfillattr;
        !          1076:        return (error);
        !          1077: nfsmout:
        !          1078:        VOP_ABORTOP(&nd);
        !          1079:        if (nd.ni_dvp == nd.ni_vp)
        !          1080:                vrele(nd.ni_dvp);
        !          1081:        else
        !          1082:                vput(nd.ni_dvp);
        !          1083:        if (nd.ni_vp)
        !          1084:                vrele(nd.ni_vp);
        !          1085:        return (error);
        !          1086: }
        !          1087: 
        !          1088: /*
        !          1089:  * nfs rmdir service
        !          1090:  */
        !          1091: nfsrv_rmdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !          1092:        struct mbuf *mrep, *md, **mrq;
        !          1093:        caddr_t dpos;
        !          1094:        struct ucred *cred;
        !          1095:        u_long xid;
        !          1096:        int *repstat;
        !          1097:        struct proc *p;
        !          1098: {
        !          1099:        register u_long *tl;
        !          1100:        register long t1;
        !          1101:        caddr_t bpos;
        !          1102:        int error = 0;
        !          1103:        char *cp2;
        !          1104:        struct mbuf *mb, *mreq;
        !          1105:        struct vnode *vp;
        !          1106:        nfsv2fh_t nfh;
        !          1107:        fhandle_t *fhp;
        !          1108:        long len;
        !          1109:        struct nameidata nd;
        !          1110: 
        !          1111:        fhp = &nfh.fh_generic;
        !          1112:        nfsm_srvmtofh(fhp);
        !          1113:        nfsm_srvstrsiz(len, NFS_MAXNAMLEN);
        !          1114:        nd.ni_cred = cred;
        !          1115:        nd.ni_nameiop = DELETE | LOCKPARENT | LOCKLEAF;
        !          1116:        if (error = nfs_namei(&nd, fhp, len, &md, &dpos, p))
        !          1117:                nfsm_reply(0);
        !          1118:        vp = nd.ni_vp;
        !          1119:        if (vp->v_type != VDIR) {
        !          1120:                error = ENOTDIR;
        !          1121:                goto out;
        !          1122:        }
        !          1123:        /*
        !          1124:         * No rmdir "." please.
        !          1125:         */
        !          1126:        if (nd.ni_dvp == vp) {
        !          1127:                error = EINVAL;
        !          1128:                goto out;
        !          1129:        }
        !          1130:        /*
        !          1131:         * The root of a mounted filesystem cannot be deleted.
        !          1132:         */
        !          1133:        if (vp->v_flag & VROOT)
        !          1134:                error = EBUSY;
        !          1135: out:
        !          1136:        if (!error) {
        !          1137:                error = VOP_RMDIR(&nd, p);
        !          1138:        } else {
        !          1139:                VOP_ABORTOP(&nd);
        !          1140:                if (nd.ni_dvp == nd.ni_vp)
        !          1141:                        vrele(nd.ni_dvp);
        !          1142:                else
        !          1143:                        vput(nd.ni_dvp);
        !          1144:                vput(vp);
        !          1145:        }
        !          1146:        nfsm_reply(0);
        !          1147:        nfsm_srvdone;
        !          1148: }
        !          1149: 
        !          1150: /*
        !          1151:  * nfs readdir service
        !          1152:  * - mallocs what it thinks is enough to read
        !          1153:  *     count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
        !          1154:  * - calls VOP_READDIR()
        !          1155:  * - loops around building the reply
        !          1156:  *     if the output generated exceeds count break out of loop
        !          1157:  *     The nfsm_clget macro is used here so that the reply will be packed
        !          1158:  *     tightly in mbuf clusters.
        !          1159:  * - it only knows that it has encountered eof when the VOP_READDIR()
        !          1160:  *     reads nothing
        !          1161:  * - as such one readdir rpc will return eof false although you are there
        !          1162:  *     and then the next will return eof
        !          1163:  * - it trims out records with d_ino == 0
        !          1164:  *     this doesn't matter for Unix clients, but they might confuse clients
        !          1165:  *     for other os'.
        !          1166:  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
        !          1167:  *     than requested, but this may not apply to all filesystems. For
        !          1168:  *     example, client NFS does not { although it is never remote mounted
        !          1169:  *     anyhow }
        !          1170:  * PS: The NFS protocol spec. does not clarify what the "count" byte
        !          1171:  *     argument is a count of.. just name strings and file id's or the
        !          1172:  *     entire reply rpc or ...
        !          1173:  *     I tried just file name and id sizes and it confused the Sun client,
        !          1174:  *     so I am using the full rpc size now. The "paranoia.." comment refers
        !          1175:  *     to including the status longwords that are not a part of the dir.
        !          1176:  *     "entry" structures, but are in the rpc.
        !          1177:  */
        !          1178: nfsrv_readdir(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !          1179:        struct mbuf **mrq;
        !          1180:        struct mbuf *mrep, *md;
        !          1181:        caddr_t dpos;
        !          1182:        struct ucred *cred;
        !          1183:        u_long xid;
        !          1184:        int *repstat;
        !          1185:        struct proc *p;
        !          1186: {
        !          1187:        register char *bp, *be;
        !          1188:        register struct mbuf *mp;
        !          1189:        register struct direct *dp;
        !          1190:        register caddr_t cp;
        !          1191:        register u_long *tl;
        !          1192:        register long t1;
        !          1193:        caddr_t bpos;
        !          1194:        int error = 0;
        !          1195:        char *cp2;
        !          1196:        struct mbuf *mb, *mb2, *mreq;
        !          1197:        char *cpos, *cend;
        !          1198:        int len, nlen, rem, xfer, tsiz, i;
        !          1199:        struct vnode *vp;
        !          1200:        struct mbuf *mp2, *mp3;
        !          1201:        nfsv2fh_t nfh;
        !          1202:        fhandle_t *fhp;
        !          1203:        struct uio io;
        !          1204:        struct iovec iv;
        !          1205:        int siz, cnt, fullsiz, eofflag;
        !          1206:        u_long on;
        !          1207:        char *rbuf;
        !          1208:        off_t off, toff;
        !          1209: 
        !          1210:        fhp = &nfh.fh_generic;
        !          1211:        nfsm_srvmtofh(fhp);
        !          1212:        nfsm_disect(tl, u_long *, 2*NFSX_UNSIGNED);
        !          1213:        toff = fxdr_unsigned(off_t, *tl++);
        !          1214:        off = (toff & ~(NFS_DIRBLKSIZ-1));
        !          1215:        on = (toff & (NFS_DIRBLKSIZ-1));
        !          1216:        cnt = fxdr_unsigned(int, *tl);
        !          1217:        siz = ((cnt+NFS_DIRBLKSIZ-1) & ~(NFS_DIRBLKSIZ-1));
        !          1218:        if (cnt > NFS_MAXREADDIR)
        !          1219:                siz = NFS_MAXREADDIR;
        !          1220:        fullsiz = siz;
        !          1221:        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
        !          1222:                nfsm_reply(0);
        !          1223:        if (error = nfsrv_access(vp, VEXEC, cred, p)) {
        !          1224:                vput(vp);
        !          1225:                nfsm_reply(0);
        !          1226:        }
        !          1227:        VOP_UNLOCK(vp);
        !          1228:        MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
        !          1229: again:
        !          1230:        iv.iov_base = rbuf;
        !          1231:        iv.iov_len = fullsiz;
        !          1232:        io.uio_iov = &iv;
        !          1233:        io.uio_iovcnt = 1;
        !          1234:        io.uio_offset = off;
        !          1235:        io.uio_resid = fullsiz;
        !          1236:        io.uio_segflg = UIO_SYSSPACE;
        !          1237:        io.uio_rw = UIO_READ;
        !          1238:        io.uio_procp = (struct proc *)0;
        !          1239:        error = VOP_READDIR(vp, &io, cred, &eofflag);
        !          1240:        off = io.uio_offset;
        !          1241:        if (error) {
        !          1242:                vrele(vp);
        !          1243:                free((caddr_t)rbuf, M_TEMP);
        !          1244:                nfsm_reply(0);
        !          1245:        }
        !          1246:        if (io.uio_resid) {
        !          1247:                siz -= io.uio_resid;
        !          1248: 
        !          1249:                /*
        !          1250:                 * If nothing read, return eof
        !          1251:                 * rpc reply
        !          1252:                 */
        !          1253:                if (siz == 0) {
        !          1254:                        vrele(vp);
        !          1255:                        nfsm_reply(2*NFSX_UNSIGNED);
        !          1256:                        nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
        !          1257:                        *tl++ = nfs_false;
        !          1258:                        *tl = nfs_true;
        !          1259:                        FREE((caddr_t)rbuf, M_TEMP);
        !          1260:                        return (0);
        !          1261:                }
        !          1262:        }
        !          1263: 
        !          1264:        /*
        !          1265:         * Check for degenerate cases of nothing useful read.
        !          1266:         * If so go try again
        !          1267:         */
        !          1268:        cpos = rbuf + on;
        !          1269:        cend = rbuf + siz;
        !          1270:        dp = (struct direct *)cpos;
        !          1271:        while (cpos < cend && dp->d_ino == 0) {
        !          1272:                cpos += dp->d_reclen;
        !          1273:                dp = (struct direct *)cpos;
        !          1274:        }
        !          1275:        if (cpos >= cend) {
        !          1276:                toff = off;
        !          1277:                siz = fullsiz;
        !          1278:                on = 0;
        !          1279:                goto again;
        !          1280:        }
        !          1281: 
        !          1282:        cpos = rbuf + on;
        !          1283:        cend = rbuf + siz;
        !          1284:        dp = (struct direct *)cpos;
        !          1285:        vrele(vp);
        !          1286:        len = 3*NFSX_UNSIGNED;  /* paranoia, probably can be 0 */
        !          1287:        bp = be = (caddr_t)0;
        !          1288:        mp3 = (struct mbuf *)0;
        !          1289:        nfsm_reply(siz);
        !          1290: 
        !          1291:        /* Loop through the records and build reply */
        !          1292:        while (cpos < cend) {
        !          1293:                if (dp->d_ino != 0) {
        !          1294:                        nlen = dp->d_namlen;
        !          1295:                        rem = nfsm_rndup(nlen)-nlen;
        !          1296:        
        !          1297:                        /*
        !          1298:                         * As noted above, the NFS spec. is not clear about what
        !          1299:                         * should be included in "count" as totalled up here in
        !          1300:                         * "len".
        !          1301:                         */
        !          1302:                        len += (4*NFSX_UNSIGNED+nlen+rem);
        !          1303:                        if (len > cnt) {
        !          1304:                                eofflag = 0;
        !          1305:                                break;
        !          1306:                        }
        !          1307:        
        !          1308:                        /* Build the directory record xdr from the direct entry */
        !          1309:                        nfsm_clget;
        !          1310:                        *tl = nfs_true;
        !          1311:                        bp += NFSX_UNSIGNED;
        !          1312:                        nfsm_clget;
        !          1313:                        *tl = txdr_unsigned(dp->d_ino);
        !          1314:                        bp += NFSX_UNSIGNED;
        !          1315:                        nfsm_clget;
        !          1316:                        *tl = txdr_unsigned(nlen);
        !          1317:                        bp += NFSX_UNSIGNED;
        !          1318:        
        !          1319:                        /* And loop arround copying the name */
        !          1320:                        xfer = nlen;
        !          1321:                        cp = dp->d_name;
        !          1322:                        while (xfer > 0) {
        !          1323:                                nfsm_clget;
        !          1324:                                if ((bp+xfer) > be)
        !          1325:                                        tsiz = be-bp;
        !          1326:                                else
        !          1327:                                        tsiz = xfer;
        !          1328:                                bcopy(cp, bp, tsiz);
        !          1329:                                bp += tsiz;
        !          1330:                                xfer -= tsiz;
        !          1331:                                if (xfer > 0)
        !          1332:                                        cp += tsiz;
        !          1333:                        }
        !          1334:                        /* And null pad to a long boundary */
        !          1335:                        for (i = 0; i < rem; i++)
        !          1336:                                *bp++ = '\0';
        !          1337:                        nfsm_clget;
        !          1338:        
        !          1339:                        /* Finish off the record */
        !          1340:                        toff += dp->d_reclen;
        !          1341:                        *tl = txdr_unsigned(toff);
        !          1342:                        bp += NFSX_UNSIGNED;
        !          1343:                } else
        !          1344:                        toff += dp->d_reclen;
        !          1345:                cpos += dp->d_reclen;
        !          1346:                dp = (struct direct *)cpos;
        !          1347:        }
        !          1348:        nfsm_clget;
        !          1349:        *tl = nfs_false;
        !          1350:        bp += NFSX_UNSIGNED;
        !          1351:        nfsm_clget;
        !          1352:        if (eofflag)
        !          1353:                *tl = nfs_true;
        !          1354:        else
        !          1355:                *tl = nfs_false;
        !          1356:        bp += NFSX_UNSIGNED;
        !          1357:        if (bp < be)
        !          1358:                mp->m_len = bp-mtod(mp, caddr_t);
        !          1359:        mb->m_next = mp3;
        !          1360:        FREE(rbuf, M_TEMP);
        !          1361:        nfsm_srvdone;
        !          1362: }
        !          1363: 
        !          1364: /*
        !          1365:  * nfs statfs service
        !          1366:  */
        !          1367: nfsrv_statfs(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !          1368:        struct mbuf **mrq;
        !          1369:        struct mbuf *mrep, *md;
        !          1370:        caddr_t dpos;
        !          1371:        struct ucred *cred;
        !          1372:        u_long xid;
        !          1373:        int *repstat;
        !          1374:        struct proc *p;
        !          1375: {
        !          1376:        register struct statfs *sf;
        !          1377:        register struct nfsv2_statfs *sfp;
        !          1378:        register u_long *tl;
        !          1379:        register long t1;
        !          1380:        caddr_t bpos;
        !          1381:        int error = 0;
        !          1382:        char *cp2;
        !          1383:        struct mbuf *mb, *mb2, *mreq;
        !          1384:        struct vnode *vp;
        !          1385:        nfsv2fh_t nfh;
        !          1386:        fhandle_t *fhp;
        !          1387:        struct statfs statfs;
        !          1388: 
        !          1389:        fhp = &nfh.fh_generic;
        !          1390:        nfsm_srvmtofh(fhp);
        !          1391:        if (error = nfsrv_fhtovp(fhp, TRUE, &vp, cred))
        !          1392:                nfsm_reply(0);
        !          1393:        sf = &statfs;
        !          1394:        error = VFS_STATFS(vp->v_mount, sf, p);
        !          1395:        vput(vp);
        !          1396:        nfsm_reply(NFSX_STATFS);
        !          1397:        nfsm_build(sfp, struct nfsv2_statfs *, NFSX_STATFS);
        !          1398:        sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
        !          1399:        sfp->sf_bsize = txdr_unsigned(sf->f_fsize);
        !          1400:        sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
        !          1401:        sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
        !          1402:        sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
        !          1403:        nfsm_srvdone;
        !          1404: }
        !          1405: 
        !          1406: /*
        !          1407:  * Null operation, used by clients to ping server
        !          1408:  */
        !          1409: /* ARGSUSED */
        !          1410: nfsrv_null(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !          1411:        struct mbuf **mrq;
        !          1412:        struct mbuf *mrep, *md;
        !          1413:        caddr_t dpos;
        !          1414:        struct ucred *cred;
        !          1415:        u_long xid;
        !          1416:        int *repstat;
        !          1417:        struct proc *p;
        !          1418: {
        !          1419:        caddr_t bpos;
        !          1420:        int error = 0;
        !          1421:        struct mbuf *mb, *mreq;
        !          1422: 
        !          1423:        error = VNOVAL;
        !          1424:        nfsm_reply(0);
        !          1425:        return (error);
        !          1426: }
        !          1427: 
        !          1428: /*
        !          1429:  * No operation, used for obsolete procedures
        !          1430:  */
        !          1431: /* ARGSUSED */
        !          1432: nfsrv_noop(mrep, md, dpos, cred, xid, mrq, repstat, p)
        !          1433:        struct mbuf **mrq;
        !          1434:        struct mbuf *mrep, *md;
        !          1435:        caddr_t dpos;
        !          1436:        struct ucred *cred;
        !          1437:        u_long xid;
        !          1438:        int *repstat;
        !          1439:        struct proc *p;
        !          1440: {
        !          1441:        caddr_t bpos;
        !          1442:        int error = 0;
        !          1443:        struct mbuf *mb, *mreq;
        !          1444: 
        !          1445:        error = EPROCUNAVAIL;
        !          1446:        nfsm_reply(0);
        !          1447:        return (error);
        !          1448: }
        !          1449: 
        !          1450: /*
        !          1451:  * Perform access checking for vnodes obtained from file handles that would
        !          1452:  * refer to files already opened by a Unix client. You cannot just use
        !          1453:  * vn_writechk() and VOP_ACCESS() for two reasons.
        !          1454:  * 1 - You must check for MNT_EXRDONLY as well as MNT_RDONLY for the write case
        !          1455:  * 2 - The owner is to be given access irrespective of mode bits so that
        !          1456:  *     processes that chmod after opening a file don't break. I don't like
        !          1457:  *     this because it opens a security hole, but since the nfs server opens
        !          1458:  *     a security hole the size of a barn door anyhow, what the heck.
        !          1459:  */
        !          1460: nfsrv_access(vp, flags, cred, p)
        !          1461:        register struct vnode *vp;
        !          1462:        int flags;
        !          1463:        register struct ucred *cred;
        !          1464:        struct proc *p;
        !          1465: {
        !          1466:        struct vattr vattr;
        !          1467:        int error;
        !          1468:        if (flags & VWRITE) {
        !          1469:                /* Just vn_writechk() changed to check MNT_EXRDONLY */
        !          1470:                /*
        !          1471:                 * Disallow write attempts on read-only file systems;
        !          1472:                 * unless the file is a socket or a block or character
        !          1473:                 * device resident on the file system.
        !          1474:                 */
        !          1475:                if (vp->v_mount->mnt_flag & (MNT_RDONLY | MNT_EXRDONLY)) {
        !          1476:                        switch (vp->v_type) {
        !          1477:                        case VREG: case VDIR: case VLNK:
        !          1478:                                return (EROFS);
        !          1479:                        }
        !          1480:                }
        !          1481:                /*
        !          1482:                 * If there's shared text associated with
        !          1483:                 * the inode, try to free it up once.  If
        !          1484:                 * we fail, we can't allow writing.
        !          1485:                 */
        !          1486:                if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
        !          1487:                        return (ETXTBSY);
        !          1488:        }
        !          1489:        if (error = VOP_GETATTR(vp, &vattr, cred, p))
        !          1490:                return (error);
        !          1491:        if ((error = VOP_ACCESS(vp, flags, cred, p)) &&
        !          1492:            cred->cr_uid != vattr.va_uid)
        !          1493:                return (error);
        !          1494:        return (0);
        !          1495: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.