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

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

unix.superglobalmegacorp.com

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