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

unix.superglobalmegacorp.com

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