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

unix.superglobalmegacorp.com

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