Annotation of 43BSDReno/sys/nfs/nfs_serv.c, revision 1.1.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.