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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1989 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Rick Macklem at The University of Guelph.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)nfs_subs.c  7.41 (Berkeley) 5/15/91
        !            37:  */
        !            38: 
        !            39: /*
        !            40:  * These functions support the macros and help fiddle mbuf chains for
        !            41:  * the nfs op functions. They do things like create the rpc header and
        !            42:  * copy data between mbuf chains and uio lists.
        !            43:  */
        !            44: #include "param.h"
        !            45: #include "proc.h"
        !            46: #include "filedesc.h"
        !            47: #include "systm.h"
        !            48: #include "kernel.h"
        !            49: #include "mount.h"
        !            50: #include "file.h"
        !            51: #include "vnode.h"
        !            52: #include "namei.h"
        !            53: #include "mbuf.h"
        !            54: #include "map.h"
        !            55: 
        !            56: #include "../ufs/quota.h"
        !            57: #include "../ufs/inode.h"
        !            58: 
        !            59: #include "rpcv2.h"
        !            60: #include "nfsv2.h"
        !            61: #include "nfsnode.h"
        !            62: #include "nfs.h"
        !            63: #include "nfsiom.h"
        !            64: #include "xdr_subs.h"
        !            65: #include "nfsm_subs.h"
        !            66: #include "nfscompress.h"
        !            67: 
        !            68: #define TRUE   1
        !            69: #define        FALSE   0
        !            70: 
        !            71: /*
        !            72:  * Data items converted to xdr at startup, since they are constant
        !            73:  * This is kinda hokey, but may save a little time doing byte swaps
        !            74:  */
        !            75: u_long nfs_procids[NFS_NPROCS];
        !            76: u_long nfs_xdrneg1;
        !            77: u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied,
        !            78:        rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
        !            79: u_long nfs_vers, nfs_prog, nfs_true, nfs_false;
        !            80: /* And other global data */
        !            81: static u_long *rpc_uidp = (u_long *)0;
        !            82: static u_long nfs_xid = 1;
        !            83: static char *rpc_unixauth;
        !            84: extern long hostid;
        !            85: enum vtype ntov_type[7] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON };
        !            86: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
        !            87: extern struct map nfsmap[NFS_MSIZ];
        !            88: extern struct nfsreq nfsreqh;
        !            89: 
        !            90: /* Function ret types */
        !            91: static char *nfs_unixauth();
        !            92: 
        !            93: /*
        !            94:  * Maximum number of groups passed through to NFS server.
        !            95:  * According to RFC1057 it should be 16.
        !            96:  * For release 3.X systems, the maximum value is 8.
        !            97:  * For some other servers, the maximum value is 10.
        !            98:  */
        !            99: int numgrps = 8;
        !           100: 
        !           101: /*
        !           102:  * Create the header for an rpc request packet
        !           103:  * The function nfs_unixauth() creates a unix style authorization string
        !           104:  * and returns a ptr to it.
        !           105:  * The hsiz is the size of the rest of the nfs request header.
        !           106:  * (just used to decide if a cluster is a good idea)
        !           107:  * nb: Note that the prog, vers and procid args are already in xdr byte order
        !           108:  */
        !           109: struct mbuf *nfsm_reqh(prog, vers, procid, cred, hsiz, bpos, mb, retxid)
        !           110:        u_long prog;
        !           111:        u_long vers;
        !           112:        u_long procid;
        !           113:        struct ucred *cred;
        !           114:        int hsiz;
        !           115:        caddr_t *bpos;
        !           116:        struct mbuf **mb;
        !           117:        u_long *retxid;
        !           118: {
        !           119:        register struct mbuf *mreq, *m;
        !           120:        register u_long *tl;
        !           121:        struct mbuf *m1;
        !           122:        char *ap;
        !           123:        int asiz, siz;
        !           124: 
        !           125:        NFSMGETHDR(mreq);
        !           126:        asiz = ((((cred->cr_ngroups - 1) > numgrps) ? numgrps :
        !           127:                  (cred->cr_ngroups - 1)) << 2);
        !           128: #ifdef FILLINHOST
        !           129:        asiz += nfsm_rndup(hostnamelen)+(9*NFSX_UNSIGNED);
        !           130: #else
        !           131:        asiz += 9*NFSX_UNSIGNED;
        !           132: #endif
        !           133: 
        !           134:        /* If we need a lot, alloc a cluster ?? */
        !           135:        if ((asiz+hsiz+RPC_SIZ) > MHLEN)
        !           136:                MCLGET(mreq, M_WAIT);
        !           137:        mreq->m_len = NFSMSIZ(mreq);
        !           138:        siz = mreq->m_len;
        !           139:        m1 = mreq;
        !           140:        /*
        !           141:         * Alloc enough mbufs
        !           142:         * We do it now to avoid all sleeps after the call to nfs_unixauth()
        !           143:         */
        !           144:        while ((asiz+RPC_SIZ) > siz) {
        !           145:                MGET(m, M_WAIT, MT_DATA);
        !           146:                m1->m_next = m;
        !           147:                m->m_len = MLEN;
        !           148:                siz += MLEN;
        !           149:                m1 = m;
        !           150:        }
        !           151:        tl = mtod(mreq, u_long *);
        !           152:        *tl++ = *retxid = txdr_unsigned(++nfs_xid);
        !           153:        *tl++ = rpc_call;
        !           154:        *tl++ = rpc_vers;
        !           155:        *tl++ = prog;
        !           156:        *tl++ = vers;
        !           157:        *tl++ = procid;
        !           158: 
        !           159:        /* Now we can call nfs_unixauth() and copy it in */
        !           160:        ap = nfs_unixauth(cred);
        !           161:        m = mreq;
        !           162:        siz = m->m_len-RPC_SIZ;
        !           163:        if (asiz <= siz) {
        !           164:                bcopy(ap, (caddr_t)tl, asiz);
        !           165:                m->m_len = asiz+RPC_SIZ;
        !           166:        } else {
        !           167:                bcopy(ap, (caddr_t)tl, siz);
        !           168:                ap += siz;
        !           169:                asiz -= siz;
        !           170:                while (asiz > 0) {
        !           171:                        siz = (asiz > MLEN) ? MLEN : asiz;
        !           172:                        m = m->m_next;
        !           173:                        bcopy(ap, mtod(m, caddr_t), siz);
        !           174:                        m->m_len = siz;
        !           175:                        asiz -= siz;
        !           176:                        ap += siz;
        !           177:                }
        !           178:        }
        !           179:        
        !           180:        /* Finally, return values */
        !           181:        *mb = m;
        !           182:        *bpos = mtod(m, caddr_t)+m->m_len;
        !           183:        return (mreq);
        !           184: }
        !           185: 
        !           186: /*
        !           187:  * copies mbuf chain to the uio scatter/gather list
        !           188:  */
        !           189: nfsm_mbuftouio(mrep, uiop, siz, dpos)
        !           190:        struct mbuf **mrep;
        !           191:        register struct uio *uiop;
        !           192:        int siz;
        !           193:        caddr_t *dpos;
        !           194: {
        !           195:        register char *mbufcp, *uiocp;
        !           196:        register int xfer, left, len;
        !           197:        register struct mbuf *mp;
        !           198:        long uiosiz, rem;
        !           199:        int error = 0;
        !           200: 
        !           201:        mp = *mrep;
        !           202:        mbufcp = *dpos;
        !           203:        len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
        !           204:        rem = nfsm_rndup(siz)-siz;
        !           205:        while (siz > 0) {
        !           206:                if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
        !           207:                        return (EFBIG);
        !           208:                left = uiop->uio_iov->iov_len;
        !           209:                uiocp = uiop->uio_iov->iov_base;
        !           210:                if (left > siz)
        !           211:                        left = siz;
        !           212:                uiosiz = left;
        !           213:                while (left > 0) {
        !           214:                        while (len == 0) {
        !           215:                                mp = mp->m_next;
        !           216:                                if (mp == NULL)
        !           217:                                        return (EBADRPC);
        !           218:                                mbufcp = mtod(mp, caddr_t);
        !           219:                                len = mp->m_len;
        !           220:                        }
        !           221:                        xfer = (left > len) ? len : left;
        !           222: #ifdef notdef
        !           223:                        /* Not Yet.. */
        !           224:                        if (uiop->uio_iov->iov_op != NULL)
        !           225:                                (*(uiop->uio_iov->iov_op))
        !           226:                                (mbufcp, uiocp, xfer);
        !           227:                        else
        !           228: #endif
        !           229:                        if (uiop->uio_segflg == UIO_SYSSPACE)
        !           230:                                bcopy(mbufcp, uiocp, xfer);
        !           231:                        else
        !           232:                                copyout(mbufcp, uiocp, xfer);
        !           233:                        left -= xfer;
        !           234:                        len -= xfer;
        !           235:                        mbufcp += xfer;
        !           236:                        uiocp += xfer;
        !           237:                        uiop->uio_offset += xfer;
        !           238:                        uiop->uio_resid -= xfer;
        !           239:                }
        !           240:                if (uiop->uio_iov->iov_len <= siz) {
        !           241:                        uiop->uio_iovcnt--;
        !           242:                        uiop->uio_iov++;
        !           243:                } else {
        !           244:                        uiop->uio_iov->iov_base += uiosiz;
        !           245:                        uiop->uio_iov->iov_len -= uiosiz;
        !           246:                }
        !           247:                siz -= uiosiz;
        !           248:        }
        !           249:        *dpos = mbufcp;
        !           250:        *mrep = mp;
        !           251:        if (rem > 0) {
        !           252:                if (len < rem)
        !           253:                        error = nfs_adv(mrep, dpos, rem, len);
        !           254:                else
        !           255:                        *dpos += rem;
        !           256:        }
        !           257:        return (error);
        !           258: }
        !           259: 
        !           260: /*
        !           261:  * copies a uio scatter/gather list to an mbuf chain...
        !           262:  */
        !           263: nfsm_uiotombuf(uiop, mq, siz, bpos)
        !           264:        register struct uio *uiop;
        !           265:        struct mbuf **mq;
        !           266:        int siz;
        !           267:        caddr_t *bpos;
        !           268: {
        !           269:        register char *uiocp;
        !           270:        register struct mbuf *mp, *mp2;
        !           271:        register int xfer, left, len;
        !           272:        int uiosiz, clflg, rem;
        !           273:        char *cp;
        !           274: 
        !           275:        if (siz > MLEN)         /* or should it >= MCLBYTES ?? */
        !           276:                clflg = 1;
        !           277:        else
        !           278:                clflg = 0;
        !           279:        rem = nfsm_rndup(siz)-siz;
        !           280:        mp2 = *mq;
        !           281:        while (siz > 0) {
        !           282:                if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
        !           283:                        return (EINVAL);
        !           284:                left = uiop->uio_iov->iov_len;
        !           285:                uiocp = uiop->uio_iov->iov_base;
        !           286:                if (left > siz)
        !           287:                        left = siz;
        !           288:                uiosiz = left;
        !           289:                while (left > 0) {
        !           290:                        MGET(mp, M_WAIT, MT_DATA);
        !           291:                        if (clflg)
        !           292:                                MCLGET(mp, M_WAIT);
        !           293:                        mp->m_len = NFSMSIZ(mp);
        !           294:                        mp2->m_next = mp;
        !           295:                        mp2 = mp;
        !           296:                        xfer = (left > mp->m_len) ? mp->m_len : left;
        !           297: #ifdef notdef
        !           298:                        /* Not Yet.. */
        !           299:                        if (uiop->uio_iov->iov_op != NULL)
        !           300:                                (*(uiop->uio_iov->iov_op))
        !           301:                                (uiocp, mtod(mp, caddr_t), xfer);
        !           302:                        else
        !           303: #endif
        !           304:                        if (uiop->uio_segflg == UIO_SYSSPACE)
        !           305:                                bcopy(uiocp, mtod(mp, caddr_t), xfer);
        !           306:                        else
        !           307:                                copyin(uiocp, mtod(mp, caddr_t), xfer);
        !           308:                        len = mp->m_len;
        !           309:                        mp->m_len = xfer;
        !           310:                        left -= xfer;
        !           311:                        uiocp += xfer;
        !           312:                        uiop->uio_offset += xfer;
        !           313:                        uiop->uio_resid -= xfer;
        !           314:                }
        !           315:                if (uiop->uio_iov->iov_len <= siz) {
        !           316:                        uiop->uio_iovcnt--;
        !           317:                        uiop->uio_iov++;
        !           318:                } else {
        !           319:                        uiop->uio_iov->iov_base += uiosiz;
        !           320:                        uiop->uio_iov->iov_len -= uiosiz;
        !           321:                }
        !           322:                siz -= uiosiz;
        !           323:        }
        !           324:        if (rem > 0) {
        !           325:                if (rem > (len-mp->m_len)) {
        !           326:                        MGET(mp, M_WAIT, MT_DATA);
        !           327:                        mp->m_len = 0;
        !           328:                        mp2->m_next = mp;
        !           329:                }
        !           330:                cp = mtod(mp, caddr_t)+mp->m_len;
        !           331:                for (left = 0; left < rem; left++)
        !           332:                        *cp++ = '\0';
        !           333:                mp->m_len += rem;
        !           334:                *bpos = cp;
        !           335:        } else
        !           336:                *bpos = mtod(mp, caddr_t)+mp->m_len;
        !           337:        *mq = mp;
        !           338:        return (0);
        !           339: }
        !           340: 
        !           341: /*
        !           342:  * Help break down an mbuf chain by setting the first siz bytes contiguous
        !           343:  * pointed to by returned val.
        !           344:  * If Updateflg == True we can overwrite the first part of the mbuf data
        !           345:  * This is used by the macros nfsm_disect and nfsm_disecton for tough
        !           346:  * cases. (The macros use the vars. dpos and dpos2)
        !           347:  */
        !           348: nfsm_disct(mdp, dposp, siz, left, updateflg, cp2)
        !           349:        struct mbuf **mdp;
        !           350:        caddr_t *dposp;
        !           351:        int siz;
        !           352:        int left;
        !           353:        int updateflg;
        !           354:        caddr_t *cp2;
        !           355: {
        !           356:        register struct mbuf *mp, *mp2;
        !           357:        register int siz2, xfer;
        !           358:        register caddr_t tl;
        !           359: 
        !           360:        mp = *mdp;
        !           361:        while (left == 0) {
        !           362:                *mdp = mp = mp->m_next;
        !           363:                if (mp == NULL)
        !           364:                        return (EBADRPC);
        !           365:                left = mp->m_len;
        !           366:                *dposp = mtod(mp, caddr_t);
        !           367:        }
        !           368:        if (left >= siz) {
        !           369:                *cp2 = *dposp;
        !           370:                *dposp += siz;
        !           371:        } else if (mp->m_next == NULL) {
        !           372:                return (EBADRPC);
        !           373:        } else if (siz > MHLEN) {
        !           374:                panic("nfs S too big");
        !           375:        } else {
        !           376:                /* Iff update, you can overwrite, else must alloc new mbuf */
        !           377:                if (updateflg) {
        !           378:                        NFSMINOFF(mp);
        !           379:                } else {
        !           380:                        MGET(mp2, M_WAIT, MT_DATA);
        !           381:                        mp2->m_next = mp->m_next;
        !           382:                        mp->m_next = mp2;
        !           383:                        mp->m_len -= left;
        !           384:                        mp = mp2;
        !           385:                }
        !           386:                *cp2 = tl = mtod(mp, caddr_t);
        !           387:                bcopy(*dposp, tl, left);                /* Copy what was left */
        !           388:                siz2 = siz-left;
        !           389:                tl += left;
        !           390:                mp2 = mp->m_next;
        !           391:                /* Loop around copying up the siz2 bytes */
        !           392:                while (siz2 > 0) {
        !           393:                        if (mp2 == NULL)
        !           394:                                return (EBADRPC);
        !           395:                        xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
        !           396:                        if (xfer > 0) {
        !           397:                                bcopy(mtod(mp2, caddr_t), tl, xfer);
        !           398:                                NFSMADV(mp2, xfer);
        !           399:                                mp2->m_len -= xfer;
        !           400:                                tl += xfer;
        !           401:                                siz2 -= xfer;
        !           402:                        }
        !           403:                        if (siz2 > 0)
        !           404:                                mp2 = mp2->m_next;
        !           405:                }
        !           406:                mp->m_len = siz;
        !           407:                *mdp = mp2;
        !           408:                *dposp = mtod(mp2, caddr_t);
        !           409:        }
        !           410:        return (0);
        !           411: }
        !           412: 
        !           413: /*
        !           414:  * Advance the position in the mbuf chain.
        !           415:  */
        !           416: nfs_adv(mdp, dposp, offs, left)
        !           417:        struct mbuf **mdp;
        !           418:        caddr_t *dposp;
        !           419:        int offs;
        !           420:        int left;
        !           421: {
        !           422:        register struct mbuf *m;
        !           423:        register int s;
        !           424: 
        !           425:        m = *mdp;
        !           426:        s = left;
        !           427:        while (s < offs) {
        !           428:                offs -= s;
        !           429:                m = m->m_next;
        !           430:                if (m == NULL)
        !           431:                        return (EBADRPC);
        !           432:                s = m->m_len;
        !           433:        }
        !           434:        *mdp = m;
        !           435:        *dposp = mtod(m, caddr_t)+offs;
        !           436:        return (0);
        !           437: }
        !           438: 
        !           439: /*
        !           440:  * Copy a string into mbufs for the hard cases...
        !           441:  */
        !           442: nfsm_strtmbuf(mb, bpos, cp, siz)
        !           443:        struct mbuf **mb;
        !           444:        char **bpos;
        !           445:        char *cp;
        !           446:        long siz;
        !           447: {
        !           448:        register struct mbuf *m1, *m2;
        !           449:        long left, xfer, len, tlen;
        !           450:        u_long *tl;
        !           451:        int putsize;
        !           452: 
        !           453:        putsize = 1;
        !           454:        m2 = *mb;
        !           455:        left = NFSMSIZ(m2)-m2->m_len;
        !           456:        if (left > 0) {
        !           457:                tl = ((u_long *)(*bpos));
        !           458:                *tl++ = txdr_unsigned(siz);
        !           459:                putsize = 0;
        !           460:                left -= NFSX_UNSIGNED;
        !           461:                m2->m_len += NFSX_UNSIGNED;
        !           462:                if (left > 0) {
        !           463:                        bcopy(cp, (caddr_t) tl, left);
        !           464:                        siz -= left;
        !           465:                        cp += left;
        !           466:                        m2->m_len += left;
        !           467:                        left = 0;
        !           468:                }
        !           469:        }
        !           470:        /* Loop arround adding mbufs */
        !           471:        while (siz > 0) {
        !           472:                MGET(m1, M_WAIT, MT_DATA);
        !           473:                if (siz > MLEN)
        !           474:                        MCLGET(m1, M_WAIT);
        !           475:                m1->m_len = NFSMSIZ(m1);
        !           476:                m2->m_next = m1;
        !           477:                m2 = m1;
        !           478:                tl = mtod(m1, u_long *);
        !           479:                tlen = 0;
        !           480:                if (putsize) {
        !           481:                        *tl++ = txdr_unsigned(siz);
        !           482:                        m1->m_len -= NFSX_UNSIGNED;
        !           483:                        tlen = NFSX_UNSIGNED;
        !           484:                        putsize = 0;
        !           485:                }
        !           486:                if (siz < m1->m_len) {
        !           487:                        len = nfsm_rndup(siz);
        !           488:                        xfer = siz;
        !           489:                        if (xfer < len)
        !           490:                                *(tl+(xfer>>2)) = 0;
        !           491:                } else {
        !           492:                        xfer = len = m1->m_len;
        !           493:                }
        !           494:                bcopy(cp, (caddr_t) tl, xfer);
        !           495:                m1->m_len = len+tlen;
        !           496:                siz -= xfer;
        !           497:                cp += xfer;
        !           498:        }
        !           499:        *mb = m1;
        !           500:        *bpos = mtod(m1, caddr_t)+m1->m_len;
        !           501:        return (0);
        !           502: }
        !           503: 
        !           504: /*
        !           505:  * Called once to initialize data structures...
        !           506:  */
        !           507: nfs_init()
        !           508: {
        !           509:        register int i;
        !           510: 
        !           511:        rpc_vers = txdr_unsigned(RPC_VER2);
        !           512:        rpc_call = txdr_unsigned(RPC_CALL);
        !           513:        rpc_reply = txdr_unsigned(RPC_REPLY);
        !           514:        rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
        !           515:        rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
        !           516:        rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
        !           517:        rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
        !           518:        nfs_vers = txdr_unsigned(NFS_VER2);
        !           519:        nfs_prog = txdr_unsigned(NFS_PROG);
        !           520:        nfs_true = txdr_unsigned(TRUE);
        !           521:        nfs_false = txdr_unsigned(FALSE);
        !           522:        /* Loop thru nfs procids */
        !           523:        for (i = 0; i < NFS_NPROCS; i++)
        !           524:                nfs_procids[i] = txdr_unsigned(i);
        !           525:        /* Ensure async daemons disabled */
        !           526:        for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
        !           527:                nfs_iodwant[i] = (struct proc *)0;
        !           528:        nfs_xdrneg1 = txdr_unsigned(-1);
        !           529:        nfs_nhinit();                   /* Init the nfsnode table */
        !           530:        nfsrv_initcache();              /* Init the server request cache */
        !           531:        rminit(nfsmap, (long)NFS_MAPREG, (long)1, "nfs mapreg", NFS_MSIZ);
        !           532: 
        !           533:        /*
        !           534:         * Initialize reply list and start timer
        !           535:         */
        !           536:        nfsreqh.r_prev = nfsreqh.r_next = &nfsreqh;
        !           537:        nfs_timer();
        !           538: }
        !           539: 
        !           540: /*
        !           541:  * Fill in the rest of the rpc_unixauth and return it
        !           542:  */
        !           543: static char *nfs_unixauth(cr)
        !           544:        register struct ucred *cr;
        !           545: {
        !           546:        register u_long *tl;
        !           547:        register int i;
        !           548:        int ngr;
        !           549: 
        !           550:        /* Maybe someday there should be a cache of AUTH_SHORT's */
        !           551:        if ((tl = rpc_uidp) == NULL) {
        !           552: #ifdef FILLINHOST
        !           553:                i = nfsm_rndup(hostnamelen)+(25*NFSX_UNSIGNED);
        !           554: #else
        !           555:                i = 25*NFSX_UNSIGNED;
        !           556: #endif
        !           557:                MALLOC(tl, u_long *, i, M_TEMP, M_WAITOK);
        !           558:                bzero((caddr_t)tl, i);
        !           559:                rpc_unixauth = (caddr_t)tl;
        !           560:                *tl++ = txdr_unsigned(RPCAUTH_UNIX);
        !           561:                tl++;   /* Fill in size later */
        !           562:                *tl++ = hostid;
        !           563: #ifdef FILLINHOST
        !           564:                *tl++ = txdr_unsigned(hostnamelen);
        !           565:                i = nfsm_rndup(hostnamelen);
        !           566:                bcopy(hostname, (caddr_t)tl, hostnamelen);
        !           567:                tl += (i>>2);
        !           568: #else
        !           569:                *tl++ = 0;
        !           570: #endif
        !           571:                rpc_uidp = tl;
        !           572:        }
        !           573:        *tl++ = txdr_unsigned(cr->cr_uid);
        !           574:        *tl++ = txdr_unsigned(cr->cr_groups[0]);
        !           575:        ngr = ((cr->cr_ngroups - 1) > numgrps) ? numgrps : (cr->cr_ngroups - 1);
        !           576:        *tl++ = txdr_unsigned(ngr);
        !           577:        for (i = 1; i <= ngr; i++)
        !           578:                *tl++ = txdr_unsigned(cr->cr_groups[i]);
        !           579:        /* And add the AUTH_NULL */
        !           580:        *tl++ = 0;
        !           581:        *tl = 0;
        !           582:        i = (((caddr_t)tl)-rpc_unixauth)-12;
        !           583:        tl = (u_long *)(rpc_unixauth+4);
        !           584:        *tl = txdr_unsigned(i);
        !           585:        return (rpc_unixauth);
        !           586: }
        !           587: 
        !           588: /*
        !           589:  * Attribute cache routines.
        !           590:  * nfs_loadattrcache() - loads or updates the cache contents from attributes
        !           591:  *     that are on the mbuf list
        !           592:  * nfs_getattrcache() - returns valid attributes if found in cache, returns
        !           593:  *     error otherwise
        !           594:  */
        !           595: 
        !           596: /*
        !           597:  * Load the attribute cache (that lives in the nfsnode entry) with
        !           598:  * the values on the mbuf list and
        !           599:  * Iff vap not NULL
        !           600:  *    copy the attributes to *vaper
        !           601:  */
        !           602: nfs_loadattrcache(vpp, mdp, dposp, vaper)
        !           603:        struct vnode **vpp;
        !           604:        struct mbuf **mdp;
        !           605:        caddr_t *dposp;
        !           606:        struct vattr *vaper;
        !           607: {
        !           608:        register struct vnode *vp = *vpp;
        !           609:        register struct vattr *vap;
        !           610:        register struct nfsv2_fattr *fp;
        !           611:        extern struct vnodeops spec_nfsv2nodeops;
        !           612:        register struct nfsnode *np;
        !           613:        register long t1;
        !           614:        caddr_t dpos, cp2;
        !           615:        int error = 0;
        !           616:        struct mbuf *md;
        !           617:        enum vtype type;
        !           618:        u_short mode;
        !           619:        long rdev;
        !           620:        struct timeval mtime;
        !           621:        struct vnode *nvp;
        !           622: 
        !           623:        md = *mdp;
        !           624:        dpos = *dposp;
        !           625:        t1 = (mtod(md, caddr_t)+md->m_len)-dpos;
        !           626:        if (error = nfsm_disct(&md, &dpos, NFSX_FATTR, t1, TRUE, &cp2))
        !           627:                return (error);
        !           628:        fp = (struct nfsv2_fattr *)cp2;
        !           629:        type = nfstov_type(fp->fa_type);
        !           630:        mode = fxdr_unsigned(u_short, fp->fa_mode);
        !           631:        if (type == VNON)
        !           632:                type = IFTOVT(mode);
        !           633:        rdev = fxdr_unsigned(long, fp->fa_rdev);
        !           634:        fxdr_time(&fp->fa_mtime, &mtime);
        !           635:        /*
        !           636:         * If v_type == VNON it is a new node, so fill in the v_type,
        !           637:         * n_mtime fields. Check to see if it represents a special 
        !           638:         * device, and if so, check for a possible alias. Once the
        !           639:         * correct vnode has been obtained, fill in the rest of the
        !           640:         * information.
        !           641:         */
        !           642:        np = VTONFS(vp);
        !           643:        if (vp->v_type == VNON) {
        !           644:                if (type == VCHR && rdev == 0xffffffff)
        !           645:                        vp->v_type = type = VFIFO;
        !           646:                else
        !           647:                        vp->v_type = type;
        !           648:                if (vp->v_type == VFIFO) {
        !           649: #ifdef FIFO
        !           650:                        extern struct vnodeops fifo_nfsv2nodeops;
        !           651:                        vp->v_op = &fifo_nfsv2nodeops;
        !           652: #else
        !           653:                        return (EOPNOTSUPP);
        !           654: #endif /* FIFO */
        !           655:                }
        !           656:                if (vp->v_type == VCHR || vp->v_type == VBLK) {
        !           657:                        vp->v_op = &spec_nfsv2nodeops;
        !           658:                        if (nvp = checkalias(vp, (dev_t)rdev, vp->v_mount)) {
        !           659:                                /*
        !           660:                                 * Reinitialize aliased node.
        !           661:                                 */
        !           662:                                np = VTONFS(nvp);
        !           663:                                np->n_vnode = nvp;
        !           664:                                np->n_flag = 0;
        !           665:                                nfs_lock(nvp);
        !           666:                                bcopy((caddr_t)&VTONFS(vp)->n_fh,
        !           667:                                        (caddr_t)&np->n_fh, NFSX_FH);
        !           668:                                insque(np, nfs_hash(&np->n_fh));
        !           669:                                np->n_attrstamp = 0;
        !           670:                                np->n_sillyrename = (struct sillyrename *)0;
        !           671:                                /*
        !           672:                                 * Discard unneeded vnode and update actual one
        !           673:                                 */
        !           674:                                vput(vp);
        !           675:                                *vpp = nvp;
        !           676:                        }
        !           677:                }
        !           678:                np->n_mtime = mtime.tv_sec;
        !           679:        }
        !           680:        vap = &np->n_vattr;
        !           681:        vap->va_type = type;
        !           682:        vap->va_mode = (mode & 07777);
        !           683:        vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
        !           684:        vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
        !           685:        vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
        !           686:        vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
        !           687:        if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size) {
        !           688:                np->n_size = vap->va_size;
        !           689:                vnode_pager_setsize(vp, np->n_size);
        !           690:        }
        !           691:        vap->va_size_rsv = 0;
        !           692:        vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
        !           693:        vap->va_rdev = (dev_t)rdev;
        !           694:        vap->va_bytes = fxdr_unsigned(long, fp->fa_blocks) * NFS_FABLKSIZE;
        !           695:        vap->va_bytes_rsv = 0;
        !           696:        vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
        !           697:        vap->va_fileid = fxdr_unsigned(long, fp->fa_fileid);
        !           698:        vap->va_atime.tv_sec = fxdr_unsigned(long, fp->fa_atime.tv_sec);
        !           699:        vap->va_atime.tv_usec = 0;
        !           700:        vap->va_flags = fxdr_unsigned(u_long, fp->fa_atime.tv_usec);
        !           701:        vap->va_mtime = mtime;
        !           702:        vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa_ctime.tv_sec);
        !           703:        vap->va_ctime.tv_usec = 0;
        !           704:        vap->va_gen = fxdr_unsigned(u_long, fp->fa_ctime.tv_usec);
        !           705:        np->n_attrstamp = time.tv_sec;
        !           706:        *dposp = dpos;
        !           707:        *mdp = md;
        !           708:        if (vaper != NULL) {
        !           709:                bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
        !           710:                if ((np->n_flag & NMODIFIED) && (np->n_size > vap->va_size))
        !           711:                        vaper->va_size = np->n_size;
        !           712:        }
        !           713:        return (0);
        !           714: }
        !           715: 
        !           716: /*
        !           717:  * Check the time stamp
        !           718:  * If the cache is valid, copy contents to *vap and return 0
        !           719:  * otherwise return an error
        !           720:  */
        !           721: nfs_getattrcache(vp, vap)
        !           722:        register struct vnode *vp;
        !           723:        struct vattr *vap;
        !           724: {
        !           725:        register struct nfsnode *np;
        !           726: 
        !           727:        np = VTONFS(vp);
        !           728:        if ((time.tv_sec-np->n_attrstamp) < NFS_ATTRTIMEO) {
        !           729:                nfsstats.attrcache_hits++;
        !           730:                bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
        !           731:                if ((np->n_flag & NMODIFIED) == 0) {
        !           732:                        np->n_size = vap->va_size;
        !           733:                        vnode_pager_setsize(vp, np->n_size);
        !           734:                } else if (np->n_size > vap->va_size)
        !           735:                        vap->va_size = np->n_size;
        !           736:                return (0);
        !           737:        } else {
        !           738:                nfsstats.attrcache_misses++;
        !           739:                return (ENOENT);
        !           740:        }
        !           741: }
        !           742: 
        !           743: /*
        !           744:  * Set up nameidata for a namei() call and do it
        !           745:  */
        !           746: nfs_namei(ndp, fhp, len, mdp, dposp, p)
        !           747:        register struct nameidata *ndp;
        !           748:        fhandle_t *fhp;
        !           749:        int len;
        !           750:        struct mbuf **mdp;
        !           751:        caddr_t *dposp;
        !           752:        struct proc *p;
        !           753: {
        !           754:        register int i, rem;
        !           755:        register struct mbuf *md;
        !           756:        register char *fromcp, *tocp;
        !           757:        struct vnode *dp;
        !           758:        int flag;
        !           759:        int error;
        !           760: 
        !           761:        flag = ndp->ni_nameiop & OPMASK;
        !           762:        MALLOC(ndp->ni_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
        !           763:        /*
        !           764:         * Copy the name from the mbuf list to ndp->ni_pnbuf
        !           765:         * and set the various ndp fields appropriately.
        !           766:         */
        !           767:        fromcp = *dposp;
        !           768:        tocp = ndp->ni_pnbuf;
        !           769:        md = *mdp;
        !           770:        rem = mtod(md, caddr_t) + md->m_len - fromcp;
        !           771:        ndp->ni_hash = 0;
        !           772:        for (i = 0; i < len; i++) {
        !           773:                while (rem == 0) {
        !           774:                        md = md->m_next;
        !           775:                        if (md == NULL) {
        !           776:                                error = EBADRPC;
        !           777:                                goto out;
        !           778:                        }
        !           779:                        fromcp = mtod(md, caddr_t);
        !           780:                        rem = md->m_len;
        !           781:                }
        !           782:                if (*fromcp == '\0' || *fromcp == '/') {
        !           783:                        error = EINVAL;
        !           784:                        goto out;
        !           785:                }
        !           786:                if (*fromcp & 0200)
        !           787:                        if ((*fromcp&0377) == ('/'|0200) || flag != DELETE) {
        !           788:                                error = EINVAL;
        !           789:                                goto out;
        !           790:                        }
        !           791:                ndp->ni_hash += (unsigned char)*fromcp;
        !           792:                *tocp++ = *fromcp++;
        !           793:                rem--;
        !           794:        }
        !           795:        *tocp = '\0';
        !           796:        *mdp = md;
        !           797:        *dposp = fromcp;
        !           798:        len = nfsm_rndup(len)-len;
        !           799:        if (len > 0) {
        !           800:                if (rem >= len)
        !           801:                        *dposp += len;
        !           802:                else if (error = nfs_adv(mdp, dposp, len, rem))
        !           803:                        goto out;
        !           804:        }
        !           805:        ndp->ni_pathlen = tocp - ndp->ni_pnbuf;
        !           806:        ndp->ni_ptr = ndp->ni_pnbuf;
        !           807:        /*
        !           808:         * Extract and set starting directory.
        !           809:         */
        !           810:        if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cred))
        !           811:                goto out;
        !           812:        if (dp->v_type != VDIR) {
        !           813:                vrele(dp);
        !           814:                error = ENOTDIR;
        !           815:                goto out;
        !           816:        }
        !           817:        ndp->ni_startdir = dp;
        !           818:        ndp->ni_nameiop |= (NOCROSSMOUNT | REMOTE);
        !           819:        /*
        !           820:         * And call lookup() to do the real work
        !           821:         */
        !           822:        if (error = lookup(ndp, p))
        !           823:                goto out;
        !           824:        /*
        !           825:         * Check for encountering a symbolic link
        !           826:         */
        !           827:        if (ndp->ni_more) {
        !           828:                if ((ndp->ni_nameiop & LOCKPARENT) && ndp->ni_pathlen == 1)
        !           829:                        vput(ndp->ni_dvp);
        !           830:                else
        !           831:                        vrele(ndp->ni_dvp);
        !           832:                vput(ndp->ni_vp);
        !           833:                ndp->ni_vp = NULL;
        !           834:                error = EINVAL;
        !           835:                goto out;
        !           836:        }
        !           837:        /*
        !           838:         * Check for saved name request
        !           839:         */
        !           840:        if (ndp->ni_nameiop & (SAVENAME | SAVESTART)) {
        !           841:                ndp->ni_nameiop |= HASBUF;
        !           842:                return (0);
        !           843:        }
        !           844: out:
        !           845:        FREE(ndp->ni_pnbuf, M_NAMEI);
        !           846:        return (error);
        !           847: }
        !           848: 
        !           849: /*
        !           850:  * A fiddled version of m_adj() that ensures null fill to a long
        !           851:  * boundary and only trims off the back end
        !           852:  */
        !           853: nfsm_adj(mp, len, nul)
        !           854:        struct mbuf *mp;
        !           855:        register int len;
        !           856:        int nul;
        !           857: {
        !           858:        register struct mbuf *m;
        !           859:        register int count, i;
        !           860:        register char *cp;
        !           861: 
        !           862:        /*
        !           863:         * Trim from tail.  Scan the mbuf chain,
        !           864:         * calculating its length and finding the last mbuf.
        !           865:         * If the adjustment only affects this mbuf, then just
        !           866:         * adjust and return.  Otherwise, rescan and truncate
        !           867:         * after the remaining size.
        !           868:         */
        !           869:        count = 0;
        !           870:        m = mp;
        !           871:        for (;;) {
        !           872:                count += m->m_len;
        !           873:                if (m->m_next == (struct mbuf *)0)
        !           874:                        break;
        !           875:                m = m->m_next;
        !           876:        }
        !           877:        if (m->m_len > len) {
        !           878:                m->m_len -= len;
        !           879:                if (nul > 0) {
        !           880:                        cp = mtod(m, caddr_t)+m->m_len-nul;
        !           881:                        for (i = 0; i < nul; i++)
        !           882:                                *cp++ = '\0';
        !           883:                }
        !           884:                return;
        !           885:        }
        !           886:        count -= len;
        !           887:        if (count < 0)
        !           888:                count = 0;
        !           889:        /*
        !           890:         * Correct length for chain is "count".
        !           891:         * Find the mbuf with last data, adjust its length,
        !           892:         * and toss data from remaining mbufs on chain.
        !           893:         */
        !           894:        for (m = mp; m; m = m->m_next) {
        !           895:                if (m->m_len >= count) {
        !           896:                        m->m_len = count;
        !           897:                        if (nul > 0) {
        !           898:                                cp = mtod(m, caddr_t)+m->m_len-nul;
        !           899:                                for (i = 0; i < nul; i++)
        !           900:                                        *cp++ = '\0';
        !           901:                        }
        !           902:                        break;
        !           903:                }
        !           904:                count -= m->m_len;
        !           905:        }
        !           906:        while (m = m->m_next)
        !           907:                m->m_len = 0;
        !           908: }
        !           909: 
        !           910: /*
        !           911:  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
        !           912:  *     - look up fsid in mount list (if not found ret error)
        !           913:  *     - check that it is exported
        !           914:  *     - get vp by calling VFS_FHTOVP() macro
        !           915:  *     - if not lockflag unlock it with VOP_UNLOCK()
        !           916:  *     - if cred->cr_uid == 0 set it to m_exroot
        !           917:  */
        !           918: nfsrv_fhtovp(fhp, lockflag, vpp, cred)
        !           919:        fhandle_t *fhp;
        !           920:        int lockflag;
        !           921:        struct vnode **vpp;
        !           922:        struct ucred *cred;
        !           923: {
        !           924:        register struct mount *mp;
        !           925: 
        !           926:        if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
        !           927:                return (ESTALE);
        !           928:        if ((mp->mnt_flag & MNT_EXPORTED) == 0)
        !           929:                return (EACCES);
        !           930:        if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
        !           931:                return (ESTALE);
        !           932:        if (cred->cr_uid == 0)
        !           933:                cred->cr_uid = mp->mnt_exroot;
        !           934:        if (!lockflag)
        !           935:                VOP_UNLOCK(*vpp);
        !           936:        return (0);
        !           937: }
        !           938: 
        !           939: /*
        !           940:  * These two functions implement nfs rpc compression.
        !           941:  * The algorithm is a trivial run length encoding of '\0' bytes. The high
        !           942:  * order nibble of hex "e" is or'd with the number of zeroes - 2 in four
        !           943:  * bits. (2 - 17 zeros) Any data byte with a high order nibble of hex "e"
        !           944:  * is byte stuffed.
        !           945:  * The compressed data is padded with 0x0 bytes to an even multiple of
        !           946:  * 4 bytes in length to avoid any weird long pointer alignments.
        !           947:  * If compression/uncompression is unsuccessful, the original mbuf list
        !           948:  * is returned.
        !           949:  * The first four bytes (the XID) are left uncompressed and the fifth
        !           950:  * byte is set to 0x1 for request and 0x2 for reply.
        !           951:  * An uncompressed RPC will always have the fifth byte == 0x0.
        !           952:  */
        !           953: struct mbuf *
        !           954: nfs_compress(m0)
        !           955:        struct mbuf *m0;
        !           956: {
        !           957:        register u_char ch, nextch;
        !           958:        register int i, rlelast;
        !           959:        register u_char *ip, *op;
        !           960:        register int ileft, oleft, noteof;
        !           961:        register struct mbuf *m, *om;
        !           962:        struct mbuf **mp, *retm;
        !           963:        int olen, clget;
        !           964: 
        !           965:        i = rlelast = 0;
        !           966:        noteof = 1;
        !           967:        m = m0;
        !           968:        if (m->m_len < 12)
        !           969:                return (m0);
        !           970:        if (m->m_pkthdr.len >= MINCLSIZE)
        !           971:                clget = 1;
        !           972:        else
        !           973:                clget = 0;
        !           974:        ileft = m->m_len - 9;
        !           975:        ip = mtod(m, u_char *);
        !           976:        MGETHDR(om, M_WAIT, MT_DATA);
        !           977:        if (clget)
        !           978:                MCLGET(om, M_WAIT);
        !           979:        retm = om;
        !           980:        mp = &om->m_next;
        !           981:        olen = om->m_len = 5;
        !           982:        oleft = M_TRAILINGSPACE(om);
        !           983:        op = mtod(om, u_char *);
        !           984:        *((u_long *)op) = *((u_long *)ip);
        !           985:        ip += 7;
        !           986:        op += 4;
        !           987:        *op++ = *ip++ + 1;
        !           988:        nextch = *ip++;
        !           989:        while (noteof) {
        !           990:                ch = nextch;
        !           991:                if (ileft == 0) {
        !           992:                        do {
        !           993:                                m = m->m_next;
        !           994:                        } while (m && m->m_len == 0);
        !           995:                        if (m) {
        !           996:                                ileft = m->m_len;
        !           997:                                ip = mtod(m, u_char *);
        !           998:                        } else {
        !           999:                                noteof = 0;
        !          1000:                                nextch = 0x1;
        !          1001:                                goto doit;
        !          1002:                        }
        !          1003:                }
        !          1004:                nextch = *ip++;
        !          1005:                ileft--;
        !          1006: doit:
        !          1007:                if (ch == '\0') {
        !          1008:                        if (++i == NFSC_MAX || nextch != '\0') {
        !          1009:                                if (i < 2) {
        !          1010:                                        nfscput('\0');
        !          1011:                                } else {
        !          1012:                                        if (rlelast == i) {
        !          1013:                                                nfscput('\0');
        !          1014:                                                i--;
        !          1015:                                        }
        !          1016:                                        if (NFSCRLE(i) == (nextch & 0xff)) {
        !          1017:                                                i--;
        !          1018:                                                if (i < 2) {
        !          1019:                                                        nfscput('\0');
        !          1020:                                                } else {
        !          1021:                                                        nfscput(NFSCRLE(i));
        !          1022:                                                }
        !          1023:                                                nfscput('\0');
        !          1024:                                                rlelast = 0;
        !          1025:                                        } else {
        !          1026:                                                nfscput(NFSCRLE(i));
        !          1027:                                                rlelast = i;
        !          1028:                                        }
        !          1029:                                }
        !          1030:                                i = 0;
        !          1031:                        }
        !          1032:                } else {
        !          1033:                        if ((ch & NFSCRL) == NFSCRL) {
        !          1034:                                nfscput(ch);
        !          1035:                        }
        !          1036:                        nfscput(ch);
        !          1037:                        i = rlelast = 0;
        !          1038:                }
        !          1039:        }
        !          1040:        if (olen < m0->m_pkthdr.len) {
        !          1041:                m_freem(m0);
        !          1042:                if (i = (olen & 0x3)) {
        !          1043:                        i = 4 - i;
        !          1044:                        while (i-- > 0) {
        !          1045:                                nfscput('\0');
        !          1046:                        }
        !          1047:                }
        !          1048:                retm->m_pkthdr.len = olen;
        !          1049:                retm->m_pkthdr.rcvif = (struct ifnet *)0;
        !          1050:                return (retm);
        !          1051:        } else {
        !          1052:                m_freem(retm);
        !          1053:                return (m0);
        !          1054:        }
        !          1055: }
        !          1056: 
        !          1057: struct mbuf *
        !          1058: nfs_uncompress(m0)
        !          1059:        struct mbuf *m0;
        !          1060: {
        !          1061:        register u_char cp, nextcp, *ip, *op;
        !          1062:        register struct mbuf *m, *om;
        !          1063:        struct mbuf *retm, **mp;
        !          1064:        int i, j, noteof, clget, ileft, oleft, olen;
        !          1065: 
        !          1066:        m = m0;
        !          1067:        i = 0;
        !          1068:        while (m && i < MINCLSIZE) {
        !          1069:                i += m->m_len;
        !          1070:                m = m->m_next;
        !          1071:        }
        !          1072:        if (i < 6)
        !          1073:                return (m0);
        !          1074:        if (i >= MINCLSIZE)
        !          1075:                clget = 1;
        !          1076:        else
        !          1077:                clget = 0;
        !          1078:        m = m0;
        !          1079:        MGET(om, M_WAIT, MT_DATA);
        !          1080:        if (clget)
        !          1081:                MCLGET(om, M_WAIT);
        !          1082:        olen = om->m_len = 8;
        !          1083:        oleft = M_TRAILINGSPACE(om);
        !          1084:        op = mtod(om, u_char *);
        !          1085:        retm = om;
        !          1086:        mp = &om->m_next;
        !          1087:        if (m->m_len >= 6) {
        !          1088:                ileft = m->m_len - 6;
        !          1089:                ip = mtod(m, u_char *);
        !          1090:                *((u_long *)op) = *((u_long *)ip);
        !          1091:                bzero(op + 4, 3);
        !          1092:                ip += 4;
        !          1093:                op += 7;
        !          1094:                if (*ip == '\0') {
        !          1095:                        m_freem(om);
        !          1096:                        return (m0);
        !          1097:                }
        !          1098:                *op++ = *ip++ - 1;
        !          1099:                cp = *ip++;
        !          1100:        } else {
        !          1101:                ileft = m->m_len;
        !          1102:                ip = mtod(m, u_char *);
        !          1103:                nfscget(*op++);
        !          1104:                nfscget(*op++);
        !          1105:                nfscget(*op++);
        !          1106:                nfscget(*op++);
        !          1107:                bzero(op, 3);
        !          1108:                op += 3;
        !          1109:                nfscget(*op);
        !          1110:                if (*op == '\0') {
        !          1111:                        m_freem(om);
        !          1112:                        return (m0);
        !          1113:                }
        !          1114:                (*op)--;
        !          1115:                op++;
        !          1116:                nfscget(cp);
        !          1117:        }
        !          1118:        noteof = 1;
        !          1119:        while (noteof) {
        !          1120:                if ((cp & NFSCRL) == NFSCRL) {
        !          1121:                        nfscget(nextcp);
        !          1122:                        if (cp == nextcp) {
        !          1123:                                nfscput(cp);
        !          1124:                                goto readit;
        !          1125:                        } else {
        !          1126:                                i = (cp & 0xf) + 2;
        !          1127:                                for (j = 0; j < i; j++) {
        !          1128:                                        nfscput('\0');
        !          1129:                                }
        !          1130:                                cp = nextcp;
        !          1131:                        }
        !          1132:                } else {
        !          1133:                        nfscput(cp);
        !          1134: readit:
        !          1135:                        nfscget(cp);
        !          1136:                }
        !          1137:        }
        !          1138:        m_freem(m0);
        !          1139:        if (i = (olen & 0x3))
        !          1140:                om->m_len -= i;
        !          1141:        return (retm);
        !          1142: }

unix.superglobalmegacorp.com

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